diff options
-rw-r--r-- | adb/Android.mk | 1 | ||||
-rw-r--r-- | adb/adb.h | 6 | ||||
-rw-r--r-- | adb/backup_service.c | 43 | ||||
-rw-r--r-- | adb/commandline.c | 33 | ||||
-rw-r--r-- | adb/services.c | 4 |
5 files changed, 68 insertions, 19 deletions
diff --git a/adb/Android.mk b/adb/Android.mk index e893ca9..2ac9335 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -165,7 +165,6 @@ LOCAL_LDLIBS := -lrt -lncurses -lpthread LOCAL_SRC_FILES := \ adb.c \ - backup_service.c \ console.c \ transport.c \ transport_local.c \ @@ -304,7 +304,11 @@ int create_jdwp_connection_fd(int jdwp_pid); #endif #if !ADB_HOST -int backup_service(char* args); +typedef enum { + BACKUP, + RESTORE +} BackupOperation; +int backup_service(BackupOperation operation, char* args); void framebuffer_service(int fd, void *cookie); void log_service(int fd, void *cookie); void remount_service(int fd, void *cookie); diff --git a/adb/backup_service.c b/adb/backup_service.c index 1e55efc..2e6e754 100644 --- a/adb/backup_service.c +++ b/adb/backup_service.c @@ -23,17 +23,28 @@ #include "adb.h" /* returns the data socket passing the backup data here for forwarding */ -int backup_service(char* args) { +int backup_service(BackupOperation op, char* args) { pid_t pid; int s[2]; + char* operation; + int socketnum; - D("backup_service(%s)\n", args); + // Command string and choice of stdin/stdout for the pipe depend on our invocation + if (op == BACKUP) { + operation = "backup"; + socketnum = STDOUT_FILENO; + } else { + operation = "restore"; + socketnum = STDIN_FILENO; + } + + D("backup_service(%s, %s)\n", operation, args); // set up the pipe from the subprocess to here // parent will read s[0]; child will write s[1] if (adb_socketpair(s)) { - D("can't create backup socketpair\n"); - fprintf(stderr, "unable to create backup socketpair\n"); + D("can't create backup/restore socketpair\n"); + fprintf(stderr, "unable to create backup/restore socketpair\n"); return -1; } @@ -41,8 +52,8 @@ int backup_service(char* args) { pid = fork(); if (pid < 0) { // failure - D("can't fork for backup\n"); - fprintf(stderr, "unable to fork for backup\n"); + D("can't fork for %s\n", operation); + fprintf(stderr, "unable to fork for %s\n", operation); adb_close(s[0]); adb_close(s[1]); return -1; @@ -52,37 +63,37 @@ int backup_service(char* args) { if (pid == 0) { char* p; int argc; - char** backup_args; + char** bu_args; // child -- actually run the backup here - argc = 2; // room for the basic 'bu' argv[0] and 'backup' argv[1] + argc = 2; // room for the basic 'bu' argv[0] and '[operation]' argv[1] for (p = (char*)args; p && *p; ) { argc++; while (*p && *p != ':') p++; if (*p == ':') p++; } - backup_args = (char**) alloca(argc*sizeof(char*) + 1); - backup_args[0] = "bu"; - backup_args[1] = "backup"; + bu_args = (char**) alloca(argc*sizeof(char*) + 1); + bu_args[0] = "bu"; + bu_args[1] = operation; argc = 2; // run through again to build the argv array - for (p = (char*)args; *p; ) { - backup_args[argc++] = p; + for (p = (char*)args; p && *p; ) { + bu_args[argc++] = p; while (*p && *p != ':') p++; if (*p == ':') { *p = 0; p++; } } - backup_args[argc] = NULL; + bu_args[argc] = NULL; // Close the half of the socket that we don't care about, route 'bu's console // to the output socket, and off we go adb_close(s[0]); - dup2(s[1], STDOUT_FILENO); + dup2(s[1], socketnum); // off we go - execvp("/system/bin/bu", (char * const *)backup_args); + execvp("/system/bin/bu", (char * const *)bu_args); // oops error - close up shop and go home fprintf(stderr, "Unable to exec 'bu', bailing\n"); exit(-1); diff --git a/adb/commandline.c b/adb/commandline.c index 733cbff..460120e 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -142,6 +142,8 @@ void help() " the -all or -shared flags are passed, then the package\n" " list is optional.)\n" "\n" + " adb restore <file> - restore device contents from the <file> backup tarfile\n" + "\n" " adb help - show this help message\n" " adb version - show version num\n" "\n" @@ -601,6 +603,33 @@ static int backup(int argc, char** argv) { return 0; } +static int restore(int argc, char** argv) { + const char* filename; + int fd, tarFd; + + if (argc != 2) return usage(); + + filename = argv[1]; + tarFd = adb_open(filename, O_RDONLY); + if (tarFd < 0) { + fprintf(stderr, "adb: unable to open file %s\n", filename); + return -1; + } + + fd = adb_connect("restore:"); + if (fd < 0) { + fprintf(stderr, "adb: unable to connect for backup\n"); + adb_close(tarFd); + return -1; + } + + copy_to_file(tarFd, fd); + + adb_close(fd); + adb_close(tarFd); + return 0; +} + #define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make" static int top_works(const char *top) { @@ -1164,6 +1193,10 @@ top: return backup(argc, argv); } + if (!strcmp(argv[0], "restore")) { + return restore(argc, argv); + } + if (!strcmp(argv[0], "jdwp")) { int fd = adb_connect("jdwp"); if (fd >= 0) { diff --git a/adb/services.c b/adb/services.c index ec0b0ba..6bbd6f8 100644 --- a/adb/services.c +++ b/adb/services.c @@ -482,7 +482,9 @@ int service_to_fd(const char *name) } else if(!strncmp(name, "backup:", 7)) { char* arg = strdup(name+7); if (arg == NULL) return -1; - ret = backup_service(arg); + ret = backup_service(BACKUP, arg); + } else if(!strncmp(name, "restore:", 8)) { + ret = backup_service(RESTORE, NULL); } else if(!strncmp(name, "tcpip:", 6)) { int port; if (sscanf(name + 6, "%d", &port) == 0) { |