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