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

Commit 47d34273 authored by Bowgo Tsai's avatar Bowgo Tsai
Browse files

fs_mgr: add fs_mgr_read_fstab_with_dt() API

With the early mount support in init, fstab entries of verified partitions
(e.g., /system, /vendor) will be moved into device tree in kernel image.

Those early mount fstab entries will be removed from the fstab file to
prevent duplicated and/or inconsistent settings.

This change adds a new function: fs_mgr_read_fstab_with_dt(), to return
the combined results from both places. It also removes
fs_mgr_read_fstab_file() from the public APIs and makes it as an
internal function.

Bug: 35811655
Test: early mount /vendor with dm-verity on sailfish

Change-Id: I2fba3614685bf9f852a789cda6f53013e2164e60
parent c1b3c8ef
Loading
Loading
Loading
Loading
+64 −47
Original line number Diff line number Diff line
@@ -404,7 +404,7 @@ bool is_dt_compatible() {
    return false;
}

struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
{
    int cnt, entries;
    ssize_t len;
@@ -540,6 +540,41 @@ err:
    return NULL;
}

/* merges fstab entries from both a and b, then returns the merged result.
 * note that the caller should only manage the return pointer without
 * doing further memory management for the two inputs, i.e. only need to
 * frees up memory of the return value without touching a and b. */
static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
{
    if (!a) return b;
    if (!b) return a;

    int total_entries = a->num_entries + b->num_entries;
    a->recs = static_cast<struct fstab_rec *>(realloc(
        a->recs, total_entries * (sizeof(struct fstab_rec))));
    if (!a->recs) {
        LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
        // If realloc() fails the original block is left untouched;
        // it is not freed or moved. So we have to free both a and b here.
        fs_mgr_free_fstab(a);
        fs_mgr_free_fstab(b);
        return nullptr;
    }

    for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
        // copy the pointer directly *without* malloc and memcpy
        a->recs[i] = b->recs[j];
    }

    // Frees up b, but don't free b->recs[X] to make sure they are
    // accessible through a->recs[X].
    free(b->fstab_filename);
    free(b);

    a->num_entries = total_entries;
    return a;
}

struct fstab *fs_mgr_read_fstab(const char *fstab_path)
{
    FILE *fstab_file;
@@ -547,13 +582,17 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)

    fstab_file = fopen(fstab_path, "r");
    if (!fstab_file) {
        LERROR << "Cannot open file " << fstab_path;
        return NULL;
        PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
        return nullptr;
    }

    fstab = fs_mgr_read_fstab_file(fstab_file);
    if (fstab) {
        fstab->fstab_filename = strdup(fstab_path);
    } else {
        LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
    }

    fclose(fstab_file);
    return fstab;
}
@@ -565,75 +604,53 @@ struct fstab *fs_mgr_read_fstab_dt()
{
    std::string fstab_buf = read_fstab_from_dt();
    if (fstab_buf.empty()) {
        return NULL;
        LERROR << __FUNCTION__ << "(): failed to read fstab from dt";
        return nullptr;
    }

    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) {
        return NULL;
        PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
        return nullptr;
    }

    struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get());
    if (!fstab) {
        LERROR << "failed to load fstab from kernel:" << std::endl << fstab_buf;
        LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
               << std::endl << fstab_buf;
    }

    return fstab;
}

/* combines fstab entries passed in from device tree with
 * the ones found from fstab_path
 */
struct fstab *fs_mgr_read_fstab_with_dt(const char *fstab_path)
{
    struct fstab *fstab_dt = fs_mgr_read_fstab_dt();
    struct fstab *fstab = fs_mgr_read_fstab(fstab_path);

    return in_place_merge(fstab_dt, fstab);
}

/* combines fstab entries passed in from device tree with
 * the ones found in /fstab.<hardware>
 */
struct fstab *fs_mgr_read_fstab_default()
{
    struct fstab *fstab = fs_mgr_read_fstab_dt();
    std::string hw;
    if (!fs_mgr_get_boot_config("hardware", &hw)) {
        // if we fail to find this, return whatever was found in device tree
        LWARNING << "failed to find device hardware name";
        return fstab;
    }
    std::string default_fstab;

    std::string default_fstab = FSTAB_PREFIX + hw;
    struct fstab *f = fs_mgr_read_fstab(default_fstab.c_str());
    if (!f) {
        // return what we have
        LWARNING << "failed to read fstab entries from '" << default_fstab << "'";
        return fstab;
    }

    // return the fstab read from file if device tree doesn't
    // have one, other wise merge the two
    if (!fstab) {
        fstab = f;
    if (fs_mgr_get_boot_config("hardware", &hw)) {
        default_fstab = FSTAB_PREFIX + hw;
    } else {
        int total_entries = fstab->num_entries + f->num_entries;
        fstab->recs = static_cast<struct fstab_rec *>(realloc(
                        fstab->recs, total_entries * (sizeof(struct fstab_rec))));
        if (!fstab->recs) {
            LERROR << "failed to allocate fstab recs";
            fstab->num_entries = 0;
            fs_mgr_free_fstab(fstab);
            return NULL;
        }

        for (int i = fstab->num_entries, j = 0; i < total_entries; i++, j++) {
            // copy everything and *not* strdup
            fstab->recs[i] = f->recs[j];
        LWARNING << __FUNCTION__ << "(): failed to find device hardware name";
    }

        // free up fstab entries read from file, but don't cleanup
        // the strings within f->recs[X] to make sure they are accessible
        // through fstab->recs[X].
        free(f->fstab_filename);
        free(f);

        fstab->num_entries = total_entries;
    }

    return fstab;
    return fs_mgr_read_fstab_with_dt(default_fstab.c_str());
}

void fs_mgr_free_fstab(struct fstab *fstab)
+1 −1
Original line number Diff line number Diff line
@@ -87,8 +87,8 @@ typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,

struct fstab *fs_mgr_read_fstab_default();
struct fstab *fs_mgr_read_fstab_dt();
struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file);
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
struct fstab *fs_mgr_read_fstab_with_dt(const char *fstab_path);
void fs_mgr_free_fstab(struct fstab *fstab);

#define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5