diff options
author | Jeff Sharkey <jsharkey@android.com> | 2014-05-26 18:30:43 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2014-05-30 11:27:56 -0700 |
commit | 5d9d434efadf1c535c7fea634d5306e18c68ef1f (patch) | |
tree | 897d509ea4528bbb795b4ab4e2217086ef421c95 /adb/backup_service.c | |
parent | abcb99927d9ad3f66288a5ce16d7c86c14b49249 (diff) | |
download | system_core-5d9d434efadf1c535c7fea634d5306e18c68ef1f.zip system_core-5d9d434efadf1c535c7fea634d5306e18c68ef1f.tar.gz system_core-5d9d434efadf1c535c7fea634d5306e18c68ef1f.tar.bz2 |
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.
Change-Id: I5993049803519d3959761f2363037b02c50920ee
Diffstat (limited to 'adb/backup_service.c')
-rw-r--r-- | adb/backup_service.c | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/adb/backup_service.c b/adb/backup_service.c deleted file mode 100644 index 654e0f3..0000000 --- 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 <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]; -} |