Merge "Add 'adb backup' for pulling a full backup tarfile to the host"
This commit is contained in:
commit
574ebc41f8
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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];
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue