am 143b9e3d: Merge changes I1730d1df,I42c18cb5,I03bb5cc1
* commit '143b9e3dd6b86d5ac14b6d57588561aed45ab7ca': adb: use oom_score_adj instead of oom_adj Add "exec" service: shell commands with no pty. adb: added support for adb pull -a to preserve time stamps and mode
This commit is contained in:
commit
ad1e41d48c
|
@ -102,7 +102,6 @@ include $(CLEAR_VARS)
|
|||
|
||||
LOCAL_SRC_FILES := \
|
||||
adb.c \
|
||||
backup_service.c \
|
||||
fdevent.c \
|
||||
transport.c \
|
||||
transport_local.c \
|
||||
|
|
12
adb/adb.h
12
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
|
||||
|
|
|
@ -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 <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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];
|
||||
}
|
|
@ -110,9 +110,10 @@ void help()
|
|||
" adb push [-p] <local> <remote>\n"
|
||||
" - copy file/dir to device\n"
|
||||
" ('-p' to display the transfer progress)\n"
|
||||
" adb pull [-p] <remote> [<local>]\n"
|
||||
" adb pull [-p] [-a] <remote> [<local>]\n"
|
||||
" - copy file/dir from device\n"
|
||||
" ('-p' to display the transfer progress)\n"
|
||||
" ('-a' means copy timestamp and mode)\n"
|
||||
" adb sync [ <directory> ] - copy host->device only if changed\n"
|
||||
" (-l means list but don't copy)\n"
|
||||
" (see 'adb help all')\n"
|
||||
|
@ -285,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;
|
||||
|
@ -299,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);
|
||||
}
|
||||
|
@ -938,13 +958,19 @@ 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) {
|
||||
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;
|
||||
}
|
||||
|
@ -968,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;
|
||||
|
@ -1189,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(;;) {
|
||||
|
@ -1233,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");
|
||||
|
@ -1415,9 +1465,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 +1479,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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
152
adb/services.c
152
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 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_score_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) {
|
||||
|
|
Loading…
Reference in New Issue