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