Merge "Add 'adb restore' to parallel 'adb backup'"
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_SRC_FILES := \
adb.c \
- backup_service.c \
console.c \
transport.c \
transport_local.c \
diff --git a/adb/adb.h b/adb/adb.h
index 318a2d8..92dc62e 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -304,7 +304,11 @@
#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 @@
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 @@
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 @@
" 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 @@
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 @@
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 @@
} 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) {