From 4b35c01e3e1fdf80b85ef417f3c3bcedeccbe442 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Fri, 19 Apr 2013 12:41:09 -0700 Subject: [PATCH 1/3] adb: added support for adb pull -a to preserve time stamps and mode Added -a flag to adb pull that preserves time and mode. Mode is subjected to umask for security. We only receive modification time from adb server, so creation time will be set to the modification time as well. Signed-off-by: Lajos Molnar (cherry picked from commit de8ff4adcaa487259f9ddcd0eab4d1117d1cca71) Change-Id: I03bb5cc14ce542299cf3b221a8be318a28ee8a8d --- adb/commandline.c | 26 +++++++++++++------ adb/file_sync_client.c | 55 +++++++++++++++++++++-------------------- adb/file_sync_service.h | 2 +- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/adb/commandline.c b/adb/commandline.c index 18dc6e0fa..9cba7519d 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -110,9 +110,10 @@ void help() " adb push [-p] \n" " - copy file/dir to device\n" " ('-p' to display the transfer progress)\n" - " adb pull [-p] []\n" + " adb pull [-p] [-a] []\n" " - copy file/dir from device\n" " ('-p' to display the transfer progress)\n" + " ('-a' means copy timestamp and mode)\n" " adb sync [ ] - copy host->device only if changed\n" " (-l means list but don't copy)\n" " (see 'adb help all')\n" @@ -939,12 +940,19 @@ static const char *find_product_out_path(const char *hint) } -static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2, - int* show_progress) { +static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2, + int *show_progress, int *copy_attrs) { *show_progress = 0; + *copy_attrs = 0; - if ((narg > 0) && !strcmp(*arg, "-p")) { - *show_progress = 1; + while (narg > 0) { + if (!strcmp(*arg, "-p")) { + *show_progress = 1; + } else if (!strcmp(*arg, "-a")) { + *copy_attrs = 1; + } else { + break; + } ++arg; --narg; } @@ -1415,9 +1423,10 @@ top: if(!strcmp(argv[0], "push")) { int show_progress = 0; + int copy_attrs = 0; // unused const char* lpath = NULL, *rpath = NULL; - parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress); + parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, ©_attrs); if ((lpath != NULL) && (rpath != NULL)) { return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress); @@ -1428,12 +1437,13 @@ top: if(!strcmp(argv[0], "pull")) { int show_progress = 0; + int copy_attrs = 0; const char* rpath = NULL, *lpath = "."; - parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress); + parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, ©_attrs); if (rpath != NULL) { - return do_sync_pull(rpath, lpath, show_progress); + return do_sync_pull(rpath, lpath, show_progress, copy_attrs); } return usage(); diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c index dc4e77fbc..3f540c14b 100644 --- a/adb/file_sync_client.c +++ b/adb/file_sync_client.c @@ -139,7 +139,8 @@ struct syncsendbuf { static syncsendbuf send_buffer; -int sync_readtime(int fd, const char *path, unsigned *timestamp) +int sync_readtime(int fd, const char *path, unsigned int *timestamp, + unsigned int *mode) { syncmsg msg; int len = strlen(path); @@ -161,6 +162,7 @@ int sync_readtime(int fd, const char *path, unsigned *timestamp) } *timestamp = ltohl(msg.stat.time); + *mode = ltohl(msg.stat.mode); return 0; } @@ -237,7 +239,7 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show if (show_progress) { // Determine local file size. struct stat st; - if (lstat(path, &st)) { + if (fstat(lfd, &st)) { fprintf(stderr,"cannot stat '%s': %s\n", path, strerror(errno)); return -1; } @@ -931,8 +933,21 @@ static int remote_build_list(int syncfd, copyinfo **filelist, return 0; } +static int set_time_and_mode(const char *lpath, unsigned int time, unsigned int mode) +{ + struct timeval times[2] = { {time, 0}, {time, 0} }; + int r1 = utimes(lpath, times); + + /* use umask for permissions */ + mode_t mask=umask(0000); + umask(mask); + int r2 = chmod(lpath, mode & ~mask); + + return r1 ? : r2; +} + static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, - int checktimestamps) + int copy_attrs) { copyinfo *filelist = 0; copyinfo *ci, *next; @@ -962,26 +977,6 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, return -1; } -#if 0 - if (checktimestamps) { - for (ci = filelist; ci != 0; ci = ci->next) { - if (sync_start_readtime(fd, ci->dst)) { - return 1; - } - } - for (ci = filelist; ci != 0; ci = ci->next) { - unsigned int timestamp, mode, size; - if (sync_finish_readtime(fd, ×tamp, &mode, &size)) - return 1; - if (size == ci->size) { - /* for links, we cannot update the atime/mtime */ - if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) || - (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) - ci->flag = 1; - } - } - } -#endif for (ci = filelist; ci != 0; ci = next) { next = ci->next; if (ci->flag == 0) { @@ -989,6 +984,10 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) { return 1; } + + if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) { + return 1; + } pulled++; } else { skipped++; @@ -1003,9 +1002,9 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, return 0; } -int do_sync_pull(const char *rpath, const char *lpath, int show_progress) +int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int copy_attrs) { - unsigned mode; + unsigned mode, time; struct stat st; int fd; @@ -1016,7 +1015,7 @@ int do_sync_pull(const char *rpath, const char *lpath, int show_progress) return 1; } - if(sync_readmode(fd, rpath, &mode)) { + if(sync_readtime(fd, rpath, &time, &mode)) { return 1; } if(mode == 0) { @@ -1047,13 +1046,15 @@ int do_sync_pull(const char *rpath, const char *lpath, int show_progress) if (sync_recv(fd, rpath, lpath, show_progress)) { return 1; } else { + if (copy_attrs && set_time_and_mode(lpath, time, mode)) + return 1; END(); sync_quit(fd); return 0; } } else if(S_ISDIR(mode)) { BEGIN(); - if (copy_remote_dir_local(fd, rpath, lpath, 0)) { + if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) { return 1; } else { END(); diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h index 3e7e096c1..8ea239ec0 100644 --- a/adb/file_sync_service.h +++ b/adb/file_sync_service.h @@ -80,7 +80,7 @@ void file_sync_service(int fd, void *cookie); int do_sync_ls(const char *path); int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int show_progress); int do_sync_sync(const char *lpath, const char *rpath, int listonly); -int do_sync_pull(const char *rpath, const char *lpath, int show_progress); +int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int pullTime); #define SYNC_DATA_MAX (64*1024) From eb97987332e2e5f7c5eb90d82d853f698a040b14 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 26 May 2014 18:30:43 -0700 Subject: [PATCH 2/3] Add "exec" service: shell commands with no pty. To facilitate device scripts that want to read/write binary data from the host side, this change introduces a new "exec" service that behaves like "shell" but without creating a pty, which would otherwise mangle binary data. After forking, it hooks up stdin/stdout of the child process to the socket connected through to the host. The adb transport doesn't support shutdown(), so the host can't half-close the socket and wait for device termination. Instead, the host side now has two explicit commands "exec-in" and "exec-out" for either sending or receiving data. Teach host side copy_to_file() to deal with stdin/stdout special cases. Switch device side backup/restore services to use the new create_subproc_raw under the hood. (cherry picked from commit 5d9d434efadf1c535c7fea634d5306e18c68ef1f) Change-Id: I42c18cb5bb907449b458c94450ef6c584d84ecdb --- adb/Android.mk | 1 - adb/adb.h | 12 ++-- adb/backup_service.c | 152 ------------------------------------------- adb/commandline.c | 72 +++++++++++++++----- adb/services.c | 152 ++++++++++++++++++++++++++++++------------- 5 files changed, 171 insertions(+), 218 deletions(-) delete mode 100644 adb/backup_service.c diff --git a/adb/Android.mk b/adb/Android.mk index 50e28a616..80427b8e6 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -102,7 +102,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ adb.c \ - backup_service.c \ fdevent.c \ transport.c \ transport_local.c \ diff --git a/adb/adb.h b/adb/adb.h index 2504f9926..4704abbb6 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -326,11 +326,6 @@ int create_jdwp_connection_fd(int jdwp_pid); int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd); #if !ADB_HOST -typedef enum { - BACKUP, - RESTORE -} BackupOperation; -int backup_service(BackupOperation operation, char* args); void framebuffer_service(int fd, void *cookie); void remount_service(int fd, void *cookie); #endif @@ -418,7 +413,7 @@ void adb_qemu_trace(const char* fmt, ...); # define D(...) ((void)0) # define DR(...) ((void)0) # define ADB_TRACING 0 -#endif +#endif /* ADB_TRACE */ #if !DEBUG_PACKETS @@ -476,6 +471,11 @@ int connection_state(atransport *t); extern int HOST; extern int SHELL_EXIT_NOTIFY_FD; +typedef enum { + SUBPROC_PTY = 0, + SUBPROC_RAW = 1, +} subproc_mode; + #define CHUNK_SIZE (64*1024) #if !ADB_HOST diff --git a/adb/backup_service.c b/adb/backup_service.c deleted file mode 100644 index 654e0f32d..000000000 --- a/adb/backup_service.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 -#include - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_ADB -#include "adb.h" - -typedef struct { - pid_t pid; - int fd; -} backup_harvest_params; - -// socketpair but do *not* mark as close_on_exec -static int backup_socketpair(int sv[2]) { - int rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); - if (rc < 0) - return -1; - - return 0; -} - -// harvest the child process then close the read end of the socketpair -static void* backup_child_waiter(void* args) { - int status; - backup_harvest_params* params = (backup_harvest_params*) args; - - waitpid(params->pid, &status, 0); - adb_close(params->fd); - free(params); - return NULL; -} - -/* returns the data socket passing the backup data here for forwarding */ -int backup_service(BackupOperation op, char* args) { - pid_t pid; - int s[2]; - char* operation; - - // Command string depends on our invocation - if (op == BACKUP) { - operation = "backup"; - } else { - operation = "restore"; - } - - 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 (backup_socketpair(s)) { - D("can't create backup/restore socketpair\n"); - fprintf(stderr, "unable to create backup/restore socketpair\n"); - return -1; - } - - D("Backup/restore socket pair: (send=%d, receive=%d)\n", s[1], s[0]); - close_on_exec(s[0]); // only the side we hold on to - - // spin off the child process to run the backup command - pid = fork(); - if (pid < 0) { - // failure - 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; - } - - // Great, we're off and running. - if (pid == 0) { - // child -- actually run the backup here - char* p; - int argc; - char portnum[16]; - char** bu_args; - - // fixed args: [0] is 'bu', [1] is the port number, [2] is the 'operation' string - argc = 3; - for (p = (char*)args; p && *p; ) { - argc++; - while (*p && *p != ':') p++; - if (*p == ':') p++; - } - - bu_args = (char**) alloca(argc*sizeof(char*) + 1); - - // run through again to build the argv array - argc = 0; - bu_args[argc++] = "bu"; - snprintf(portnum, sizeof(portnum), "%d", s[1]); - bu_args[argc++] = portnum; - bu_args[argc++] = operation; - for (p = (char*)args; p && *p; ) { - bu_args[argc++] = p; - while (*p && *p != ':') p++; - if (*p == ':') { - *p = 0; - p++; - } - } - 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]); - - // off we go - 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); - } else { - adb_thread_t t; - backup_harvest_params* params; - - // parent, i.e. adbd -- close the sending half of the socket - D("fork() returned pid %d\n", pid); - adb_close(s[1]); - - // spin a thread to harvest the child process - params = (backup_harvest_params*) malloc(sizeof(backup_harvest_params)); - params->pid = pid; - params->fd = s[0]; - if (adb_thread_create(&t, backup_child_waiter, params)) { - adb_close(s[0]); - free(params); - D("Unable to create child harvester\n"); - return -1; - } - } - - // we'll be reading from s[0] as the data is sent by the child process - return s[0]; -} diff --git a/adb/commandline.c b/adb/commandline.c index 9cba7519d..1ba60499c 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -286,8 +286,17 @@ static void copy_to_file(int inFd, int outFd) { long total = 0; D("copy_to_file(%d -> %d)\n", inFd, outFd); +#ifdef HAVE_TERMIO_H + if (inFd == STDIN_FILENO) { + stdin_raw_init(STDIN_FILENO); + } +#endif for (;;) { - len = adb_read(inFd, buf, BUFSIZE); + if (inFd == STDIN_FILENO) { + len = unix_read(inFd, buf, BUFSIZE); + } else { + len = adb_read(inFd, buf, BUFSIZE); + } if (len == 0) { D("copy_to_file() : read 0 bytes; exiting\n"); break; @@ -300,9 +309,19 @@ static void copy_to_file(int inFd, int outFd) { D("copy_to_file() : error %d\n", errno); break; } - adb_write(outFd, buf, len); + if (outFd == STDOUT_FILENO) { + fwrite(buf, 1, len, stdout); + fflush(stdout); + } else { + adb_write(outFd, buf, len); + } total += len; } +#ifdef HAVE_TERMIO_H + if (inFd == STDIN_FILENO) { + stdin_raw_restore(STDIN_FILENO); + } +#endif D("copy_to_file() finished after %lu bytes\n", total); free(buf); } @@ -939,7 +958,6 @@ static const char *find_product_out_path(const char *hint) return path_buf; } - static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2, int *show_progress, int *copy_attrs) { *show_progress = 0; @@ -976,7 +994,6 @@ int adb_commandline(int argc, char **argv) int is_server = 0; int persist = 0; int r; - int quote; transport_type ttype = kTransportAny; char* serial = NULL; char* server_port_str = NULL; @@ -1197,19 +1214,14 @@ top: return r; } - snprintf(buf, sizeof buf, "shell:%s", argv[1]); + snprintf(buf, sizeof(buf), "shell:%s", argv[1]); argc -= 2; argv += 2; - while(argc-- > 0) { - strcat(buf, " "); - - /* quote empty strings and strings with spaces */ - quote = (**argv == 0 || strchr(*argv, ' ')); - if (quote) - strcat(buf, "\""); - strcat(buf, *argv++); - if (quote) - strcat(buf, "\""); + while (argc-- > 0) { + char *quoted = dupAndQuote(*argv++); + strncat(buf, " ", sizeof(buf) - 1); + strncat(buf, quoted, sizeof(buf) - 1); + free(quoted); } for(;;) { @@ -1241,6 +1253,36 @@ top: } } + if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) { + int exec_in = !strcmp(argv[0], "exec-in"); + int fd; + + snprintf(buf, sizeof buf, "exec:%s", argv[1]); + argc -= 2; + argv += 2; + while (argc-- > 0) { + char *quoted = dupAndQuote(*argv++); + strncat(buf, " ", sizeof(buf) - 1); + strncat(buf, quoted, sizeof(buf) - 1); + free(quoted); + } + + fd = adb_connect(buf); + if (fd < 0) { + fprintf(stderr, "error: %s\n", adb_error()); + return -1; + } + + if (exec_in) { + copy_to_file(STDIN_FILENO, fd); + } else { + copy_to_file(fd, STDOUT_FILENO); + } + + adb_close(fd); + return 0; + } + if(!strcmp(argv[0], "kill-server")) { int fd; fd = _adb_connect("host:kill"); diff --git a/adb/services.c b/adb/services.c index 7b809da94..d1e8939c9 100644 --- a/adb/services.c +++ b/adb/services.c @@ -184,11 +184,26 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) } #if !ADB_HOST -static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) + +static void init_subproc_child() { + setsid(); + + // Set OOM adjustment to prevent killing + int fd = adb_open("/proc/self/oom_adj", O_WRONLY); + if (fd >= 0) { + adb_write(fd, "0", 1); + adb_close(fd); + } else { + D("adb: unable to update oom_adj\n"); + } +} + +static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) +{ + D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); #ifdef HAVE_WIN32_PROC - D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); - fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); + fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); return -1; #else /* !HAVE_WIN32_PROC */ char *devname; @@ -215,47 +230,74 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 return -1; } - if(*pid == 0){ - int pts; + if (*pid == 0) { + init_subproc_child(); - setsid(); - - pts = unix_open(devname, O_RDWR); - if(pts < 0) { + int pts = unix_open(devname, O_RDWR); + if (pts < 0) { fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); exit(-1); } - dup2(pts, 0); - dup2(pts, 1); - dup2(pts, 2); + dup2(pts, STDIN_FILENO); + dup2(pts, STDOUT_FILENO); + dup2(pts, STDERR_FILENO); adb_close(pts); adb_close(ptm); - // set OOM adjustment to zero - char text[64]; - snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); - int fd = adb_open(text, O_WRONLY); - if (fd >= 0) { - adb_write(fd, "0", 1); - adb_close(fd); - } else { - D("adb: unable to open %s\n", text); - } execl(cmd, cmd, arg0, arg1, NULL); fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", cmd, strerror(errno), errno); exit(-1); } else { - // Don't set child's OOM adjustment to zero. - // Let the child do it itself, as sometimes the parent starts - // running before the child has a /proc/pid/oom_adj. - // """adb: unable to open /proc/644/oom_adj""" seen in some logs. return ptm; } #endif /* !HAVE_WIN32_PROC */ } + +static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) +{ + D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); +#ifdef HAVE_WIN32_PROC + fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); + return -1; +#else /* !HAVE_WIN32_PROC */ + + // 0 is parent socket, 1 is child socket + int sv[2]; + if (unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) { + printf("[ cannot create socket pair - %s ]\n", strerror(errno)); + return -1; + } + + *pid = fork(); + if (*pid < 0) { + printf("- fork failed: %s -\n", strerror(errno)); + adb_close(sv[0]); + adb_close(sv[1]); + return -1; + } + + if (*pid == 0) { + adb_close(sv[0]); + init_subproc_child(); + + // Only hook up stdin/stdout; drop stderr + dup2(sv[1], STDIN_FILENO); + dup2(sv[1], STDOUT_FILENO); + adb_close(sv[1]); + + execl(cmd, cmd, arg0, arg1, NULL); + fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", + cmd, strerror(errno), errno); + exit(-1); + } else { + adb_close(sv[1]); + return sv[0]; + } +#endif /* !HAVE_WIN32_PROC */ +} #endif /* !ABD_HOST */ #if ADB_HOST @@ -296,18 +338,32 @@ static void subproc_waiter_service(int fd, void *cookie) } } -static int create_subproc_thread(const char *name) +static int create_subproc_thread(const char *name, const subproc_mode mode) { stinfo *sti; adb_thread_t t; int ret_fd; - pid_t pid; - if(name) { - ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid); + pid_t pid = -1; + + const char *arg0, *arg1; + if (name == 0 || *name == 0) { + arg0 = "-"; arg1 = 0; } else { - ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid); + arg0 = "-c"; arg1 = name; } - D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); + + switch (mode) { + case SUBPROC_PTY: + ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid); + break; + case SUBPROC_RAW: + ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid); + break; + default: + fprintf(stderr, "invalid subproc_mode %d\n", mode); + return -1; + } + D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid); sti = malloc(sizeof(stinfo)); if(sti == 0) fatal("cannot allocate stinfo"); @@ -315,14 +371,14 @@ static int create_subproc_thread(const char *name) sti->cookie = (void*) (uintptr_t) pid; sti->fd = ret_fd; - if(adb_thread_create( &t, service_bootstrap_func, sti)){ + if (adb_thread_create(&t, service_bootstrap_func, sti)) { free(sti); adb_close(ret_fd); - printf("cannot create service thread\n"); + fprintf(stderr, "cannot create service thread\n"); return -1; } - D("service thread started, fd=%d pid=%d\n",ret_fd, pid); + D("service thread started, fd=%d pid=%d\n", ret_fd, pid); return ret_fd; } #endif @@ -367,27 +423,35 @@ int service_to_fd(const char *name) } else if (!strncmp(name, "jdwp:", 5)) { ret = create_jdwp_connection_fd(atoi(name+5)); } else if(!HOST && !strncmp(name, "shell:", 6)) { - if(name[6]) { - ret = create_subproc_thread(name + 6); - } else { - ret = create_subproc_thread(0); - } + ret = create_subproc_thread(name + 6, SUBPROC_PTY); + } else if(!HOST && !strncmp(name, "exec:", 5)) { + ret = create_subproc_thread(name + 5, SUBPROC_RAW); } else if(!strncmp(name, "sync:", 5)) { ret = create_service_thread(file_sync_service, NULL); } else if(!strncmp(name, "remount:", 8)) { ret = create_service_thread(remount_service, NULL); } else if(!strncmp(name, "reboot:", 7)) { void* arg = strdup(name + 7); - if(arg == 0) return -1; + if (arg == NULL) return -1; 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); + char* arg = strdup(name + 7); if (arg == NULL) return -1; - ret = backup_service(BACKUP, arg); + char* c = arg; + for (; *c != '\0'; c++) { + if (*c == ':') + *c = ' '; + } + char* cmd; + if (asprintf(&cmd, "/system/bin/bu backup %s", arg) != -1) { + ret = create_subproc_thread(cmd, SUBPROC_RAW); + free(cmd); + } + free(arg); } else if(!strncmp(name, "restore:", 8)) { - ret = backup_service(RESTORE, NULL); + ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW); } else if(!strncmp(name, "tcpip:", 6)) { int port; if (sscanf(name + 6, "%d", &port) == 0) { From 1b3f2ff0286da1f06e095e8d96ce8aefe874b6aa Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 20 Jun 2014 16:30:54 -0700 Subject: [PATCH 3/3] adb: use oom_score_adj instead of oom_adj (cherry picked from commit 07ce7cab72d9b3e5c701491daf8fd457d035eec8) Change-Id: I1730d1df34039a5502200002ac813ce96a3eaa1a --- adb/services.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adb/services.c b/adb/services.c index d1e8939c9..e48e4603e 100644 --- a/adb/services.c +++ b/adb/services.c @@ -189,13 +189,13 @@ static void init_subproc_child() { setsid(); - // Set OOM adjustment to prevent killing - int fd = adb_open("/proc/self/oom_adj", O_WRONLY); + // Set OOM score adjustment to prevent killing + int fd = adb_open("/proc/self/oom_score_adj", O_WRONLY); if (fd >= 0) { adb_write(fd, "0", 1); adb_close(fd); } else { - D("adb: unable to update oom_adj\n"); + D("adb: unable to update oom_score_adj\n"); } }