fs_mgr.c revision 4eaf905858c6a1d7cf0639bed3e8de3bd7987646
1/* 2 * Copyright (C) 2012 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 <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <unistd.h> 21#include <fcntl.h> 22#include <ctype.h> 23#include <sys/mount.h> 24#include <sys/stat.h> 25#include <errno.h> 26#include <sys/types.h> 27#include <sys/wait.h> 28#include <libgen.h> 29#include <time.h> 30#include <sys/swap.h> 31/* XXX These need to be obtained from kernel headers. See b/9336527 */ 32#define SWAP_FLAG_PREFER 0x8000 33#define SWAP_FLAG_PRIO_MASK 0x7fff 34#define SWAP_FLAG_PRIO_SHIFT 0 35#define SWAP_FLAG_DISCARD 0x10000 36 37#include <linux/loop.h> 38#include <private/android_filesystem_config.h> 39#include <cutils/partition_utils.h> 40#include <cutils/properties.h> 41#include <logwrap/logwrap.h> 42 43#include "mincrypt/rsa.h" 44#include "mincrypt/sha.h" 45#include "mincrypt/sha256.h" 46 47#include "fs_mgr_priv.h" 48#include "fs_mgr_priv_verity.h" 49 50#define KEY_LOC_PROP "ro.crypto.keyfile.userdata" 51#define KEY_IN_FOOTER "footer" 52 53#define E2FSCK_BIN "/system/bin/e2fsck" 54#define MKSWAP_BIN "/system/bin/mkswap" 55 56#define FSCK_LOG_FILE "/dev/fscklogs/log" 57 58#define ZRAM_CONF_DEV "/sys/block/zram0/disksize" 59 60#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 61 62struct flag_list { 63 const char *name; 64 unsigned flag; 65}; 66 67static struct flag_list mount_flags[] = { 68 { "noatime", MS_NOATIME }, 69 { "noexec", MS_NOEXEC }, 70 { "nosuid", MS_NOSUID }, 71 { "nodev", MS_NODEV }, 72 { "nodiratime", MS_NODIRATIME }, 73 { "ro", MS_RDONLY }, 74 { "rw", 0 }, 75 { "remount", MS_REMOUNT }, 76 { "bind", MS_BIND }, 77 { "rec", MS_REC }, 78 { "unbindable", MS_UNBINDABLE }, 79 { "private", MS_PRIVATE }, 80 { "slave", MS_SLAVE }, 81 { "shared", MS_SHARED }, 82 { "defaults", 0 }, 83 { 0, 0 }, 84}; 85 86static struct flag_list fs_mgr_flags[] = { 87 { "wait", MF_WAIT }, 88 { "check", MF_CHECK }, 89 { "encryptable=",MF_CRYPT }, 90 { "nonremovable",MF_NONREMOVABLE }, 91 { "voldmanaged=",MF_VOLDMANAGED}, 92 { "length=", MF_LENGTH }, 93 { "recoveryonly",MF_RECOVERYONLY }, 94 { "swapprio=", MF_SWAPPRIO }, 95 { "zramsize=", MF_ZRAMSIZE }, 96 { "verify", MF_VERIFY }, 97 { "noemulatedsd", MF_NOEMULATEDSD }, 98 { "defaults", 0 }, 99 { 0, 0 }, 100}; 101 102struct fs_mgr_flag_values { 103 char *key_loc; 104 long long part_length; 105 char *label; 106 int partnum; 107 int swap_prio; 108 unsigned int zram_size; 109}; 110 111/* 112 * gettime() - returns the time in seconds of the system's monotonic clock or 113 * zero on error. 114 */ 115static time_t gettime(void) 116{ 117 struct timespec ts; 118 int ret; 119 120 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 121 if (ret < 0) { 122 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 123 return 0; 124 } 125 126 return ts.tv_sec; 127} 128 129static int wait_for_file(const char *filename, int timeout) 130{ 131 struct stat info; 132 time_t timeout_time = gettime() + timeout; 133 int ret = -1; 134 135 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 136 usleep(10000); 137 138 return ret; 139} 140 141static int parse_flags(char *flags, struct flag_list *fl, 142 struct fs_mgr_flag_values *flag_vals, 143 char *fs_options, int fs_options_len) 144{ 145 int f = 0; 146 int i; 147 char *p; 148 char *savep; 149 150 /* initialize flag values. If we find a relevant flag, we'll 151 * update the value */ 152 if (flag_vals) { 153 memset(flag_vals, 0, sizeof(*flag_vals)); 154 flag_vals->partnum = -1; 155 flag_vals->swap_prio = -1; /* negative means it wasn't specified. */ 156 } 157 158 /* initialize fs_options to the null string */ 159 if (fs_options && (fs_options_len > 0)) { 160 fs_options[0] = '\0'; 161 } 162 163 p = strtok_r(flags, ",", &savep); 164 while (p) { 165 /* Look for the flag "p" in the flag list "fl" 166 * If not found, the loop exits with fl[i].name being null. 167 */ 168 for (i = 0; fl[i].name; i++) { 169 if (!strncmp(p, fl[i].name, strlen(fl[i].name))) { 170 f |= fl[i].flag; 171 if ((fl[i].flag == MF_CRYPT) && flag_vals) { 172 /* The encryptable flag is followed by an = and the 173 * location of the keys. Get it and return it. 174 */ 175 flag_vals->key_loc = strdup(strchr(p, '=') + 1); 176 } else if ((fl[i].flag == MF_LENGTH) && flag_vals) { 177 /* The length flag is followed by an = and the 178 * size of the partition. Get it and return it. 179 */ 180 flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0); 181 } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) { 182 /* The voldmanaged flag is followed by an = and the 183 * label, a colon and the partition number or the 184 * word "auto", e.g. 185 * voldmanaged=sdcard:3 186 * Get and return them. 187 */ 188 char *label_start; 189 char *label_end; 190 char *part_start; 191 192 label_start = strchr(p, '=') + 1; 193 label_end = strchr(p, ':'); 194 if (label_end) { 195 flag_vals->label = strndup(label_start, 196 (int) (label_end - label_start)); 197 part_start = strchr(p, ':') + 1; 198 if (!strcmp(part_start, "auto")) { 199 flag_vals->partnum = -1; 200 } else { 201 flag_vals->partnum = strtol(part_start, NULL, 0); 202 } 203 } else { 204 ERROR("Warning: voldmanaged= flag malformed\n"); 205 } 206 } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) { 207 flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0); 208 } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) { 209 flag_vals->zram_size = strtoll(strchr(p, '=') + 1, NULL, 0); 210 } 211 break; 212 } 213 } 214 215 if (!fl[i].name) { 216 if (fs_options) { 217 /* It's not a known flag, so it must be a filesystem specific 218 * option. Add it to fs_options if it was passed in. 219 */ 220 strlcat(fs_options, p, fs_options_len); 221 strlcat(fs_options, ",", fs_options_len); 222 } else { 223 /* fs_options was not passed in, so if the flag is unknown 224 * it's an error. 225 */ 226 ERROR("Warning: unknown flag %s\n", p); 227 } 228 } 229 p = strtok_r(NULL, ",", &savep); 230 } 231 232out: 233 if (fs_options && fs_options[0]) { 234 /* remove the last trailing comma from the list of options */ 235 fs_options[strlen(fs_options) - 1] = '\0'; 236 } 237 238 return f; 239} 240 241/* Read a line of text till the next newline character. 242 * If no newline is found before the buffer is full, continue reading till a new line is seen, 243 * then return an empty buffer. This effectively ignores lines that are too long. 244 * On EOF, return null. 245 */ 246static char *fs_getline(char *buf, int size, FILE *file) 247{ 248 int cnt = 0; 249 int eof = 0; 250 int eol = 0; 251 int c; 252 253 if (size < 1) { 254 return NULL; 255 } 256 257 while (cnt < (size - 1)) { 258 c = getc(file); 259 if (c == EOF) { 260 eof = 1; 261 break; 262 } 263 264 *(buf + cnt) = c; 265 cnt++; 266 267 if (c == '\n') { 268 eol = 1; 269 break; 270 } 271 } 272 273 /* Null terminate what we've read */ 274 *(buf + cnt) = '\0'; 275 276 if (eof) { 277 if (cnt) { 278 return buf; 279 } else { 280 return NULL; 281 } 282 } else if (eol) { 283 return buf; 284 } else { 285 /* The line is too long. Read till a newline or EOF. 286 * If EOF, return null, if newline, return an empty buffer. 287 */ 288 while(1) { 289 c = getc(file); 290 if (c == EOF) { 291 return NULL; 292 } else if (c == '\n') { 293 *buf = '\0'; 294 return buf; 295 } 296 } 297 } 298} 299 300struct fstab *fs_mgr_read_fstab(const char *fstab_path) 301{ 302 FILE *fstab_file; 303 int cnt, entries; 304 int len; 305 char line[256]; 306 const char *delim = " \t"; 307 char *save_ptr, *p; 308 struct fstab *fstab; 309 struct fstab_rec *recs; 310 struct fs_mgr_flag_values flag_vals; 311#define FS_OPTIONS_LEN 1024 312 char tmp_fs_options[FS_OPTIONS_LEN]; 313 314 fstab_file = fopen(fstab_path, "r"); 315 if (!fstab_file) { 316 ERROR("Cannot open file %s\n", fstab_path); 317 return 0; 318 } 319 320 entries = 0; 321 while (fs_getline(line, sizeof(line), fstab_file)) { 322 /* if the last character is a newline, shorten the string by 1 byte */ 323 len = strlen(line); 324 if (line[len - 1] == '\n') { 325 line[len - 1] = '\0'; 326 } 327 /* Skip any leading whitespace */ 328 p = line; 329 while (isspace(*p)) { 330 p++; 331 } 332 /* ignore comments or empty lines */ 333 if (*p == '#' || *p == '\0') 334 continue; 335 entries++; 336 } 337 338 if (!entries) { 339 ERROR("No entries found in fstab\n"); 340 return 0; 341 } 342 343 /* Allocate and init the fstab structure */ 344 fstab = calloc(1, sizeof(struct fstab)); 345 fstab->num_entries = entries; 346 fstab->fstab_filename = strdup(fstab_path); 347 fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec)); 348 349 fseek(fstab_file, 0, SEEK_SET); 350 351 cnt = 0; 352 while (fs_getline(line, sizeof(line), fstab_file)) { 353 /* if the last character is a newline, shorten the string by 1 byte */ 354 len = strlen(line); 355 if (line[len - 1] == '\n') { 356 line[len - 1] = '\0'; 357 } 358 359 /* Skip any leading whitespace */ 360 p = line; 361 while (isspace(*p)) { 362 p++; 363 } 364 /* ignore comments or empty lines */ 365 if (*p == '#' || *p == '\0') 366 continue; 367 368 /* If a non-comment entry is greater than the size we allocated, give an 369 * error and quit. This can happen in the unlikely case the file changes 370 * between the two reads. 371 */ 372 if (cnt >= entries) { 373 ERROR("Tried to process more entries than counted\n"); 374 break; 375 } 376 377 if (!(p = strtok_r(line, delim, &save_ptr))) { 378 ERROR("Error parsing mount source\n"); 379 return 0; 380 } 381 fstab->recs[cnt].blk_device = strdup(p); 382 383 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 384 ERROR("Error parsing mount_point\n"); 385 return 0; 386 } 387 fstab->recs[cnt].mount_point = strdup(p); 388 389 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 390 ERROR("Error parsing fs_type\n"); 391 return 0; 392 } 393 fstab->recs[cnt].fs_type = strdup(p); 394 395 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 396 ERROR("Error parsing mount_flags\n"); 397 return 0; 398 } 399 tmp_fs_options[0] = '\0'; 400 fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, 401 tmp_fs_options, FS_OPTIONS_LEN); 402 403 /* fs_options are optional */ 404 if (tmp_fs_options[0]) { 405 fstab->recs[cnt].fs_options = strdup(tmp_fs_options); 406 } else { 407 fstab->recs[cnt].fs_options = NULL; 408 } 409 410 if (!(p = strtok_r(NULL, delim, &save_ptr))) { 411 ERROR("Error parsing fs_mgr_options\n"); 412 return 0; 413 } 414 fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, 415 &flag_vals, NULL, 0); 416 fstab->recs[cnt].key_loc = flag_vals.key_loc; 417 fstab->recs[cnt].length = flag_vals.part_length; 418 fstab->recs[cnt].label = flag_vals.label; 419 fstab->recs[cnt].partnum = flag_vals.partnum; 420 fstab->recs[cnt].swap_prio = flag_vals.swap_prio; 421 fstab->recs[cnt].zram_size = flag_vals.zram_size; 422 cnt++; 423 } 424 fclose(fstab_file); 425 426 return fstab; 427} 428 429void fs_mgr_free_fstab(struct fstab *fstab) 430{ 431 int i; 432 433 for (i = 0; i < fstab->num_entries; i++) { 434 /* Free the pointers return by strdup(3) */ 435 free(fstab->recs[i].blk_device); 436 free(fstab->recs[i].mount_point); 437 free(fstab->recs[i].fs_type); 438 free(fstab->recs[i].fs_options); 439 free(fstab->recs[i].key_loc); 440 free(fstab->recs[i].label); 441 i++; 442 } 443 444 /* Free the fstab_recs array created by calloc(3) */ 445 free(fstab->recs); 446 447 /* Free the fstab filename */ 448 free(fstab->fstab_filename); 449 450 /* Free fstab */ 451 free(fstab); 452} 453 454static void check_fs(char *blk_device, char *fs_type, char *target) 455{ 456 int status; 457 int ret; 458 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; 459 char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; 460 char *e2fsck_argv[] = { 461 E2FSCK_BIN, 462 "-y", 463 blk_device 464 }; 465 466 /* Check for the types of filesystems we know how to check */ 467 if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { 468 /* 469 * First try to mount and unmount the filesystem. We do this because 470 * the kernel is more efficient than e2fsck in running the journal and 471 * processing orphaned inodes, and on at least one device with a 472 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes 473 * to do what the kernel does in about a second. 474 * 475 * After mounting and unmounting the filesystem, run e2fsck, and if an 476 * error is recorded in the filesystem superblock, e2fsck will do a full 477 * check. Otherwise, it does nothing. If the kernel cannot mount the 478 * filesytsem due to an error, e2fsck is still run to do a full check 479 * fix the filesystem. 480 */ 481 ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); 482 if (!ret) { 483 umount(target); 484 } 485 486 INFO("Running %s on %s\n", E2FSCK_BIN, blk_device); 487 488 ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, 489 &status, true, LOG_KLOG | LOG_FILE, 490 true, FSCK_LOG_FILE); 491 492 if (ret < 0) { 493 /* No need to check for error in fork, we can't really handle it now */ 494 ERROR("Failed trying to run %s\n", E2FSCK_BIN); 495 } 496 } 497 498 return; 499} 500 501static void remove_trailing_slashes(char *n) 502{ 503 int len; 504 505 len = strlen(n) - 1; 506 while ((*(n + len) == '/') && len) { 507 *(n + len) = '\0'; 508 len--; 509 } 510} 511 512/* 513 * Mark the given block device as read-only, using the BLKROSET ioctl. 514 * Return 0 on success, and -1 on error. 515 */ 516static void fs_set_blk_ro(const char *blockdev) 517{ 518 int fd; 519 int ON = 1; 520 521 fd = open(blockdev, O_RDONLY); 522 if (fd < 0) { 523 // should never happen 524 return; 525 } 526 527 ioctl(fd, BLKROSET, &ON); 528 close(fd); 529} 530 531/* 532 * __mount(): wrapper around the mount() system call which also 533 * sets the underlying block device to read-only if the mount is read-only. 534 * See "man 2 mount" for return values. 535 */ 536static int __mount(const char *source, const char *target, 537 const char *filesystemtype, unsigned long mountflags, 538 const void *data) 539{ 540 int ret = mount(source, target, filesystemtype, mountflags, data); 541 542 if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { 543 fs_set_blk_ro(source); 544 } 545 546 return ret; 547} 548 549static int fs_match(char *in1, char *in2) 550{ 551 char *n1; 552 char *n2; 553 int ret; 554 555 n1 = strdup(in1); 556 n2 = strdup(in2); 557 558 remove_trailing_slashes(n1); 559 remove_trailing_slashes(n2); 560 561 ret = !strcmp(n1, n2); 562 563 free(n1); 564 free(n2); 565 566 return ret; 567} 568 569int fs_mgr_mount_all(struct fstab *fstab) 570{ 571 int i = 0; 572 int encrypted = 0; 573 int ret = -1; 574 int mret; 575 576 if (!fstab) { 577 return ret; 578 } 579 580 for (i = 0; i < fstab->num_entries; i++) { 581 /* Don't mount entries that are managed by vold */ 582 if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { 583 continue; 584 } 585 586 /* Skip swap and raw partition entries such as boot, recovery, etc */ 587 if (!strcmp(fstab->recs[i].fs_type, "swap") || 588 !strcmp(fstab->recs[i].fs_type, "emmc") || 589 !strcmp(fstab->recs[i].fs_type, "mtd")) { 590 continue; 591 } 592 593 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 594 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 595 } 596 597 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 598 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, 599 fstab->recs[i].mount_point); 600 } 601 602 if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { 603 if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { 604 ERROR("Could not set up verified partition, skipping!"); 605 continue; 606 } 607 } 608 609 mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, 610 fstab->recs[i].fs_type, fstab->recs[i].flags, 611 fstab->recs[i].fs_options); 612 613 if (!mret) { 614 /* Success! Go get the next one */ 615 continue; 616 } 617 618 /* mount(2) returned an error, check if it's encrypted and deal with it */ 619 if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) && 620 !partition_wiped(fstab->recs[i].blk_device)) { 621 /* Need to mount a tmpfs at this mountpoint for now, and set 622 * properties that vold will query later for decrypting 623 */ 624 if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", 625 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { 626 ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", 627 fstab->recs[i].mount_point); 628 goto out; 629 } 630 encrypted = 1; 631 } else { 632 ERROR("Cannot mount filesystem on %s at %s\n", 633 fstab->recs[i].blk_device, fstab->recs[i].mount_point); 634 goto out; 635 } 636 } 637 638 if (encrypted) { 639 ret = 1; 640 } else { 641 ret = 0; 642 } 643 644out: 645 return ret; 646} 647 648/* If tmp_mount_point is non-null, mount the filesystem there. This is for the 649 * tmp mount we do to check the user password 650 */ 651int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, 652 char *tmp_mount_point) 653{ 654 int i = 0; 655 int ret = -1; 656 char *m; 657 658 if (!fstab) { 659 return ret; 660 } 661 662 for (i = 0; i < fstab->num_entries; i++) { 663 if (!fs_match(fstab->recs[i].mount_point, n_name)) { 664 continue; 665 } 666 667 /* We found our match */ 668 /* If this swap or a raw partition, report an error */ 669 if (!strcmp(fstab->recs[i].fs_type, "swap") || 670 !strcmp(fstab->recs[i].fs_type, "emmc") || 671 !strcmp(fstab->recs[i].fs_type, "mtd")) { 672 ERROR("Cannot mount filesystem of type %s on %s\n", 673 fstab->recs[i].fs_type, n_blk_device); 674 goto out; 675 } 676 677 /* First check the filesystem if requested */ 678 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 679 wait_for_file(n_blk_device, WAIT_TIMEOUT); 680 } 681 682 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 683 check_fs(n_blk_device, fstab->recs[i].fs_type, 684 fstab->recs[i].mount_point); 685 } 686 687 if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { 688 if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { 689 ERROR("Could not set up verified partition, skipping!"); 690 continue; 691 } 692 } 693 694 /* Now mount it where requested */ 695 if (tmp_mount_point) { 696 m = tmp_mount_point; 697 } else { 698 m = fstab->recs[i].mount_point; 699 } 700 if (__mount(n_blk_device, m, fstab->recs[i].fs_type, 701 fstab->recs[i].flags, fstab->recs[i].fs_options)) { 702 ERROR("Cannot mount filesystem on %s at %s\n", 703 n_blk_device, m); 704 goto out; 705 } else { 706 ret = 0; 707 goto out; 708 } 709 } 710 711 /* We didn't find a match, say so and return an error */ 712 ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); 713 714out: 715 return ret; 716} 717 718/* 719 * mount a tmpfs filesystem at the given point. 720 * return 0 on success, non-zero on failure. 721 */ 722int fs_mgr_do_tmpfs_mount(char *n_name) 723{ 724 int ret; 725 726 ret = mount("tmpfs", n_name, "tmpfs", 727 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS); 728 if (ret < 0) { 729 ERROR("Cannot mount tmpfs filesystem at %s\n", n_name); 730 return -1; 731 } 732 733 /* Success */ 734 return 0; 735} 736 737int fs_mgr_unmount_all(struct fstab *fstab) 738{ 739 int i = 0; 740 int ret = 0; 741 742 if (!fstab) { 743 return -1; 744 } 745 746 while (fstab->recs[i].blk_device) { 747 if (umount(fstab->recs[i].mount_point)) { 748 ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point); 749 ret = -1; 750 } 751 i++; 752 } 753 754 return ret; 755} 756 757/* This must be called after mount_all, because the mkswap command needs to be 758 * available. 759 */ 760int fs_mgr_swapon_all(struct fstab *fstab) 761{ 762 int i = 0; 763 int flags = 0; 764 int err = 0; 765 int ret = 0; 766 int status; 767 char *mkswap_argv[2] = { 768 MKSWAP_BIN, 769 NULL 770 }; 771 772 if (!fstab) { 773 return -1; 774 } 775 776 for (i = 0; i < fstab->num_entries; i++) { 777 /* Skip non-swap entries */ 778 if (strcmp(fstab->recs[i].fs_type, "swap")) { 779 continue; 780 } 781 782 if (fstab->recs[i].zram_size > 0) { 783 /* A zram_size was specified, so we need to configure the 784 * device. There is no point in having multiple zram devices 785 * on a system (all the memory comes from the same pool) so 786 * we can assume the device number is 0. 787 */ 788 FILE *zram_fp; 789 790 zram_fp = fopen(ZRAM_CONF_DEV, "r+"); 791 if (zram_fp == NULL) { 792 ERROR("Unable to open zram conf device " ZRAM_CONF_DEV); 793 ret = -1; 794 continue; 795 } 796 fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size); 797 fclose(zram_fp); 798 } 799 800 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 801 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 802 } 803 804 /* Initialize the swap area */ 805 mkswap_argv[1] = fstab->recs[i].blk_device; 806 err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, 807 &status, true, LOG_KLOG, false, NULL); 808 if (err) { 809 ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); 810 ret = -1; 811 continue; 812 } 813 814 /* If -1, then no priority was specified in fstab, so don't set 815 * SWAP_FLAG_PREFER or encode the priority */ 816 if (fstab->recs[i].swap_prio >= 0) { 817 flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) & 818 SWAP_FLAG_PRIO_MASK; 819 flags |= SWAP_FLAG_PREFER; 820 } else { 821 flags = 0; 822 } 823 err = swapon(fstab->recs[i].blk_device, flags); 824 if (err) { 825 ERROR("swapon failed for %s\n", fstab->recs[i].blk_device); 826 ret = -1; 827 } 828 } 829 830 return ret; 831} 832 833/* 834 * key_loc must be at least PROPERTY_VALUE_MAX bytes long 835 * 836 * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long 837 */ 838int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size) 839{ 840 int i = 0; 841 842 if (!fstab) { 843 return -1; 844 } 845 /* Initialize return values to null strings */ 846 if (key_loc) { 847 *key_loc = '\0'; 848 } 849 if (real_blk_device) { 850 *real_blk_device = '\0'; 851 } 852 853 /* Look for the encryptable partition to find the data */ 854 for (i = 0; i < fstab->num_entries; i++) { 855 /* Don't deal with vold managed enryptable partitions here */ 856 if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { 857 continue; 858 } 859 if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) { 860 continue; 861 } 862 863 /* We found a match */ 864 if (key_loc) { 865 strlcpy(key_loc, fstab->recs[i].key_loc, size); 866 } 867 if (real_blk_device) { 868 strlcpy(real_blk_device, fstab->recs[i].blk_device, size); 869 } 870 break; 871 } 872 873 return 0; 874} 875 876/* Add an entry to the fstab, and return 0 on success or -1 on error */ 877int fs_mgr_add_entry(struct fstab *fstab, 878 const char *mount_point, const char *fs_type, 879 const char *blk_device, long long length) 880{ 881 struct fstab_rec *new_fstab_recs; 882 int n = fstab->num_entries; 883 884 new_fstab_recs = (struct fstab_rec *) 885 realloc(fstab->recs, sizeof(struct fstab_rec) * (n + 1)); 886 887 if (!new_fstab_recs) { 888 return -1; 889 } 890 891 /* A new entry was added, so initialize it */ 892 memset(&new_fstab_recs[n], 0, sizeof(struct fstab_rec)); 893 new_fstab_recs[n].mount_point = strdup(mount_point); 894 new_fstab_recs[n].fs_type = strdup(fs_type); 895 new_fstab_recs[n].blk_device = strdup(blk_device); 896 new_fstab_recs[n].length = 0; 897 898 /* Update the fstab struct */ 899 fstab->recs = new_fstab_recs; 900 fstab->num_entries++; 901 902 return 0; 903} 904 905struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) 906{ 907 int i; 908 909 if (!fstab) { 910 return NULL; 911 } 912 913 for (i = 0; i < fstab->num_entries; i++) { 914 int len = strlen(fstab->recs[i].mount_point); 915 if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && 916 (path[len] == '\0' || path[len] == '/')) { 917 return &fstab->recs[i]; 918 } 919 } 920 921 return NULL; 922} 923 924int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) 925{ 926 return fstab->fs_mgr_flags & MF_VOLDMANAGED; 927} 928 929int fs_mgr_is_nonremovable(struct fstab_rec *fstab) 930{ 931 return fstab->fs_mgr_flags & MF_NONREMOVABLE; 932} 933 934int fs_mgr_is_encryptable(struct fstab_rec *fstab) 935{ 936 return fstab->fs_mgr_flags & MF_CRYPT; 937} 938 939int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab) 940{ 941 return fstab->fs_mgr_flags & MF_NOEMULATEDSD; 942} 943