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