diff options
author | Tom Marshall <tdm@cyngn.com> | 2014-11-24 16:02:04 -0800 |
---|---|---|
committer | Tom Marshall <tdm@cyngn.com> | 2015-11-25 15:34:31 -0800 |
commit | 3f092f7778ed608d454df4c3dc3b3f7cb4afde3b (patch) | |
tree | 326444388672880e6ab3bf72f434e13e1d80c25e /roots.cpp | |
parent | 383f723fdb0ebba5078ccc2aabf87f0516215bf9 (diff) | |
download | bootable_recovery-3f092f7778ed608d454df4c3dc3b3f7cb4afde3b.zip bootable_recovery-3f092f7778ed608d454df4c3dc3b3f7cb4afde3b.tar.gz bootable_recovery-3f092f7778ed608d454df4c3dc3b3f7cb4afde3b.tar.bz2 |
recovery: Awakening of MiniVold
A minimal vold client for recovery.
Change-Id: Id25d955dc1861a910e5f5fc27d9a19e245d66833
Diffstat (limited to 'roots.cpp')
-rw-r--r-- | roots.cpp | 112 |
1 files changed, 102 insertions, 10 deletions
@@ -23,6 +23,7 @@ #include <unistd.h> #include <ctype.h> #include <fcntl.h> +#include <dirent.h> #include <fs_mgr.h> #include "mtdutils/mtdutils.h" @@ -35,10 +36,30 @@ extern "C" { #include "cryptfs.h" } +#include "voldclient.h" + static struct fstab *fstab = NULL; extern struct selabel_handle *sehandle; +static int mkdir_p(const char* path, mode_t mode) +{ + char dir[PATH_MAX]; + char* p; + strcpy(dir, path); + for (p = strchr(&dir[1], '/'); p != NULL; p = strchr(p+1, '/')) { + *p = '\0'; + if (mkdir(dir, mode) != 0 && errno != EEXIST) { + return -1; + } + *p = '/'; + } + if (mkdir(dir, mode) != 0 && errno != EEXIST) { + return -1; + } + return 0; +} + static void write_fstab_entry(Volume *v, FILE *file) { if (NULL != v && strcmp(v->fs_type, "mtd") != 0 && strcmp(v->fs_type, "emmc") != 0 @@ -53,6 +74,14 @@ static void write_fstab_entry(Volume *v, FILE *file) } } +int get_num_volumes() { + return fstab->num_entries; +} + +Volume* get_device_volumes() { + return fstab->recs; +} + void load_volume_table() { int i; @@ -98,6 +127,17 @@ Volume* volume_for_path(const char* path) { return fs_mgr_get_entry_for_mount_point(fstab, path); } +Volume* volume_for_label(const char* label) { + int i; + for (i = 0; i < get_num_volumes(); i++) { + Volume* v = get_device_volumes() + i; + if (v->label && !strcmp(v->label, label)) { + return v; + } + } + return NULL; +} + // Mount the volume specified by path at the given mount_point. int ensure_path_mounted_at(const char* path, const char* mount_point) { Volume* v = volume_for_path(path); @@ -121,14 +161,16 @@ int ensure_path_mounted_at(const char* path, const char* mount_point) { mount_point = v->mount_point; } - const MountedVolume* mv = - find_mounted_volume_by_mount_point(mount_point); - if (mv) { - // volume is already mounted - return 0; + if (!fs_mgr_is_voldmanaged(v)) { + const MountedVolume* mv = + find_mounted_volume_by_mount_point(mount_point); + if (mv) { + // volume is already mounted + return 0; + } } - mkdir(mount_point, 0755); // in case it doesn't already exist + mkdir_p(mount_point, 0755); // in case it doesn't already exist if (strcmp(v->fs_type, "yaffs2") == 0) { // mount an MTD partition as a YAFFS2 filesystem. @@ -156,17 +198,49 @@ int ensure_path_mounted_at(const char* path, const char* mount_point) { return -1; } +int ensure_volume_mounted(Volume* v) { + if (v == NULL) { + LOGE("cannot mount unknown volume\n"); + return -1; + } + return ensure_path_mounted_at(v->mount_point, nullptr); +} + int ensure_path_mounted(const char* path) { // Mount at the default mount point. return ensure_path_mounted_at(path, nullptr); } -int ensure_path_unmounted(const char* path) { - Volume* v = volume_for_path(path); +int ensure_path_unmounted(const char* path, bool detach /* = false */) { + Volume* v; + if (memcmp(path, "/storage/", 9) == 0) { + char label[PATH_MAX]; + const char* p = path+9; + const char* q = strchr(p, '/'); + memset(label, 0, sizeof(label)); + if (q) { + memcpy(label, p, q-p); + } + else { + strcpy(label, p); + } + v = volume_for_label(label); + } + else { + v = volume_for_path(path); + } if (v == NULL) { LOGE("unknown volume for path [%s]\n", path); return -1; } + return ensure_volume_unmounted(v, detach); +} + +int ensure_volume_unmounted(Volume* v, bool detach /* = false */) { + if (v == NULL) { + LOGE("cannot unmount unknown volume\n"); + return -1; + } if (strcmp(v->fs_type, "ramdisk") == 0) { // the ramdisk is always mounted; you can't unmount it. return -1; @@ -186,7 +260,14 @@ int ensure_path_unmounted(const char* path) { return 0; } - return unmount_mounted_volume(mv); + if (detach) { + result = unmount_mounted_volume_detach(mv); + } + else { + result = unmount_mounted_volume(mv); + } + + return result; } static int exec_cmd(const char* path, char* const argv[]) { @@ -224,6 +305,11 @@ int format_volume(const char* volume) { return -1; } + if (fs_mgr_is_voldmanaged(v)) { + LOGE("can't format vold volume \"%s\"", volume); + return -1; + } + if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) { mtd_scan_partitions(); const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device); @@ -317,7 +403,13 @@ int setup_install_mounts() { } } else { - if (ensure_path_unmounted(v->mount_point) != 0) { + // datamedia and anything managed by vold must be unmounted + // with the detach flag to ensure that FUSE works. + bool detach = false; + if (is_data_media() && strcmp(v->mount_point, "/data") == 0) { + detach = true; + } + if (ensure_volume_unmounted(v, detach) != 0) { LOGE("failed to unmount %s\n", v->mount_point); return -1; } |