Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2316bb1 authored by Yi-Yo Chiang's avatar Yi-Yo Chiang Committed by Gerrit Code Review
Browse files

Merge changes I71190c73,Ic1dd0eb9

* changes:
  Add ParseFstabFromString(), remove ReadFstabFromFp()
  Replace strtok_r() with C++-style android::base::Tokenize()
parents 5f77edac c811d139
Loading
Loading
Loading
Loading
+31 −71
Original line number Diff line number Diff line
@@ -530,67 +530,37 @@ bool EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {

}  // namespace

bool ReadFstabFromFp(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out) {
    ssize_t len;
    size_t alloc_len = 0;
    char *line = NULL;
    const char *delim = " \t";
    char *save_ptr, *p;
bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* fstab_out) {
    const int expected_fields = proc_mounts ? 4 : 5;

    Fstab fstab;

    while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
        /* if the last character is a newline, shorten the string by 1 byte */
        if (line[len - 1] == '\n') {
            line[len - 1] = '\0';
        }
    for (const auto& line : android::base::Split(fstab_str, "\n")) {
        auto fields = android::base::Tokenize(line, " \t");

        /* Skip any leading whitespace */
        p = line;
        while (isspace(*p)) {
            p++;
        }
        /* ignore comments or empty lines */
        if (*p == '#' || *p == '\0')
        // Ignore empty lines and comments.
        if (fields.empty() || android::base::StartsWith(fields.front(), '#')) {
            continue;

        FstabEntry entry;

        if (!(p = strtok_r(line, delim, &save_ptr))) {
            LERROR << "Error parsing mount source";
            goto err;
        }
        entry.blk_device = p;

        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
            LERROR << "Error parsing mount_point";
            goto err;
        }
        entry.mount_point = p;

        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
            LERROR << "Error parsing fs_type";
            goto err;
        if (fields.size() < expected_fields) {
            LERROR << "Error parsing fstab: expected " << expected_fields << " fields, got "
                   << fields.size();
            return false;
        }
        entry.fs_type = p;

        if (!(p = strtok_r(NULL, delim, &save_ptr))) {
            LERROR << "Error parsing mount_flags";
            goto err;
        }
        FstabEntry entry;
        auto it = fields.begin();

        ParseMountFlags(p, &entry);
        entry.blk_device = std::move(*it++);
        entry.mount_point = std::move(*it++);
        entry.fs_type = std::move(*it++);
        ParseMountFlags(std::move(*it++), &entry);

        // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
        if (proc_mounts) {
            p += strlen(p);
        } else if (!(p = strtok_r(NULL, delim, &save_ptr))) {
            LERROR << "Error parsing fs_mgr_options";
            goto err;
        }

        if (!ParseFsMgrFlags(p, &entry)) {
        if (!proc_mounts && !ParseFsMgrFlags(std::move(*it++), &entry)) {
            LERROR << "Error parsing fs_mgr_flags";
            goto err;
            return false;
        }

        if (entry.fs_mgr_flags.logical) {
@@ -602,21 +572,17 @@ bool ReadFstabFromFp(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out) {

    if (fstab.empty()) {
        LERROR << "No entries found in fstab";
        goto err;
        return false;
    }

    /* If an A/B partition, modify block device to be the real block device */
    if (!fs_mgr_update_for_slotselect(&fstab)) {
        LERROR << "Error updating for slotselect";
        goto err;
        return false;
    }
    free(line);

    *fstab_out = std::move(fstab);
    return true;

err:
    free(line);
    return false;
}

void TransformFstabForDsu(Fstab* fstab, const std::string& dsu_slot,
@@ -715,16 +681,18 @@ void EnableMandatoryFlags(Fstab* fstab) {
}

bool ReadFstabFromFile(const std::string& path, Fstab* fstab_out) {
    auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
    if (!fstab_file) {
        PERROR << __FUNCTION__ << "(): cannot open file: '" << path << "'";
    const bool is_proc_mounts = (path == "/proc/mounts");
    // /proc/mounts could be a symlink to /proc/self/mounts.
    const bool follow_symlinks = is_proc_mounts;

    std::string fstab_str;
    if (!android::base::ReadFileToString(path, &fstab_str, follow_symlinks)) {
        PERROR << __FUNCTION__ << "(): failed to read file: '" << path << "'";
        return false;
    }

    bool is_proc_mounts = path == "/proc/mounts";

    Fstab fstab;
    if (!ReadFstabFromFp(fstab_file.get(), is_proc_mounts, &fstab)) {
    if (!ParseFstabFromString(fstab_str, is_proc_mounts, &fstab)) {
        LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
        return false;
    }
@@ -771,15 +739,7 @@ bool ReadFstabFromDt(Fstab* fstab, bool verbose) {
        return false;
    }

    std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
        fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
                 fstab_buf.length(), "r"), fclose);
    if (!fstab_file) {
        if (verbose) PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
        return false;
    }

    if (!ReadFstabFromFp(fstab_file.get(), false, fstab)) {
    if (!ParseFstabFromString(fstab_buf, /* proc_mounts = */ false, fstab)) {
        if (verbose) {
            LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:" << std::endl
                   << fstab_buf;
+2 −6
Original line number Diff line number Diff line
@@ -19,12 +19,8 @@
#include <fstab/fstab.h>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
            fmemopen(static_cast<void*>(const_cast<uint8_t*>(data)), size, "r"), fclose);
    if (fstab_file == nullptr) {
        return 0;
    }
    std::string make_fstab_str(reinterpret_cast<const char*>(data), size);
    android::fs_mgr::Fstab fstab;
    android::fs_mgr::ReadFstabFromFp(fstab_file.get(), /* proc_mounts= */ false, &fstab);
    android::fs_mgr::ParseFstabFromString(make_fstab_str, /* proc_mounts = */ false, &fstab);
    return 0;
}
+2 −2
Original line number Diff line number Diff line
@@ -94,8 +94,8 @@ struct FstabEntry {
// Unless explicitly requested, a lookup on mount point should always return the 1st one.
using Fstab = std::vector<FstabEntry>;

// Exported for testability. Regular users should use ReadFstabFromfile().
bool ReadFstabFromFp(FILE* fstab_file, bool proc_mounts, Fstab* fstab_out);
// Exported for testability. Regular users should use ReadFstabFromFile().
bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* fstab_out);

bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
bool ReadFstabFromDt(Fstab* fstab, bool verbose = true);