Home | History | Annotate | Download | only in fs_mgr
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <ctype.h>
     18 #include <dirent.h>
     19 #include <errno.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <sys/mount.h>
     24 #include <unistd.h>
     25 
     26 #include <android-base/file.h>
     27 #include <android-base/stringprintf.h>
     28 #include <android-base/strings.h>
     29 
     30 #include "fs_mgr_priv.h"
     31 
     32 const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
     33 
     34 struct fs_mgr_flag_values {
     35     char *key_loc;
     36     char* key_dir;
     37     char *verity_loc;
     38     long long part_length;
     39     char *label;
     40     int partnum;
     41     int swap_prio;
     42     int max_comp_streams;
     43     unsigned int zram_size;
     44     uint64_t reserved_size;
     45     unsigned int file_contents_mode;
     46     unsigned int file_names_mode;
     47     unsigned int erase_blk_size;
     48     unsigned int logical_blk_size;
     49 };
     50 
     51 struct flag_list {
     52     const char *name;
     53     unsigned int flag;
     54 };
     55 
     56 static struct flag_list mount_flags[] = {
     57     { "noatime",    MS_NOATIME },
     58     { "noexec",     MS_NOEXEC },
     59     { "nosuid",     MS_NOSUID },
     60     { "nodev",      MS_NODEV },
     61     { "nodiratime", MS_NODIRATIME },
     62     { "ro",         MS_RDONLY },
     63     { "rw",         0 },
     64     { "remount",    MS_REMOUNT },
     65     { "bind",       MS_BIND },
     66     { "rec",        MS_REC },
     67     { "unbindable", MS_UNBINDABLE },
     68     { "private",    MS_PRIVATE },
     69     { "slave",      MS_SLAVE },
     70     { "shared",     MS_SHARED },
     71     { "defaults",   0 },
     72     { 0,            0 },
     73 };
     74 
     75 static struct flag_list fs_mgr_flags[] = {
     76     {"wait", MF_WAIT},
     77     {"check", MF_CHECK},
     78     {"encryptable=", MF_CRYPT},
     79     {"forceencrypt=", MF_FORCECRYPT},
     80     {"fileencryption=", MF_FILEENCRYPTION},
     81     {"forcefdeorfbe=", MF_FORCEFDEORFBE},
     82     {"keydirectory=", MF_KEYDIRECTORY},
     83     {"nonremovable", MF_NONREMOVABLE},
     84     {"voldmanaged=", MF_VOLDMANAGED},
     85     {"length=", MF_LENGTH},
     86     {"recoveryonly", MF_RECOVERYONLY},
     87     {"swapprio=", MF_SWAPPRIO},
     88     {"zramsize=", MF_ZRAMSIZE},
     89     {"max_comp_streams=", MF_MAX_COMP_STREAMS},
     90     {"verifyatboot", MF_VERIFYATBOOT},
     91     {"verify", MF_VERIFY},
     92     {"avb", MF_AVB},
     93     {"noemulatedsd", MF_NOEMULATEDSD},
     94     {"notrim", MF_NOTRIM},
     95     {"formattable", MF_FORMATTABLE},
     96     {"slotselect", MF_SLOTSELECT},
     97     {"nofail", MF_NOFAIL},
     98     {"latemount", MF_LATEMOUNT},
     99     {"reservedsize=", MF_RESERVEDSIZE},
    100     {"quota", MF_QUOTA},
    101     {"eraseblk=", MF_ERASEBLKSIZE},
    102     {"logicalblk=", MF_LOGICALBLKSIZE},
    103     {"defaults", 0},
    104     {0, 0},
    105 };
    106 
    107 #define EM_AES_256_XTS  1
    108 #define EM_ICE          2
    109 #define EM_AES_256_CTS  3
    110 #define EM_AES_256_HEH  4
    111 
    112 static const struct flag_list file_contents_encryption_modes[] = {
    113     {"aes-256-xts", EM_AES_256_XTS},
    114     {"software", EM_AES_256_XTS}, /* alias for backwards compatibility */
    115     {"ice", EM_ICE}, /* hardware-specific inline cryptographic engine */
    116     {0, 0},
    117 };
    118 
    119 static const struct flag_list file_names_encryption_modes[] = {
    120     {"aes-256-cts", EM_AES_256_CTS},
    121     {"aes-256-heh", EM_AES_256_HEH},
    122     {0, 0},
    123 };
    124 
    125 static unsigned int encryption_mode_to_flag(const struct flag_list *list,
    126                                             const char *mode, const char *type)
    127 {
    128     const struct flag_list *j;
    129 
    130     for (j = list; j->name; ++j) {
    131         if (!strcmp(mode, j->name)) {
    132             return j->flag;
    133         }
    134     }
    135     LERROR << "Unknown " << type << " encryption mode: " << mode;
    136     return 0;
    137 }
    138 
    139 static const char *flag_to_encryption_mode(const struct flag_list *list,
    140                                            unsigned int flag)
    141 {
    142     const struct flag_list *j;
    143 
    144     for (j = list; j->name; ++j) {
    145         if (flag == j->flag) {
    146             return j->name;
    147         }
    148     }
    149     return nullptr;
    150 }
    151 
    152 static uint64_t calculate_zram_size(unsigned int percentage)
    153 {
    154     uint64_t total;
    155 
    156     total  = sysconf(_SC_PHYS_PAGES);
    157     total *= percentage;
    158     total /= 100;
    159 
    160     total *= sysconf(_SC_PAGESIZE);
    161 
    162     return total;
    163 }
    164 
    165 static uint64_t parse_size(const char *arg)
    166 {
    167     char *endptr;
    168     uint64_t size = strtoull(arg, &endptr, 10);
    169     if (*endptr == 'k' || *endptr == 'K')
    170         size *= 1024LL;
    171     else if (*endptr == 'm' || *endptr == 'M')
    172         size *= 1024LL * 1024LL;
    173     else if (*endptr == 'g' || *endptr == 'G')
    174         size *= 1024LL * 1024LL * 1024LL;
    175 
    176     return size;
    177 }
    178 
    179 /* fills 'dt_value' with the underlying device tree value string without
    180  * the trailing '\0'. Returns true if 'dt_value' has a valid string, 'false'
    181  * otherwise.
    182  */
    183 static bool read_dt_file(const std::string& file_name, std::string* dt_value)
    184 {
    185     if (android::base::ReadFileToString(file_name, dt_value)) {
    186         if (!dt_value->empty()) {
    187             // trim the trailing '\0' out, otherwise the comparison
    188             // will produce false-negatives.
    189             dt_value->resize(dt_value->size() - 1);
    190             return true;
    191         }
    192     }
    193 
    194     return false;
    195 }
    196 
    197 static int parse_flags(char *flags, struct flag_list *fl,
    198                        struct fs_mgr_flag_values *flag_vals,
    199                        char *fs_options, int fs_options_len)
    200 {
    201     int f = 0;
    202     int i;
    203     char *p;
    204     char *savep;
    205 
    206     /* initialize flag values.  If we find a relevant flag, we'll
    207      * update the value */
    208     if (flag_vals) {
    209         memset(flag_vals, 0, sizeof(*flag_vals));
    210         flag_vals->partnum = -1;
    211         flag_vals->swap_prio = -1; /* negative means it wasn't specified. */
    212     }
    213 
    214     /* initialize fs_options to the null string */
    215     if (fs_options && (fs_options_len > 0)) {
    216         fs_options[0] = '\0';
    217     }
    218 
    219     p = strtok_r(flags, ",", &savep);
    220     while (p) {
    221         /* Look for the flag "p" in the flag list "fl"
    222          * If not found, the loop exits with fl[i].name being null.
    223          */
    224         for (i = 0; fl[i].name; i++) {
    225             if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
    226                 f |= fl[i].flag;
    227                 if ((fl[i].flag == MF_CRYPT) && flag_vals) {
    228                     /* The encryptable flag is followed by an = and the
    229                      * location of the keys.  Get it and return it.
    230                      */
    231                     flag_vals->key_loc = strdup(strchr(p, '=') + 1);
    232                 } else if ((fl[i].flag == MF_VERIFY) && flag_vals) {
    233                     /* If the verify flag is followed by an = and the
    234                      * location for the verity state,  get it and return it.
    235                      */
    236                     char *start = strchr(p, '=');
    237                     if (start) {
    238                         flag_vals->verity_loc = strdup(start + 1);
    239                     }
    240                 } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) {
    241                     /* The forceencrypt flag is followed by an = and the
    242                      * location of the keys.  Get it and return it.
    243                      */
    244                     flag_vals->key_loc = strdup(strchr(p, '=') + 1);
    245                 } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) {
    246                     /* The forcefdeorfbe flag is followed by an = and the
    247                      * location of the keys.  Get it and return it.
    248                      */
    249                     flag_vals->key_loc = strdup(strchr(p, '=') + 1);
    250                     flag_vals->file_contents_mode = EM_AES_256_XTS;
    251                     flag_vals->file_names_mode = EM_AES_256_CTS;
    252                 } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
    253                     /* The fileencryption flag is followed by an = and
    254                      * the mode of contents encryption, then optionally a
    255                      * : and the mode of filenames encryption (defaults
    256                      * to aes-256-cts).  Get it and return it.
    257                      */
    258                     char *mode = strchr(p, '=') + 1;
    259                     char *colon = strchr(mode, ':');
    260                     if (colon) {
    261                         *colon = '\0';
    262                     }
    263                     flag_vals->file_contents_mode =
    264                         encryption_mode_to_flag(file_contents_encryption_modes,
    265                                                 mode, "file contents");
    266                     if (colon) {
    267                         flag_vals->file_names_mode =
    268                             encryption_mode_to_flag(file_names_encryption_modes,
    269                                                     colon + 1, "file names");
    270                     } else {
    271                         flag_vals->file_names_mode = EM_AES_256_CTS;
    272                     }
    273                 } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) {
    274                     /* The metadata flag is followed by an = and the
    275                      * directory for the keys.  Get it and return it.
    276                      */
    277                     flag_vals->key_dir = strdup(strchr(p, '=') + 1);
    278                 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
    279                     /* The length flag is followed by an = and the
    280                      * size of the partition.  Get it and return it.
    281                      */
    282                     flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
    283                 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
    284                     /* The voldmanaged flag is followed by an = and the
    285                      * label, a colon and the partition number or the
    286                      * word "auto", e.g.
    287                      *   voldmanaged=sdcard:3
    288                      * Get and return them.
    289                      */
    290                     char *label_start;
    291                     char *label_end;
    292                     char *part_start;
    293 
    294                     label_start = strchr(p, '=') + 1;
    295                     label_end = strchr(p, ':');
    296                     if (label_end) {
    297                         flag_vals->label = strndup(label_start,
    298                                                    (int) (label_end - label_start));
    299                         part_start = strchr(p, ':') + 1;
    300                         if (!strcmp(part_start, "auto")) {
    301                             flag_vals->partnum = -1;
    302                         } else {
    303                             flag_vals->partnum = strtol(part_start, NULL, 0);
    304                         }
    305                     } else {
    306                         LERROR << "Warning: voldmanaged= flag malformed";
    307                     }
    308                 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
    309                     flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
    310                 } else if ((fl[i].flag == MF_MAX_COMP_STREAMS) && flag_vals) {
    311                     flag_vals->max_comp_streams = strtoll(strchr(p, '=') + 1, NULL, 0);
    312                 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
    313                     int is_percent = !!strrchr(p, '%');
    314                     unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0);
    315                     if (is_percent)
    316                         flag_vals->zram_size = calculate_zram_size(val);
    317                     else
    318                         flag_vals->zram_size = val;
    319                 } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
    320                     /* The reserved flag is followed by an = and the
    321                      * reserved size of the partition.  Get it and return it.
    322                      */
    323                     flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
    324                 } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) {
    325                     /* The erase block size flag is followed by an = and the flash
    326                      * erase block size. Get it, check that it is a power of 2 and
    327                      * at least 4096, and return it.
    328                      */
    329                     unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
    330                     if (val >= 4096 && (val & (val - 1)) == 0)
    331                         flag_vals->erase_blk_size = val;
    332                 } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) {
    333                     /* The logical block size flag is followed by an = and the flash
    334                      * logical block size. Get it, check that it is a power of 2 and
    335                      * at least 4096, and return it.
    336                      */
    337                     unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
    338                     if (val >= 4096 && (val & (val - 1)) == 0)
    339                         flag_vals->logical_blk_size = val;
    340                 }
    341                 break;
    342             }
    343         }
    344 
    345         if (!fl[i].name) {
    346             if (fs_options) {
    347                 /* It's not a known flag, so it must be a filesystem specific
    348                  * option.  Add it to fs_options if it was passed in.
    349                  */
    350                 strlcat(fs_options, p, fs_options_len);
    351                 strlcat(fs_options, ",", fs_options_len);
    352             } else {
    353                 /* fs_options was not passed in, so if the flag is unknown
    354                  * it's an error.
    355                  */
    356                 LERROR << "Warning: unknown flag " << p;
    357             }
    358         }
    359         p = strtok_r(NULL, ",", &savep);
    360     }
    361 
    362     if (fs_options && fs_options[0]) {
    363         /* remove the last trailing comma from the list of options */
    364         fs_options[strlen(fs_options) - 1] = '\0';
    365     }
    366 
    367     return f;
    368 }
    369 
    370 static std::string init_android_dt_dir() {
    371     std::string android_dt_dir;
    372     // The platform may specify a custom Android DT path in kernel cmdline
    373     if (!fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) {
    374         // Fall back to the standard procfs-based path
    375         android_dt_dir = kDefaultAndroidDtDir;
    376     }
    377     return android_dt_dir;
    378 }
    379 
    380 // FIXME: The same logic is duplicated in system/core/init/
    381 const std::string& get_android_dt_dir() {
    382     // Set once and saves time for subsequent calls to this function
    383     static const std::string kAndroidDtDir = init_android_dt_dir();
    384     return kAndroidDtDir;
    385 }
    386 
    387 static bool is_dt_fstab_compatible() {
    388     std::string dt_value;
    389     std::string file_name = get_android_dt_dir() + "/fstab/compatible";
    390     if (read_dt_file(file_name, &dt_value)) {
    391         if (dt_value == "android,fstab") {
    392             return true;
    393         }
    394     }
    395 
    396     return false;
    397 }
    398 
    399 static std::string read_fstab_from_dt() {
    400     std::string fstab;
    401     if (!is_dt_compatible() || !is_dt_fstab_compatible()) {
    402         return fstab;
    403     }
    404 
    405     std::string fstabdir_name = get_android_dt_dir() + "/fstab";
    406     std::unique_ptr<DIR, int (*)(DIR*)> fstabdir(opendir(fstabdir_name.c_str()), closedir);
    407     if (!fstabdir) return fstab;
    408 
    409     dirent* dp;
    410     while ((dp = readdir(fstabdir.get())) != NULL) {
    411         // skip over name, compatible and .
    412         if (dp->d_type != DT_DIR || dp->d_name[0] == '.') continue;
    413 
    414         // create <dev> <mnt_point>  <type>  <mnt_flags>  <fsmgr_flags>\n
    415         std::vector<std::string> fstab_entry;
    416         std::string file_name;
    417         std::string value;
    418         // skip a partition entry if the status property is present and not set to ok
    419         file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
    420         if (read_dt_file(file_name, &value)) {
    421             if (value != "okay" && value != "ok") {
    422                 LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
    423                 continue;
    424             }
    425         }
    426 
    427         file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
    428         if (!read_dt_file(file_name, &value)) {
    429             LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
    430             fstab.clear();
    431             break;
    432         }
    433         fstab_entry.push_back(value);
    434         fstab_entry.push_back(android::base::StringPrintf("/%s", dp->d_name));
    435 
    436         file_name = android::base::StringPrintf("%s/%s/type", fstabdir_name.c_str(), dp->d_name);
    437         if (!read_dt_file(file_name, &value)) {
    438             LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
    439             fstab.clear();
    440             break;
    441         }
    442         fstab_entry.push_back(value);
    443 
    444         file_name = android::base::StringPrintf("%s/%s/mnt_flags", fstabdir_name.c_str(), dp->d_name);
    445         if (!read_dt_file(file_name, &value)) {
    446             LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
    447             fstab.clear();
    448             break;
    449         }
    450         fstab_entry.push_back(value);
    451 
    452         file_name = android::base::StringPrintf("%s/%s/fsmgr_flags", fstabdir_name.c_str(), dp->d_name);
    453         if (!read_dt_file(file_name, &value)) {
    454             LERROR << "dt_fstab: Failed to find type for partition " << dp->d_name;
    455             fstab.clear();
    456             break;
    457         }
    458         fstab_entry.push_back(value);
    459 
    460         fstab += android::base::Join(fstab_entry, " ");
    461         fstab += '\n';
    462     }
    463 
    464     return fstab;
    465 }
    466 
    467 bool is_dt_compatible() {
    468     std::string file_name = get_android_dt_dir() + "/compatible";
    469     std::string dt_value;
    470     if (read_dt_file(file_name, &dt_value)) {
    471         if (dt_value == "android,firmware") {
    472             return true;
    473         }
    474     }
    475 
    476     return false;
    477 }
    478 
    479 static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
    480 {
    481     int cnt, entries;
    482     ssize_t len;
    483     size_t alloc_len = 0;
    484     char *line = NULL;
    485     const char *delim = " \t";
    486     char *save_ptr, *p;
    487     struct fstab *fstab = NULL;
    488     struct fs_mgr_flag_values flag_vals;
    489 #define FS_OPTIONS_LEN 1024
    490     char tmp_fs_options[FS_OPTIONS_LEN];
    491 
    492     entries = 0;
    493     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
    494         /* if the last character is a newline, shorten the string by 1 byte */
    495         if (line[len - 1] == '\n') {
    496             line[len - 1] = '\0';
    497         }
    498         /* Skip any leading whitespace */
    499         p = line;
    500         while (isspace(*p)) {
    501             p++;
    502         }
    503         /* ignore comments or empty lines */
    504         if (*p == '#' || *p == '\0')
    505             continue;
    506         entries++;
    507     }
    508 
    509     if (!entries) {
    510         LERROR << "No entries found in fstab";
    511         goto err;
    512     }
    513 
    514     /* Allocate and init the fstab structure */
    515     fstab = static_cast<struct fstab *>(calloc(1, sizeof(struct fstab)));
    516     fstab->num_entries = entries;
    517     fstab->recs = static_cast<struct fstab_rec *>(
    518         calloc(fstab->num_entries, sizeof(struct fstab_rec)));
    519 
    520     fseek(fstab_file, 0, SEEK_SET);
    521 
    522     cnt = 0;
    523     while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
    524         /* if the last character is a newline, shorten the string by 1 byte */
    525         if (line[len - 1] == '\n') {
    526             line[len - 1] = '\0';
    527         }
    528 
    529         /* Skip any leading whitespace */
    530         p = line;
    531         while (isspace(*p)) {
    532             p++;
    533         }
    534         /* ignore comments or empty lines */
    535         if (*p == '#' || *p == '\0')
    536             continue;
    537 
    538         /* If a non-comment entry is greater than the size we allocated, give an
    539          * error and quit.  This can happen in the unlikely case the file changes
    540          * between the two reads.
    541          */
    542         if (cnt >= entries) {
    543             LERROR << "Tried to process more entries than counted";
    544             break;
    545         }
    546 
    547         if (!(p = strtok_r(line, delim, &save_ptr))) {
    548             LERROR << "Error parsing mount source";
    549             goto err;
    550         }
    551         fstab->recs[cnt].blk_device = strdup(p);
    552 
    553         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
    554             LERROR << "Error parsing mount_point";
    555             goto err;
    556         }
    557         fstab->recs[cnt].mount_point = strdup(p);
    558 
    559         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
    560             LERROR << "Error parsing fs_type";
    561             goto err;
    562         }
    563         fstab->recs[cnt].fs_type = strdup(p);
    564 
    565         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
    566             LERROR << "Error parsing mount_flags";
    567             goto err;
    568         }
    569         tmp_fs_options[0] = '\0';
    570         fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL,
    571                                        tmp_fs_options, FS_OPTIONS_LEN);
    572 
    573         /* fs_options are optional */
    574         if (tmp_fs_options[0]) {
    575             fstab->recs[cnt].fs_options = strdup(tmp_fs_options);
    576         } else {
    577             fstab->recs[cnt].fs_options = NULL;
    578         }
    579 
    580         if (!(p = strtok_r(NULL, delim, &save_ptr))) {
    581             LERROR << "Error parsing fs_mgr_options";
    582             goto err;
    583         }
    584         fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
    585                                                     &flag_vals, NULL, 0);
    586         fstab->recs[cnt].key_loc = flag_vals.key_loc;
    587         fstab->recs[cnt].key_dir = flag_vals.key_dir;
    588         fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
    589         fstab->recs[cnt].length = flag_vals.part_length;
    590         fstab->recs[cnt].label = flag_vals.label;
    591         fstab->recs[cnt].partnum = flag_vals.partnum;
    592         fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
    593         fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
    594         fstab->recs[cnt].zram_size = flag_vals.zram_size;
    595         fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
    596         fstab->recs[cnt].file_contents_mode = flag_vals.file_contents_mode;
    597         fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
    598         fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
    599         fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
    600         cnt++;
    601     }
    602     /* If an A/B partition, modify block device to be the real block device */
    603     if (!fs_mgr_update_for_slotselect(fstab)) {
    604         LERROR << "Error updating for slotselect";
    605         goto err;
    606     }
    607     free(line);
    608     return fstab;
    609 
    610 err:
    611     free(line);
    612     if (fstab)
    613         fs_mgr_free_fstab(fstab);
    614     return NULL;
    615 }
    616 
    617 /* merges fstab entries from both a and b, then returns the merged result.
    618  * note that the caller should only manage the return pointer without
    619  * doing further memory management for the two inputs, i.e. only need to
    620  * frees up memory of the return value without touching a and b. */
    621 static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
    622 {
    623     if (!a) return b;
    624     if (!b) return a;
    625 
    626     int total_entries = a->num_entries + b->num_entries;
    627     a->recs = static_cast<struct fstab_rec *>(realloc(
    628         a->recs, total_entries * (sizeof(struct fstab_rec))));
    629     if (!a->recs) {
    630         LERROR << __FUNCTION__ << "(): failed to allocate fstab recs";
    631         // If realloc() fails the original block is left untouched;
    632         // it is not freed or moved. So we have to free both a and b here.
    633         fs_mgr_free_fstab(a);
    634         fs_mgr_free_fstab(b);
    635         return nullptr;
    636     }
    637 
    638     for (int i = a->num_entries, j = 0; i < total_entries; i++, j++) {
    639         // copy the pointer directly *without* malloc and memcpy
    640         a->recs[i] = b->recs[j];
    641     }
    642 
    643     // Frees up b, but don't free b->recs[X] to make sure they are
    644     // accessible through a->recs[X].
    645     free(b->fstab_filename);
    646     free(b);
    647 
    648     a->num_entries = total_entries;
    649     return a;
    650 }
    651 
    652 struct fstab *fs_mgr_read_fstab(const char *fstab_path)
    653 {
    654     FILE *fstab_file;
    655     struct fstab *fstab;
    656 
    657     fstab_file = fopen(fstab_path, "r");
    658     if (!fstab_file) {
    659         PERROR << __FUNCTION__<< "(): cannot open file: '" << fstab_path << "'";
    660         return nullptr;
    661     }
    662 
    663     fstab = fs_mgr_read_fstab_file(fstab_file);
    664     if (fstab) {
    665         fstab->fstab_filename = strdup(fstab_path);
    666     } else {
    667         LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
    668     }
    669 
    670     fclose(fstab_file);
    671     return fstab;
    672 }
    673 
    674 /* Returns fstab entries parsed from the device tree if they
    675  * exist
    676  */
    677 struct fstab *fs_mgr_read_fstab_dt()
    678 {
    679     std::string fstab_buf = read_fstab_from_dt();
    680     if (fstab_buf.empty()) {
    681         LINFO << __FUNCTION__ << "(): failed to read fstab from dt";
    682         return nullptr;
    683     }
    684 
    685     std::unique_ptr<FILE, decltype(&fclose)> fstab_file(
    686         fmemopen(static_cast<void*>(const_cast<char*>(fstab_buf.c_str())),
    687                  fstab_buf.length(), "r"), fclose);
    688     if (!fstab_file) {
    689         PERROR << __FUNCTION__ << "(): failed to create a file stream for fstab dt";
    690         return nullptr;
    691     }
    692 
    693     struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get());
    694     if (!fstab) {
    695         LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
    696                << std::endl << fstab_buf;
    697     }
    698 
    699     return fstab;
    700 }
    701 
    702 /*
    703  * tries to load default fstab.<hardware> file from /odm/etc, /vendor/etc
    704  * or /. loads the first one found and also combines fstab entries passed
    705  * in from device tree.
    706  */
    707 struct fstab *fs_mgr_read_fstab_default()
    708 {
    709     std::string hw;
    710     std::string default_fstab;
    711 
    712     // Use different fstab paths for normal boot and recovery boot, respectively
    713     if (access("/sbin/recovery", F_OK) == 0) {
    714         default_fstab = "/etc/recovery.fstab";
    715     } else if (fs_mgr_get_boot_config("hardware", &hw)) {  // normal boot
    716         for (const char *prefix : {"/odm/etc/fstab.","/vendor/etc/fstab.", "/fstab."}) {
    717             default_fstab = prefix + hw;
    718             if (access(default_fstab.c_str(), F_OK) == 0) break;
    719         }
    720     } else {
    721         LWARNING << __FUNCTION__ << "(): failed to find device hardware name";
    722     }
    723 
    724     // combines fstab entries passed in from device tree with
    725     // the ones found from default_fstab file
    726     struct fstab *fstab_dt = fs_mgr_read_fstab_dt();
    727     struct fstab *fstab = fs_mgr_read_fstab(default_fstab.c_str());
    728 
    729     return in_place_merge(fstab_dt, fstab);
    730 }
    731 
    732 void fs_mgr_free_fstab(struct fstab *fstab)
    733 {
    734     int i;
    735 
    736     if (!fstab) {
    737         return;
    738     }
    739 
    740     for (i = 0; i < fstab->num_entries; i++) {
    741         /* Free the pointers return by strdup(3) */
    742         free(fstab->recs[i].blk_device);
    743         free(fstab->recs[i].mount_point);
    744         free(fstab->recs[i].fs_type);
    745         free(fstab->recs[i].fs_options);
    746         free(fstab->recs[i].key_loc);
    747         free(fstab->recs[i].key_dir);
    748         free(fstab->recs[i].label);
    749     }
    750 
    751     /* Free the fstab_recs array created by calloc(3) */
    752     free(fstab->recs);
    753 
    754     /* Free the fstab filename */
    755     free(fstab->fstab_filename);
    756 
    757     /* Free fstab */
    758     free(fstab);
    759 }
    760 
    761 /* Add an entry to the fstab, and return 0 on success or -1 on error */
    762 int fs_mgr_add_entry(struct fstab *fstab,
    763                      const char *mount_point, const char *fs_type,
    764                      const char *blk_device)
    765 {
    766     struct fstab_rec *new_fstab_recs;
    767     int n = fstab->num_entries;
    768 
    769     new_fstab_recs = (struct fstab_rec *)
    770                      realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1));
    771 
    772     if (!new_fstab_recs) {
    773         return -1;
    774     }
    775 
    776     /* A new entry was added, so initialize it */
    777      memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec));
    778      new_fstab_recs[n].mount_point = strdup(mount_point);
    779      new_fstab_recs[n].fs_type = strdup(fs_type);
    780      new_fstab_recs[n].blk_device = strdup(blk_device);
    781      new_fstab_recs[n].length = 0;
    782 
    783      /* Update the fstab struct */
    784      fstab->recs = new_fstab_recs;
    785      fstab->num_entries++;
    786 
    787      return 0;
    788 }
    789 
    790 /*
    791  * Returns the 1st matching fstab_rec that follows the start_rec.
    792  * start_rec is the result of a previous search or NULL.
    793  */
    794 struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path)
    795 {
    796     int i;
    797     if (!fstab) {
    798         return NULL;
    799     }
    800 
    801     if (start_rec) {
    802         for (i = 0; i < fstab->num_entries; i++) {
    803             if (&fstab->recs[i] == start_rec) {
    804                 i++;
    805                 break;
    806             }
    807         }
    808     } else {
    809         i = 0;
    810     }
    811     for (; i < fstab->num_entries; i++) {
    812         int len = strlen(fstab->recs[i].mount_point);
    813         if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
    814             (path[len] == '\0' || path[len] == '/')) {
    815             return &fstab->recs[i];
    816         }
    817     }
    818     return NULL;
    819 }
    820 
    821 /*
    822  * Returns the 1st matching mount point.
    823  * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after()
    824  * and give the fstab_rec from the previous search.
    825  */
    826 struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
    827 {
    828     return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
    829 }
    830 
    831 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
    832 {
    833     return fstab->fs_mgr_flags & MF_VOLDMANAGED;
    834 }
    835 
    836 int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
    837 {
    838     return fstab->fs_mgr_flags & MF_NONREMOVABLE;
    839 }
    840 
    841 int fs_mgr_is_verified(const struct fstab_rec *fstab)
    842 {
    843     return fstab->fs_mgr_flags & MF_VERIFY;
    844 }
    845 
    846 int fs_mgr_is_avb(const struct fstab_rec *fstab)
    847 {
    848     return fstab->fs_mgr_flags & MF_AVB;
    849 }
    850 
    851 int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
    852 {
    853     return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
    854 }
    855 
    856 int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
    857 {
    858     return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
    859 }
    860 
    861 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
    862 {
    863     return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
    864 }
    865 
    866 void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab,
    867                                       const char **contents_mode_ret,
    868                                       const char **filenames_mode_ret)
    869 {
    870     *contents_mode_ret = flag_to_encryption_mode(file_contents_encryption_modes,
    871                                                  fstab->file_contents_mode);
    872     *filenames_mode_ret = flag_to_encryption_mode(file_names_encryption_modes,
    873                                                   fstab->file_names_mode);
    874 }
    875 
    876 int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
    877 {
    878     return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
    879 }
    880 
    881 int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
    882 {
    883     return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
    884 }
    885 
    886 int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
    887     return fstab->fs_mgr_flags & MF_NOTRIM;
    888 }
    889 
    890 int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
    891     return fstab->fs_mgr_flags & (MF_FORMATTABLE);
    892 }
    893 
    894 int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
    895     return fstab->fs_mgr_flags & MF_SLOTSELECT;
    896 }
    897 
    898 int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
    899     return fstab->fs_mgr_flags & MF_NOFAIL;
    900 }
    901 
    902 int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
    903     return fstab->fs_mgr_flags & MF_LATEMOUNT;
    904 }
    905 
    906 int fs_mgr_is_quota(const struct fstab_rec* fstab) {
    907     return fstab->fs_mgr_flags & MF_QUOTA;
    908 }
    909