void load_volume_table() { int i; int ret; fstab = fs_mgr_read_fstab("/etc/recovery.fstab"); if (!fstab) { LOGE("failed to read /etc/recovery.fstab\n"); return; } ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk"); if (ret < 0 ) { LOGE("failed to add /tmp entry to fstab\n"); fs_mgr_free_fstab(fstab); fstab = NULL; return; } printf("recovery filesystem table\n"); printf("=========================\n"); for (i = 0; i < fstab->num_entries; ++i) { Volume* v = &fstab->recs[i]; printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, v->blk_device, v->length); } printf("\n"); }
int main(int argc, char *argv[]) { int a_flag=0; int u_flag=0; int n_flag=0; char *n_name=NULL; char *n_blk_dev=NULL; char *fstab_file=NULL; struct fstab *fstab=NULL; klog_set_level(6); parse_options(argc, argv, &a_flag, &u_flag, &n_flag, &n_name, &n_blk_dev); /* The name of the fstab file is last, after the option */ fstab_file = argv[argc - 1]; fstab = fs_mgr_read_fstab(fstab_file); if (a_flag) { return fs_mgr_mount_all(fstab); } else if (n_flag) { return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0); } else if (u_flag) { return fs_mgr_unmount_all(fstab); } else { ERROR("%s: Internal error, unknown option\n", me); exit(1); } fs_mgr_free_fstab(fstab); /* Should not get here */ exit(1); }
void TrimTask::addFromFstab() { struct fstab *fstab; struct fstab_rec *prev_rec = NULL; fstab = fs_mgr_read_fstab(android::vold::DefaultFstabPath().c_str()); for (int i = 0; i < fstab->num_entries; i++) { /* Skip raw partitions */ if (!strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } /* Skip read-only filesystems */ if (fstab->recs[i].flags & MS_RDONLY) { continue; } if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { continue; /* Should we trim fat32 filesystems? */ } if (fs_mgr_is_notrim(&fstab->recs[i])) { continue; } /* Skip the multi-type partitions, which are required to be following each other. * See fs_mgr.c's mount_with_alternatives(). */ if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) { continue; } mPaths.push_back(fstab->recs[i].mount_point); prev_rec = &fstab->recs[i]; } fs_mgr_free_fstab(fstab); }
// Returns the device used to mount a directory in the fstab. static std::string find_fstab_mount(const char* dir) { std::string fstab_filename = "/fstab." + android::base::GetProperty("ro.hardware", ""); struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str()); struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir); std::string dev = rec ? std::string(rec->blk_device) : ""; fs_mgr_free_fstab(fstab); return dev; }
void load_volume_table() { int i; int ret; fstab = fs_mgr_read_fstab("/etc/recovery.fstab"); if (!fstab) { LOGE("failed to read /etc/recovery.fstab\n"); LOGE("try read other fstab\n"); fstab = mt_read_fstab(); if (!fstab) { LOGE("failed to read fstab\n"); return; } } ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk"); if (ret < 0 ) { LOGE("failed to add /tmp entry to fstab\n"); fs_mgr_free_fstab(fstab); fstab = NULL; return; } ret = mt_load_volume_table(fstab); if (ret < 0 ) { LOGE("mt_load_volume_table fail to add entry to fstab\n"); fs_mgr_free_fstab(fstab); fstab = NULL; return; } mt_ensure_dev_ready("/misc"); mt_ensure_dev_ready("/cache"); mt_fstab_translation_NAND(fstab); printf("recovery filesystem table\n"); printf("=========================\n"); for (i = 0; i < fstab->num_entries; ++i) { Volume* v = &fstab->recs[i]; printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, v->blk_device, v->length); } printf("\n"); }
int do_mount_all(int nargs, char **args) { pid_t pid; int ret = -1; int child_ret = -1; int status; const char *prop; struct fstab *fstab; if (nargs != 2) { return -1; } /* * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and * do the call in the child to provide protection to the main init * process if anything goes wrong (crash or memory leak), and wait for * the child to finish in the parent. */ pid = fork(); if (pid > 0) { /* Parent. Wait for the child to return */ waitpid(pid, &status, 0); if (WIFEXITED(status)) { ret = WEXITSTATUS(status); } else { ret = -1; } } else if (pid == 0) { /* child, call fs_mgr_mount_all() */ klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ fstab = fs_mgr_read_fstab(args[1]); child_ret = fs_mgr_mount_all(fstab); fs_mgr_free_fstab(fstab); if (child_ret == -1) { ERROR("fs_mgr_mount_all returned an error\n"); } exit(child_ret); } else { /* fork failed, return an error */ return -1; } /* ret is 1 if the device is encrypted, 0 if not, and -1 on error */ if (ret == 1) { property_set("ro.crypto.state", "encrypted"); property_set("vold.decrypt", "1"); } else if (ret == 0) { property_set("ro.crypto.state", "unencrypted"); /* If fs_mgr determined this is an unencrypted device, then trigger * that action. */ action_for_each_trigger("nonencrypted", action_add_queue_tail); } return ret; }
static int do_swapon_all(const std::vector<std::string>& args) { struct fstab *fstab; int ret; fstab = fs_mgr_read_fstab(args[1].c_str()); ret = fs_mgr_swapon_all(fstab); fs_mgr_free_fstab(fstab); return ret; }
int do_swapon_all(int nargs, char **args) { struct fstab *fstab; int ret; fstab = fs_mgr_read_fstab(args[1]); ret = fs_mgr_swapon_all(fstab); fs_mgr_free_fstab(fstab); return ret; }
// Returns the device used to mount a directory in the fstab. static std::string find_fstab_mount(const char* dir) { char propbuf[PROPERTY_VALUE_MAX]; property_get("ro.hardware", propbuf, ""); std::string fstab_filename = kFstab_Prefix + propbuf; struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str()); struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir); std::string dev = rec ? std::string(rec->blk_device) : ""; fs_mgr_free_fstab(fstab); return dev; }
void load_volume_table() { int i; int ret; fstab = fs_mgr_read_fstab("/etc/recovery.fstab"); if (!fstab) { LOGE("failed to read /etc/recovery.fstab\n"); return; } ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk"); if (ret < 0 ) { LOGE("failed to add /tmp entry to fstab\n"); fs_mgr_free_fstab(fstab); fstab = NULL; return; } // Create a boring /etc/fstab so tools like Busybox work FILE *file = fopen("/etc/fstab", "w"); if (file == NULL) { LOGW("Unable to create /etc/fstab!\n"); return; } is_datamedia = 1; printf("recovery filesystem table\n"); printf("=========================\n"); for (i = 0; i < fstab->num_entries; ++i) { fstab_rec* v = &fstab->recs[i]; printf(" %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, v->blk_device, v->length); write_fstab_entry(v, file); if (is_volume_primary_storage(v)) { is_datamedia = 0; } } fclose(file); printf("\n"); }
void load_volume_table() { int i; int ret; fstab = fs_mgr_read_fstab("/etc/recovery.fstab"); if (!fstab) { LOGE("failed to read /etc/recovery.fstab\n"); return; } ret = fs_mgr_add_entry(fstab, "/tmp", "ramdisk", "ramdisk", 0); if (ret < 0 ) { LOGE("failed to add /tmp entry to fstab\n"); fs_mgr_free_fstab(fstab); fstab = NULL; return; } // Process vold-managed volumes with mount point "auto" for (i = 0; i < fstab->num_entries; ++i) { Volume* v = &fstab->recs[i]; if (fs_mgr_is_voldmanaged(v) && strcmp(v->mount_point, "auto") == 0) { char mount[PATH_MAX]; // Set the mount point to /storage/label which as used by vold snprintf(mount, PATH_MAX, "/storage/%s", v->label); free(v->mount_point); v->mount_point = strdup(mount); } } fprintf(stderr, "recovery filesystem table\n"); fprintf(stderr, "=========================\n"); for (i = 0; i < fstab->num_entries; ++i) { Volume* v = &fstab->recs[i]; fprintf(stderr, " %d %s %s %s %lld\n", i, v->mount_point, v->fs_type, v->blk_device, v->length); } fprintf(stderr, "\n"); }
struct fstab *fs_mgr_read_fstab(const char *fstab_path) { FILE *fstab_file; int cnt, entries; ssize_t len; size_t alloc_len = 0; char *line = NULL; const char *delim = " \t"; char *save_ptr, *p; struct fstab *fstab = NULL; struct fstab_rec *recs; struct fs_mgr_flag_values flag_vals; #define FS_OPTIONS_LEN 1024 char tmp_fs_options[FS_OPTIONS_LEN]; fstab_file = fopen(fstab_path, "r"); if (!fstab_file) { ERROR("Cannot open file %s\n", fstab_path); return 0; } entries = 0; while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { /* if the last character is a newline, shorten the string by 1 byte */ if (line[len - 1] == '\n') { line[len - 1] = '\0'; } /* Skip any leading whitespace */ p = line; while (isspace(*p)) { p++; } /* ignore comments or empty lines */ if (*p == '#' || *p == '\0') continue; entries++; } if (!entries) { ERROR("No entries found in fstab\n"); goto err; } /* Allocate and init the fstab structure */ fstab = calloc(1, sizeof(struct fstab)); fstab->num_entries = entries; fstab->fstab_filename = strdup(fstab_path); fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec)); fseek(fstab_file, 0, SEEK_SET); cnt = 0; while ((len = getline(&line, &alloc_len, fstab_file)) != -1) { /* if the last character is a newline, shorten the string by 1 byte */ if (line[len - 1] == '\n') { line[len - 1] = '\0'; } /* Skip any leading whitespace */ p = line; while (isspace(*p)) { p++; } /* ignore comments or empty lines */ if (*p == '#' || *p == '\0') continue; /* If a non-comment entry is greater than the size we allocated, give an * error and quit. This can happen in the unlikely case the file changes * between the two reads. */ if (cnt >= entries) { ERROR("Tried to process more entries than counted\n"); break; } if (!(p = strtok_r(line, delim, &save_ptr))) { ERROR("Error parsing mount source\n"); goto err; } fstab->recs[cnt].blk_device = strdup(p); if (!(p = strtok_r(NULL, delim, &save_ptr))) { ERROR("Error parsing mount_point\n"); goto err; } fstab->recs[cnt].mount_point = strdup(p); if (!(p = strtok_r(NULL, delim, &save_ptr))) { ERROR("Error parsing fs_type\n"); goto err; } fstab->recs[cnt].fs_type = strdup(p); if (!(p = strtok_r(NULL, delim, &save_ptr))) { ERROR("Error parsing mount_flags\n"); goto err; } tmp_fs_options[0] = '\0'; fstab->recs[cnt].flags = parse_flags(p, mount_flags, NULL, tmp_fs_options, FS_OPTIONS_LEN); /* fs_options are optional */ if (tmp_fs_options[0]) { fstab->recs[cnt].fs_options = strdup(tmp_fs_options); } else { fstab->recs[cnt].fs_options = NULL; } if (!(p = strtok_r(NULL, delim, &save_ptr))) { ERROR("Error parsing fs_mgr_options\n"); goto err; } fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &flag_vals, NULL, 0); fstab->recs[cnt].key_loc = flag_vals.key_loc; fstab->recs[cnt].length = flag_vals.part_length; fstab->recs[cnt].label = flag_vals.label; fstab->recs[cnt].partnum = flag_vals.partnum; fstab->recs[cnt].swap_prio = flag_vals.swap_prio; fstab->recs[cnt].zram_size = flag_vals.zram_size; cnt++; } fclose(fstab_file); free(line); return fstab; err: fclose(fstab_file); free(line); if (fstab) fs_mgr_free_fstab(fstab); return NULL; }
/* * This function might request a reboot, in which case it will * not return. */ int do_mount_all(int nargs, char **args) { pid_t pid; int ret = -1; int child_ret = -1; int status; char boot_mode[PROP_VALUE_MAX] = {0}; struct fstab *fstab; if (nargs != 2) { return -1; } /* * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and * do the call in the child to provide protection to the main init * process if anything goes wrong (crash or memory leak), and wait for * the child to finish in the parent. */ pid = fork(); if (pid > 0) { /* Parent. Wait for the child to return */ int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (wp_ret < 0) { /* Unexpected error code. We will continue anyway. */ NOTICE("waitpid failed rc=%d: %s\n", wp_ret, strerror(errno)); } if (WIFEXITED(status)) { ret = WEXITSTATUS(status); } else { ret = -1; } } else if (pid == 0) { /* child, call fs_mgr_mount_all() */ klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ fstab = fs_mgr_read_fstab(args[1]); child_ret = fs_mgr_mount_all(fstab); fs_mgr_free_fstab(fstab); if (child_ret == -1) { ERROR("fs_mgr_mount_all returned an error\n"); } _exit(child_ret); } else { /* fork failed, return an error */ return -1; } if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { property_set("vold.decrypt", "trigger_encryption"); } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { property_set("ro.crypto.state", "encrypted"); property_set("ro.crypto.type", "block"); property_set("vold.decrypt", "trigger_default_encryption"); } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { property_set("ro.crypto.state", "unencrypted"); /* If fs_mgr determined this is an unencrypted device and we are * not booting into ffbm(fast factory boot mode),then trigger * that action. */ property_get("ro.bootmode", boot_mode); if (strncmp(boot_mode, "ffbm", 4)) action_for_each_trigger("nonencrypted", action_add_queue_tail); } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { /* Setup a wipe via recovery, and reboot into recovery */ ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n"); ret = wipe_data_via_recovery(); /* If reboot worked, there is no return. */ } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; } property_set("ro.crypto.state", "encrypted"); property_set("ro.crypto.type", "file"); // Although encrypted, we have device key, so we do not need to // do anything different from the nonencrypted case. property_get("ro.bootmode", boot_mode); if (strncmp(boot_mode, "ffbm", 4)) action_for_each_trigger("nonencrypted", action_add_queue_tail); } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { return -1; } property_set("ro.crypto.state", "encrypted"); property_set("ro.crypto.type", "file"); property_set("vold.decrypt", "trigger_restart_min_framework"); } else if (ret > 0) { ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret); } /* else ... < 0: error */ return ret; }
int main(int argc, char **argv) { struct fstab *fstab; int ret=0, syspart, i, status; char filenamePatched[PATH_MAX], filenameSystem[PATH_MAX]; // check arguments if(argc!=2) { ERROR("Invalid Arguments"); return -EINVAL; } // get syspart from cmdline syspart = getDualbootSyspart(); if(syspart<0) { ERROR("Cannot read system number"); return -EINVAL; } // patch fstab sprintf(filenamePatched, "%s.patched", argv[1]); sprintf(filenameSystem, "%s.system", argv[1]); patch_fstab(argv[1], filenamePatched, filenameSystem, syspart); // mount system fstab = fs_mgr_read_fstab(filenameSystem); ret = fs_mgr_mount_all(fstab); fs_mgr_free_fstab(fstab); if (ret == -1) { ERROR("fs_mgr_mount_all returned an error\n"); } // mount data fstab = fs_mgr_read_fstab(argv[1]); for (i = 0; i < fstab->num_entries; ++i) { struct fstab_rec* v = &fstab->recs[i]; if(strcmp(PARTITION_USERDATA, v->blk_device)) continue; if (v->fs_mgr_flags & MF_WAIT) { wait_for_file(v->blk_device, WAIT_TIMEOUT); } if (v->fs_mgr_flags & MF_CHECK) { check_fs(v->blk_device, v->fs_type, v->mount_point); } if(mountScriptExists()) { char *e2fsck_argv[] = { "/system/bin/mount_ext4.sh", v->blk_device, v->mount_point }; ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, &status, true, LOG_KLOG, true, NULL); } else { ret = mount(v->blk_device, v->mount_point, v->fs_type, v->flags, v->fs_options); } } fs_mgr_free_fstab(fstab); if (ret == -1) { ERROR("error mounting userdata\n"); } return ret; }
int boot_info_open_partition(const char *name, uint64_t *out_size, int flags) { char *path; int fd; struct fstab *fstab; struct fstab_rec *record; // We can't use fs_mgr to look up |name| because fstab doesn't list // every slot partition (it uses the slotselect option to mask the // suffix) and |slot| is expected to be of that form, e.g. boot_a. // // We can however assume that there's an entry for the /misc mount // point and use that to get the device file for the misc // partition. From there we'll assume that a by-name scheme is used // so we can just replace the trailing "misc" by the given |name|, // e.g. // // /dev/block/platform/soc.0/7824900.sdhci/by-name/misc -> // /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a // // If needed, it's possible to relax this assumption in the future // by trawling /sys/block looking for the appropriate sibling of // misc and then finding an entry in /dev matching the sysfs entry. fstab = open_fstab(); if (fstab == NULL) return -1; record = fs_mgr_get_entry_for_mount_point(fstab, "/misc"); if (record == NULL) { fs_mgr_free_fstab(fstab); return -1; } if (strcmp(name, "misc") == 0) { path = strdup(record->blk_device); } else { size_t trimmed_len, name_len; const char *end_slash = strrchr(record->blk_device, '/'); if (end_slash == NULL) { fs_mgr_free_fstab(fstab); return -1; } trimmed_len = end_slash - record->blk_device + 1; name_len = strlen(name); path = calloc(trimmed_len + name_len + 1, 1); strncpy(path, record->blk_device, trimmed_len); strncpy(path + trimmed_len, name, name_len); } fs_mgr_free_fstab(fstab); fd = open(path, flags); free(path); // If we successfully opened the device, get size if requested. if (fd != -1 && out_size != NULL) { if (ioctl(fd, BLKGETSIZE64, out_size) != 0) { close(fd); return -1; } } return fd; }
/* * This function might request a reboot, in which case it will * not return. */ int do_mount_all(int nargs, char **args) { pid_t pid; int ret = -1; int child_ret = -1; int status; struct fstab *fstab; if (nargs != 2) { return -1; } /* * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and * do the call in the child to provide protection to the main init * process if anything goes wrong (crash or memory leak), and wait for * the child to finish in the parent. */ pid = fork(); if (pid > 0) { /* Parent. Wait for the child to return */ int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (wp_ret < 0) { /* Unexpected error code. We will continue anyway. */ NOTICE("waitpid failed rc=%d, errno=%d\n", wp_ret, errno); } if (WIFEXITED(status)) { ret = WEXITSTATUS(status); } else { ret = -1; } } else if (pid == 0) { /* child, call fs_mgr_mount_all() */ klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ fstab = fs_mgr_read_fstab(args[1]); child_ret = fs_mgr_mount_all(fstab); fs_mgr_free_fstab(fstab); if (child_ret == -1) { ERROR("fs_mgr_mount_all returned an error\n"); } _exit(child_ret); } else { /* fork failed, return an error */ return -1; } if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { property_set("vold.decrypt", "trigger_encryption"); } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { property_set("ro.crypto.state", "encrypted"); property_set("vold.decrypt", "trigger_default_encryption"); } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { property_set("ro.crypto.state", "unencrypted"); /* If fs_mgr determined this is an unencrypted device, then trigger * that action. */ action_for_each_trigger("nonencrypted", action_add_queue_tail); } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { /* Setup a wipe via recovery, and reboot into recovery */ ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n"); ret = wipe_data_via_recovery(); /* If reboot worked, there is no return. */ } else if (ret > 0) { ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret); } /* else ... < 0: error */ return ret; }