aboutsummaryrefslogtreecommitdiffstats
path: root/roots.cpp
diff options
context:
space:
mode:
authorTom Marshall <tdm@cyngn.com>2014-11-24 16:02:04 -0800
committerTom Marshall <tdm@cyngn.com>2015-11-25 15:34:31 -0800
commit3f092f7778ed608d454df4c3dc3b3f7cb4afde3b (patch)
tree326444388672880e6ab3bf72f434e13e1d80c25e /roots.cpp
parent383f723fdb0ebba5078ccc2aabf87f0516215bf9 (diff)
downloadbootable_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.cpp112
1 files changed, 102 insertions, 10 deletions
diff --git a/roots.cpp b/roots.cpp
index 966c8b2..3dc604b 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -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;
}