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