Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 574ebc41 authored by Christopher Tate's avatar Christopher Tate Committed by Android (Google) Code Review
Browse files

Merge "Add 'adb backup' for pulling a full backup tarfile to the host"

parents 0ab886bd d2f5415c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -113,6 +113,7 @@ include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
	adb.c \
	backup_service.c \
	fdevent.c \
	transport.c \
	transport_local.c \
@@ -164,6 +165,7 @@ LOCAL_LDLIBS := -lrt -lncurses -lpthread

LOCAL_SRC_FILES := \
	adb.c \
	backup_service.c \
	console.c \
	transport.c \
	transport_local.c \
+2 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
#define ADB_VERSION_MAJOR 1         // Used for help/version information
#define ADB_VERSION_MINOR 0         // Used for help/version information

#define ADB_SERVER_VERSION    26    // Increment this when we want to force users to start a new adb server
#define ADB_SERVER_VERSION    27    // Increment this when we want to force users to start a new adb server

typedef struct amessage amessage;
typedef struct apacket apacket;
@@ -304,6 +304,7 @@ int create_jdwp_connection_fd(int jdwp_pid);
#endif

#if !ADB_HOST
int backup_service(char* args);
void framebuffer_service(int fd, void *cookie);
void log_service(int fd, void *cookie);
void remount_service(int fd, void *cookie);

adb/backup_service.c

0 → 100644
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unistd.h>
#include <stdio.h>

#include "sysdeps.h"

#define TRACE_TAG  TRACE_ADB
#include "adb.h"

/* returns the data socket passing the backup data here for forwarding */
int backup_service(char* args) {
    pid_t pid;
    int s[2];

    D("backup_service(%s)\n", 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");
        return -1;
    }

    // spin off the child process to run the backup command
    pid = fork();
    if (pid < 0) {
        // failure
        D("can't fork for backup\n");
        fprintf(stderr, "unable to fork for backup\n");
        adb_close(s[0]);
        adb_close(s[1]);
        return -1;
    }

    // Great, we're off and running.
    if (pid == 0) {
        char* p;
        int argc;
        char** backup_args;

        // child -- actually run the backup here
        argc = 1; // room for the basic 'bu' argv[0]
        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";
        argc = 1;   // run through again to build the argv array
        for (p = (char*)args; *p; ) {
            backup_args[argc++] = p;
            while (*p && *p != ':') p++;
            if (*p == ':') {
                *p = 0;
                p++;
            }
        }
        backup_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);

        // off we go
        execvp("/system/bin/bu", (char * const *)backup_args);
        // oops error - close up shop and go home
        fprintf(stderr, "Unable to exec 'bu', bailing\n");
        exit(-1);
    } else {
        // parent, i.e. adbd -- close the sending half of the socket
        adb_close(s[1]);
    }

    // we'll be reading from s[0] as the data is sent by the child process
    return s[0];
}
+75 −0
Original line number Diff line number Diff line
@@ -129,6 +129,19 @@ void help()
        "  adb bugreport                - return all information from the device\n"
        "                                 that should be included in a bug report.\n"
        "\n"
        "  adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [<packages...>]\n"
        "                               - Write a tarfile backup of the device's data to <file>.\n"
        "                                 The -f option must come first; if not specified then the data\n"
        "                                 is written to \"backup.tar\" in the current directory.\n"
        "                                 (-apk|-noapk enable/disable backup of the .apks themselves\n"
        "                                    in the tarfile; the default is noapk.)\n"
        "                                 (-shared|-noshared enable/disable backup of the device's\n"
        "                                    shared storage / SD card contents; the default is noshared.)\n"
        "                                 (-all means to back up all installed applications)\n"
        "                                 (<packages...> is the list of applications to be backed up.  If\n"
        "                                    the -all or -shared flags are passed, then the package\n"
        "                                    list is optional.)\n"
        "\n"
        "  adb help                     - show this help message\n"
        "  adb version                  - show version num\n"
        "\n"
@@ -223,6 +236,25 @@ static void read_and_dump(int fd)
    }
}

static void copy_to_file(int inFd, int outFd) {
    char buf[4096];
    int len;

    D("copy_to_file(%d -> %d)\n", inFd, outFd);
    for (;;) {
        len = adb_read(inFd, buf, sizeof(buf));
        if (len == 0) {
            break;
        }
        if (len < 0) {
            if (errno == EINTR) continue;
            D("copy_to_file() : error %d\n", errno);
            break;
        }
        adb_write(outFd, buf, len);
    }
}

static void *stdin_read_thread(void *x)
{
    int fd, fdi;
@@ -530,6 +562,45 @@ static int logcat(transport_type transport, char* serial, int argc, char **argv)
    return 0;
}

static int backup(int argc, char** argv) {
    char buf[4096];
    const char* filename = "./backup.tar";
    int fd, outFd;

    if (!strcmp("-f", argv[1])) {
        if (argc < 3) return usage();
        filename = argv[2];
        argc -= 2;
        argv += 2;
    }

    outFd = adb_open_mode(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
    if (outFd < 0) {
        fprintf(stderr, "adb: unable to open file %s\n", filename);
        return -1;
    }

    snprintf(buf, sizeof(buf), "backup");
    for (argc--, argv++; argc; argc--, argv++) {
        strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
        strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
    }

    D("backup. filename=%s buf=%s\n", filename, buf);
    fd = adb_connect(buf);
    if (fd < 0) {
        fprintf(stderr, "adb: unable to connect for backup\n");
        adb_close(outFd);
        return -1;
    }

    copy_to_file(fd, outFd);

    adb_close(fd);
    adb_close(outFd);
    return 0;
}

#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
static int top_works(const char *top)
{
@@ -1089,6 +1160,10 @@ top:
        return adb_connect("host:start-server");
    }

    if (!strcmp(argv[0], "backup")) {
        return backup(argc, argv);
    }

    if (!strcmp(argv[0], "jdwp")) {
        int  fd = adb_connect("jdwp");
        if (fd >= 0) {
+4 −0
Original line number Diff line number Diff line
@@ -479,6 +479,10 @@ int service_to_fd(const char *name)
        ret = create_service_thread(reboot_service, arg);
    } else if(!strncmp(name, "root:", 5)) {
        ret = create_service_thread(restart_root_service, NULL);
    } else if(!strncmp(name, "backup:", 7)) {
        char* arg = strdup(name+7);
        if (arg == NULL) return -1;
        ret = backup_service(arg);
    } else if(!strncmp(name, "tcpip:", 6)) {
        int port;
        if (sscanf(name + 6, "%d", &port) == 0) {