tar nandroid and /data/media support.
Change-Id: I9405e701887fc83c422c63c1dbf5ff087fff880d
diff --git a/Android.mk b/Android.mk
index 1d5a056..d12850c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,7 +26,7 @@
LOCAL_FORCE_STATIC_EXECUTABLE := true
-RECOVERY_VERSION := ClockworkMod Recovery v3.2.0.1
+RECOVERY_VERSION := ClockworkMod Recovery v3.2.0.2
LOCAL_CFLAGS += -DRECOVERY_VERSION="$(RECOVERY_VERSION)"
RECOVERY_API_VERSION := 2
LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
@@ -58,7 +58,7 @@
LOCAL_STATIC_LIBRARIES += libedify libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image
-LOCAL_STATIC_LIBRARIES += libflashutils libmtdutils libmmcutils libbmlutils
+LOCAL_STATIC_LIBRARIES += libcrecovery libflashutils libmtdutils libmmcutils libbmlutils
ifeq ($(BOARD_USES_BML_OVER_MTD),true)
LOCAL_STATIC_LIBRARIES += libbml_over_mtd
@@ -129,6 +129,7 @@
include $(commands_recovery_local_path)/bmlutils/Android.mk
include $(commands_recovery_local_path)/flashutils/Android.mk
+include $(commands_recovery_local_path)/libcrecovery/Android.mk
include $(commands_recovery_local_path)/minui/Android.mk
include $(commands_recovery_local_path)/minzip/Android.mk
include $(commands_recovery_local_path)/mtdutils/Android.mk
diff --git a/extendedcommands.c b/extendedcommands.c
index cb44cb1..5543e96 100644
--- a/extendedcommands.c
+++ b/extendedcommands.c
@@ -466,10 +466,16 @@
}
static char tmp[PATH_MAX];
- sprintf(tmp, "rm -rf %s/*", path);
- __system(tmp);
- sprintf(tmp, "rm -rf %s/.*", path);
- __system(tmp);
+ if (strcmp(path, "/data") == 0) {
+ sprintf(tmp, "cd /data ; for f in $(ls -a | grep -v ^media$); do rm -rf $f; done");
+ __system(tmp);
+ }
+ else {
+ sprintf(tmp, "rm -rf %s/*", path);
+ __system(tmp);
+ sprintf(tmp, "rm -rf %s/.*", path);
+ __system(tmp);
+ }
ensure_path_unmounted(path);
return 0;
diff --git a/flashutils/Android.mk b/flashutils/Android.mk
index d503ce7..d513275 100644
--- a/flashutils/Android.mk
+++ b/flashutils/Android.mk
@@ -8,7 +8,7 @@
LOCAL_MODULE := libflashutils
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES := libmmcutils libmtdutils libbmlutils
+LOCAL_STATIC_LIBRARIES := libmmcutils libmtdutils libbmlutils libcrecovery
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
diff --git a/flashutils/flashutils.c b/flashutils/flashutils.c
index 27f0c66..958476c 100644
--- a/flashutils/flashutils.c
+++ b/flashutils/flashutils.c
@@ -29,47 +29,6 @@
return device_flash_type() == MMC ? "ext3" : "yaffs2";
}
-// This was pulled from bionic: The default system command always looks
-// for shell in /system/bin/sh. This is bad.
-#define _PATH_BSHELL "/sbin/sh"
-
-extern char **environ;
-int
-__system(const char *command)
-{
- pid_t pid;
- sig_t intsave, quitsave;
- sigset_t mask, omask;
- int pstat;
- char *argp[] = {"sh", "-c", NULL, NULL};
-
- if (!command) /* just checking... */
- return(1);
-
- argp[2] = (char *)command;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &mask, &omask);
- switch (pid = vfork()) {
- case -1: /* error */
- sigprocmask(SIG_SETMASK, &omask, NULL);
- return(-1);
- case 0: /* child */
- sigprocmask(SIG_SETMASK, &omask, NULL);
- execve(_PATH_BSHELL, argp, environ);
- _exit(127);
- }
-
- intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
- quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
- pid = waitpid(pid, (int *)&pstat, 0);
- sigprocmask(SIG_SETMASK, &omask, NULL);
- (void)bsd_signal(SIGINT, intsave);
- (void)bsd_signal(SIGQUIT, quitsave);
- return (pid == -1 ? -1 : pstat);
-}
-
int get_flash_type(const char* partitionType) {
int type = UNSUPPORTED;
if (strcmp(partitionType, "mtd") == 0)
diff --git a/flashutils/flashutils.h b/flashutils/flashutils.h
index dd59537..d112a31 100644
--- a/flashutils/flashutils.h
+++ b/flashutils/flashutils.h
@@ -15,8 +15,6 @@
int is_mtd_device();
char* get_default_filesystem();
-int __system(const char *command);
-
extern int cmd_mtd_restore_raw_partition(const char *partition, const char *filename);
extern int cmd_mtd_backup_raw_partition(const char *partition, const char *filename);
extern int cmd_mtd_erase_raw_partition(const char *partition);
diff --git a/libcrecovery/Android.mk b/libcrecovery/Android.mk
new file mode 100644
index 0000000..3d28d97
--- /dev/null
+++ b/libcrecovery/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(TARGET_SIMULATOR),true)
+ifeq ($(TARGET_ARCH),arm)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := system.c popen.c
+LOCAL_MODULE := libcrecovery
+LOCAL_MODULE_TAGS := eng
+include $(BUILD_STATIC_LIBRARY)
+
+endif
+endif
diff --git a/libcrecovery/common.h b/libcrecovery/common.h
new file mode 100644
index 0000000..bf83dd2
--- /dev/null
+++ b/libcrecovery/common.h
@@ -0,0 +1,8 @@
+#ifndef LIBCRECOVERY_COMMON_H
+#define LIBCRECOVERY_COMMON_H
+
+int __system(const char *command);
+FILE * __popen(const char *program, const char *type);
+int __pclose(FILE *iop);
+
+#endif
\ No newline at end of file
diff --git a/libcrecovery/defines.h b/libcrecovery/defines.h
new file mode 100644
index 0000000..d94ad2d
--- /dev/null
+++ b/libcrecovery/defines.h
@@ -0,0 +1,2 @@
+#undef _PATH_BSHELL
+#define _PATH_BSHELL "/sbin/sh"
diff --git a/libcrecovery/popen.c b/libcrecovery/popen.c
new file mode 100644
index 0000000..73d3c74
--- /dev/null
+++ b/libcrecovery/popen.c
@@ -0,0 +1,169 @@
+/* $OpenBSD: popen.c,v 1.17 2005/08/08 08:05:34 espie Exp $ */
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+
+#include "defines.h"
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+ pid_t pid;
+} *pidlist;
+
+FILE *
+__popen(const char *program, const char *type)
+{
+ struct pid * volatile cur;
+ FILE *iop;
+ int pdes[2];
+ pid_t pid;
+
+ if ((*type != 'r' && *type != 'w') || type[1] != '\0') {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((cur = malloc(sizeof(struct pid))) == NULL)
+ return (NULL);
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return (NULL);
+ }
+
+ switch (pid = vfork()) {
+ case -1: /* Error. */
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
+ free(cur);
+ return (NULL);
+ /* NOTREACHED */
+ case 0: /* Child. */
+ {
+ struct pid *pcur;
+ /*
+ * because vfork() instead of fork(), must leak FILE *,
+ * but luckily we are terminally headed for an execl()
+ */
+ for (pcur = pidlist; pcur; pcur = pcur->next)
+ close(fileno(pcur->fp));
+
+ if (*type == 'r') {
+ int tpdes1 = pdes[1];
+
+ (void) close(pdes[0]);
+ /*
+ * We must NOT modify pdes, due to the
+ * semantics of vfork.
+ */
+ if (tpdes1 != STDOUT_FILENO) {
+ (void)dup2(tpdes1, STDOUT_FILENO);
+ (void)close(tpdes1);
+ tpdes1 = STDOUT_FILENO;
+ }
+ } else {
+ (void)close(pdes[1]);
+ if (pdes[0] != STDIN_FILENO) {
+ (void)dup2(pdes[0], STDIN_FILENO);
+ (void)close(pdes[0]);
+ }
+ }
+ execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL);
+ _exit(127);
+ /* NOTREACHED */
+ }
+ }
+
+ /* Parent; assume fdopen can't fail. */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ (void)close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ (void)close(pdes[0]);
+ }
+
+ /* Link into list of file descriptors. */
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+ return (iop);
+}
+
+/*
+ * pclose --
+ * Pclose returns -1 if stream is not associated with a `popened' command,
+ * if already `pclosed', or waitpid returns an error.
+ */
+int
+__pclose(FILE *iop)
+{
+ struct pid *cur, *last;
+ int pstat;
+ pid_t pid;
+
+ /* Find the appropriate file pointer. */
+ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ if (cur->fp == iop)
+ break;
+
+ if (cur == NULL)
+ return (-1);
+
+ (void)fclose(iop);
+
+ do {
+ pid = waitpid(cur->pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+
+ /* Remove the entry from the linked list. */
+ if (last == NULL)
+ pidlist = cur->next;
+ else
+ last->next = cur->next;
+ free(cur);
+
+ return (pid == -1 ? -1 : pstat);
+}
diff --git a/libcrecovery/system.c b/libcrecovery/system.c
new file mode 100644
index 0000000..6d78ae9
--- /dev/null
+++ b/libcrecovery/system.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: system.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <paths.h>
+#include <sys/wait.h>
+
+#include "defines.h"
+
+extern char **environ;
+
+int
+__system(const char *command)
+{
+ pid_t pid;
+ sig_t intsave, quitsave;
+ sigset_t mask, omask;
+ int pstat;
+ char *argp[] = {"sh", "-c", NULL, NULL};
+
+ if (!command) /* just checking... */
+ return(1);
+
+ argp[2] = (char *)command;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, &omask);
+ switch (pid = vfork()) {
+ case -1: /* error */
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ return(-1);
+ case 0: /* child */
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ execve(_PATH_BSHELL, argp, environ);
+ _exit(127);
+ }
+
+ intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
+ quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
+ pid = waitpid(pid, (int *)&pstat, 0);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ (void)bsd_signal(SIGINT, intsave);
+ (void)bsd_signal(SIGQUIT, quitsave);
+ return (pid == -1 ? -1 : pstat);
+}
diff --git a/mounts.c b/mounts.c
index c90fc8a..e8b69e8 100644
--- a/mounts.c
+++ b/mounts.c
@@ -23,13 +23,6 @@
#include "mounts.h"
-struct MountedVolume {
- const char *device;
- const char *mount_point;
- const char *filesystem;
- const char *flags;
-};
-
typedef struct {
MountedVolume *volumes;
int volumes_allocd;
diff --git a/mounts.h b/mounts.h
index 30b2927..ed7fb5f 100644
--- a/mounts.h
+++ b/mounts.h
@@ -17,7 +17,12 @@
#ifndef MTDUTILS_MOUNTS_H_
#define MTDUTILS_MOUNTS_H_
-typedef struct MountedVolume MountedVolume;
+typedef struct {
+ const char *device;
+ const char *mount_point;
+ const char *filesystem;
+ const char *flags;
+} MountedVolume;
int scan_mounted_volumes(void);
diff --git a/nandroid.c b/nandroid.c
index 54d90b0..8cee3be 100644
--- a/nandroid.c
+++ b/nandroid.c
@@ -37,10 +37,11 @@
#include "extendedcommands.h"
#include "nandroid.h"
+#include "mounts.h"
+
#include "flashutils/flashutils.h"
#include <libgen.h>
-
void nandroid_generate_timestamp_path(const char* backup_path)
{
time_t t = time(NULL);
@@ -57,25 +58,31 @@
}
}
-int print_and_error(const char* message) {
+static int print_and_error(const char* message) {
ui_print("%s", message);
return 1;
}
-int yaffs_files_total = 0;
-int yaffs_files_count = 0;
-void yaffs_callback(const char* filename)
+static int yaffs_files_total = 0;
+static int yaffs_files_count = 0;
+static void yaffs_callback(const char* filename)
{
- char* justfile = basename(filename);
- if (strlen(justfile) < 30)
- ui_print("%s", justfile);
+ if (filename == NULL)
+ return;
+ const char* justfile = basename(filename);
+ char tmp[PATH_MAX];
+ strcpy(tmp, justfile);
+ if (tmp[strlen(tmp) - 1] == '\n')
+ tmp[strlen(tmp) - 1] = NULL;
+ if (strlen(tmp) < 30)
+ ui_print("%s", tmp);
yaffs_files_count++;
if (yaffs_files_total != 0)
ui_set_progress((float)yaffs_files_count / (float)yaffs_files_total);
ui_reset_text_col();
}
-void compute_directory_stats(const char* directory)
+static void compute_directory_stats(const char* directory)
{
char tmp[PATH_MAX];
sprintf(tmp, "find %s | wc -l > /tmp/dircount", directory);
@@ -90,12 +97,62 @@
ui_show_progress(1, 0);
}
+typedef void (*file_event_callback)(const char* filename);
+typedef int (*nandroid_backup_handler)(const char* backup_path, const char* backup_file_image, const file_event_callback callback);
+
+static int mkyaffs2image_wrapper(const char* backup_path, const char* backup_file_image, const file_event_callback callback) {
+ return mkyaffs2image(backup_path, backup_file_image, 0, callback);
+}
+
+static int tar_compress_wrapper(const char* backup_path, const char* backup_file_image, const file_event_callback callback) {
+ char tmp[PATH_MAX];
+ if (strcmp(backup_path, "/data") == 0 && volume_for_path("/sdcard") == NULL)
+ sprintf(tmp, "cd $(dirname %s) ; tar cvf %s --exclude 'media' $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path);
+ else
+ sprintf(tmp, "cd $(dirname %s) ; tar cvf %s $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path);
+
+ FILE *fp = __popen(tmp, "r");
+ if (fp == NULL) {
+ ui_print("Unable to execute tar.\n");
+ return -1;
+ }
+
+ while (fgets(tmp, PATH_MAX, fp) != NULL) {
+ tmp[PATH_MAX - 1] = NULL;
+ if (NULL != callback)
+ yaffs_callback(tmp);
+ }
+
+ return __pclose(fp);
+}
+
+static nandroid_backup_handler get_backup_handler(const char *backup_path) {
+ Volume *v = volume_for_path(backup_path);
+ if (v == NULL) {
+ ui_print("Unable to find volume.\n");
+ return NULL;
+ }
+ scan_mounted_volumes();
+ MountedVolume *mv = find_mounted_volume_by_mount_point(v->mount_point);
+ if (mv == NULL) {
+ ui_print("Unable to find mounted volume: %s\n", v->mount_point);
+ return NULL;
+ }
+
+ if (strcmp("yaffs2", mv->filesystem) == 0) {
+ return mkyaffs2image_wrapper;
+ }
+
+ return tar_compress_wrapper;
+}
+
+
int nandroid_backup_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
int ret = 0;
char* name = basename(mount_point);
struct stat file_info;
- mkyaffs2image_callback callback = NULL;
+ file_event_callback callback = NULL;
if (0 != stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info)) {
callback = yaffs_callback;
}
@@ -108,12 +165,17 @@
compute_directory_stats(mount_point);
char tmp[PATH_MAX];
sprintf(tmp, "%s/%s.img", backup_path, name);
- ret = mkyaffs2image(mount_point, tmp, 0, callback);
+ nandroid_backup_handler backup_handler = get_backup_handler(mount_point);
+ if (backup_handler == NULL) {
+ ui_print("Error finding an appropriate backup handler.\n");
+ return -2;
+ }
+ ret = backup_handler(mount_point, tmp, callback);
if (umount_when_finished) {
ensure_path_unmounted(mount_point);
}
if (0 != ret) {
- ui_print("Error while making a yaffs2 image of %s!\n", mount_point);
+ ui_print("Error while making a backup image of %s!\n", mount_point);
return ret;
}
return 0;
@@ -245,6 +307,51 @@
__system(tmp);
}
+typedef int (*nandroid_restore_handler)(const char* backup_file_image, const char* backup_path, file_event_callback callback);
+
+static int unyaffs_wrapper(const char* backup_file_image, const char* backup_path, file_event_callback callback) {
+ return unyaffs(backup_file_image, backup_path, callback);
+}
+
+static int tar_extract_wrapper(const char* backup_file_image, const char* backup_path, file_event_callback callback) {
+ char tmp[PATH_MAX];
+ sprintf(tmp, "cd $(dirname %s) ; tar xvf %s ; exit $?", backup_path, backup_file_image);
+
+ char path[PATH_MAX];
+ FILE *fp = __popen(tmp, "r");
+ if (fp == NULL) {
+ ui_print("Unable to execute tar.\n");
+ return -1;
+ }
+
+ while (fgets(path, PATH_MAX, fp) != NULL) {
+ if (NULL != callback)
+ callback(path);
+ }
+
+ return __pclose(fp);
+}
+
+static nandroid_restore_handler get_restore_handler(const char *backup_path) {
+ Volume *v = volume_for_path(backup_path);
+ if (v == NULL) {
+ ui_print("Unable to find volume.\n");
+ return NULL;
+ }
+ scan_mounted_volumes();
+ MountedVolume *mv = find_mounted_volume_by_mount_point(v->mount_point);
+ if (mv == NULL) {
+ ui_print("Unable to find mounted volume: %s\n", v->mount_point);
+ return NULL;
+ }
+
+ if (strcmp("yaffs2", mv->filesystem) == 0) {
+ return unyaffs_wrapper;
+ }
+
+ return tar_extract_wrapper;
+}
+
int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) {
int ret = 0;
char* name = basename(mount_point);
@@ -259,7 +366,7 @@
ensure_directory(mount_point);
- unyaffs_callback callback = NULL;
+ file_event_callback callback = NULL;
if (0 != stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info)) {
callback = yaffs_callback;
}
@@ -281,7 +388,12 @@
return ret;
}
- if (0 != (ret = unyaffs(tmp, mount_point, callback))) {
+ nandroid_restore_handler restore_handler = get_restore_handler(mount_point);
+ if (restore_handler == NULL) {
+ ui_print("Error finding an appropriate restore handler.\n");
+ return -2;
+ }
+ if (0 != (ret = restore_handler(tmp, mount_point, callback))) {
ui_print("Error while restoring %s!\n", mount_point);
return ret;
}
diff --git a/roots.c b/roots.c
index 4ecc4dd..49b7729 100644
--- a/roots.c
+++ b/roots.c
@@ -167,6 +167,16 @@
int ensure_path_mounted(const char* path) {
Volume* v = volume_for_path(path);
if (v == NULL) {
+ // no /sdcard? let's assume /data/media
+ if (strstr(path, "/sdcard") == path) {
+ LOGW("using /data/media, no /sdcard found.\n");
+ int ret;
+ if (0 != (ret = ensure_path_mounted("/data")))
+ return ret;
+ rmdir("/sdcard");
+ symlink("/data/media", "/sdcard");
+ return 0;
+ }
LOGE("unknown volume for path [%s]\n", path);
return -1;
}
@@ -227,8 +237,17 @@
}
int ensure_path_unmounted(const char* path) {
+ // if we are using /data/media, do not ever unmount volumes /data or /sdcard
+ if (volume_for_path("/sdcard") == NULL && (strstr(path, "/sdcard") == path || strstr(path, "/data") == path)) {
+ return 0;
+ }
+
Volume* v = volume_for_path(path);
if (v == NULL) {
+ // no /sdcard? let's assume /data/media
+ if (strstr(path, "/sdcard") == path) {
+ return ensure_path_unmounted("/data");
+ }
LOGE("unknown volume for path [%s]\n", path);
return -1;
}