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) {