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 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 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 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 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 */ 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 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 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 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 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 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. */ 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 811 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab) 812 { 813 return fstab->fs_mgr_flags & MF_VOLDMANAGED; 814 } 815 816 int fs_mgr_is_nonremovable(const struct fstab_rec *fstab) 817 { 818 return fstab->fs_mgr_flags & MF_NONREMOVABLE; 819 } 820 821 int fs_mgr_is_verified(const struct fstab_rec *fstab) 822 { 823 return fstab->fs_mgr_flags & MF_VERIFY; 824 } 825 826 int fs_mgr_is_avb(const struct fstab_rec *fstab) 827 { 828 return fstab->fs_mgr_flags & MF_AVB; 829 } 830 831 int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab) 832 { 833 return fstab->fs_mgr_flags & MF_VERIFYATBOOT; 834 } 835 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 841 int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab) 842 { 843 return fstab->fs_mgr_flags & MF_FILEENCRYPTION; 844 } 845 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 856 int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab) 857 { 858 return fstab->fs_mgr_flags & MF_FORCEFDEORFBE; 859 } 860 861 int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab) 862 { 863 return fstab->fs_mgr_flags & MF_NOEMULATEDSD; 864 } 865 866 int fs_mgr_is_notrim(struct fstab_rec *fstab) 867 { 868 return fstab->fs_mgr_flags & MF_NOTRIM; 869 } 870 871 int fs_mgr_is_formattable(struct fstab_rec *fstab) 872 { 873 return fstab->fs_mgr_flags & (MF_FORMATTABLE); 874 } 875 876 int fs_mgr_is_slotselect(struct fstab_rec *fstab) 877 { 878 return fstab->fs_mgr_flags & MF_SLOTSELECT; 879 } 880 881 int fs_mgr_is_nofail(struct fstab_rec *fstab) 882 { 883 return fstab->fs_mgr_flags & MF_NOFAIL; 884 } 885 886 int fs_mgr_is_latemount(struct fstab_rec *fstab) 887 { 888 return fstab->fs_mgr_flags & MF_LATEMOUNT; 889 } 890 891 int fs_mgr_is_quota(struct fstab_rec *fstab) 892 { 893 return fstab->fs_mgr_flags & MF_QUOTA; 894 } 895