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
36const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android");
37
38struct 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
56struct flag_list {
57    const char *name;
58    unsigned int flag;
59};
60
61static 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
80static 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
120static 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
128static 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
135static 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
149static 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
162static 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
175static 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 */
193static 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
207static 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
383static 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/
394const 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
400static 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
412static 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
494bool 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
506static 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
638err:
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. */
649static 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 */
692static 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
725struct 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 */
750struct 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 */
780static 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 */
801struct 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
826void 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 */
857int 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 */
889struct 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
901std::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
918int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
919{
920    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
921}
922
923int fs_mgr_is_nonremovable(const struct fstab_rec *fstab)
924{
925    return fstab->fs_mgr_flags & MF_NONREMOVABLE;
926}
927
928int fs_mgr_is_verified(const struct fstab_rec *fstab)
929{
930    return fstab->fs_mgr_flags & MF_VERIFY;
931}
932
933int fs_mgr_is_avb(const struct fstab_rec *fstab)
934{
935    return fstab->fs_mgr_flags & MF_AVB;
936}
937
938int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
939{
940    return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
941}
942
943int fs_mgr_is_encryptable(const struct fstab_rec *fstab)
944{
945    return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE);
946}
947
948int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
949{
950    return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
951}
952
953void 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
963int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
964{
965    return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
966}
967
968int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab)
969{
970    return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
971}
972
973int fs_mgr_is_notrim(const struct fstab_rec* fstab) {
974    return fstab->fs_mgr_flags & MF_NOTRIM;
975}
976
977int fs_mgr_is_formattable(const struct fstab_rec* fstab) {
978    return fstab->fs_mgr_flags & (MF_FORMATTABLE);
979}
980
981int fs_mgr_is_slotselect(const struct fstab_rec* fstab) {
982    return fstab->fs_mgr_flags & MF_SLOTSELECT;
983}
984
985int fs_mgr_is_nofail(const struct fstab_rec* fstab) {
986    return fstab->fs_mgr_flags & MF_NOFAIL;
987}
988
989int fs_mgr_is_latemount(const struct fstab_rec* fstab) {
990    return fstab->fs_mgr_flags & MF_LATEMOUNT;
991}
992
993int fs_mgr_is_quota(const struct fstab_rec* fstab) {
994    return fstab->fs_mgr_flags & MF_QUOTA;
995}
996
997int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
998{
999    return fstab->fs_mgr_flags & MF_SYSFS;
1000}
1001