blob: 4f0c8ac7665b3aa6f1798cdd04ad1dfe4807a41e [file] [log] [blame]
Christopher Tated2f54152011-04-21 12:53:28 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <unistd.h>
18#include <stdio.h>
19
20#include "sysdeps.h"
21
22#define TRACE_TAG TRACE_ADB
23#include "adb.h"
24
Christopher Tate5b811fa2011-06-10 11:38:37 -070025// socketpair but do *not* mark as close_on_exec
26static int backup_socketpair(int sv[2]) {
27 int rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv );
28 if (rc < 0)
29 return -1;
30
31 return 0;
32}
33
34static void* backup_child_waiter(void* pid_cookie) {
35 int status;
36
37 waitpid((pid_t) pid_cookie, &status, 0);
38 D("harvested backup/restore child, status=%d\n", status);
39 return NULL;
40}
41
Christopher Tated2f54152011-04-21 12:53:28 -070042/* returns the data socket passing the backup data here for forwarding */
Christopher Tate702967a2011-05-17 15:52:54 -070043int backup_service(BackupOperation op, char* args) {
Christopher Tated2f54152011-04-21 12:53:28 -070044 pid_t pid;
45 int s[2];
Christopher Tate702967a2011-05-17 15:52:54 -070046 char* operation;
47 int socketnum;
Christopher Tated2f54152011-04-21 12:53:28 -070048
Christopher Tate702967a2011-05-17 15:52:54 -070049 // Command string and choice of stdin/stdout for the pipe depend on our invocation
50 if (op == BACKUP) {
51 operation = "backup";
52 socketnum = STDOUT_FILENO;
53 } else {
54 operation = "restore";
55 socketnum = STDIN_FILENO;
56 }
57
58 D("backup_service(%s, %s)\n", operation, args);
Christopher Tated2f54152011-04-21 12:53:28 -070059
60 // set up the pipe from the subprocess to here
61 // parent will read s[0]; child will write s[1]
Christopher Tate5b811fa2011-06-10 11:38:37 -070062 if (backup_socketpair(s)) {
Christopher Tate702967a2011-05-17 15:52:54 -070063 D("can't create backup/restore socketpair\n");
64 fprintf(stderr, "unable to create backup/restore socketpair\n");
Christopher Tated2f54152011-04-21 12:53:28 -070065 return -1;
66 }
67
Christopher Tate5b811fa2011-06-10 11:38:37 -070068 D("Backup/restore socket pair: (send=%d, receive=%d)\n", s[1], s[0]);
69 close_on_exec(s[0]); // only the side we hold on to
70
Christopher Tated2f54152011-04-21 12:53:28 -070071 // spin off the child process to run the backup command
72 pid = fork();
73 if (pid < 0) {
74 // failure
Christopher Tate702967a2011-05-17 15:52:54 -070075 D("can't fork for %s\n", operation);
76 fprintf(stderr, "unable to fork for %s\n", operation);
Christopher Tated2f54152011-04-21 12:53:28 -070077 adb_close(s[0]);
78 adb_close(s[1]);
79 return -1;
80 }
81
82 // Great, we're off and running.
83 if (pid == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -070084 // child -- actually run the backup here
Christopher Tated2f54152011-04-21 12:53:28 -070085 char* p;
86 int argc;
Christopher Tate5b811fa2011-06-10 11:38:37 -070087 char portnum[16];
Christopher Tate702967a2011-05-17 15:52:54 -070088 char** bu_args;
Christopher Tated2f54152011-04-21 12:53:28 -070089
Christopher Tate5b811fa2011-06-10 11:38:37 -070090 // fixed args: [0] is 'bu', [1] is the port number, [2] is the 'operation' string
91 argc = 3;
Christopher Tated2f54152011-04-21 12:53:28 -070092 for (p = (char*)args; p && *p; ) {
93 argc++;
94 while (*p && *p != ':') p++;
95 if (*p == ':') p++;
96 }
97
Christopher Tate702967a2011-05-17 15:52:54 -070098 bu_args = (char**) alloca(argc*sizeof(char*) + 1);
Christopher Tate5b811fa2011-06-10 11:38:37 -070099
100 // run through again to build the argv array
101 argc = 0;
102 bu_args[argc++] = "bu";
103 snprintf(portnum, sizeof(portnum), "%d", s[1]);
104 bu_args[argc++] = portnum;
105 bu_args[argc++] = operation;
Christopher Tate702967a2011-05-17 15:52:54 -0700106 for (p = (char*)args; p && *p; ) {
107 bu_args[argc++] = p;
Christopher Tated2f54152011-04-21 12:53:28 -0700108 while (*p && *p != ':') p++;
109 if (*p == ':') {
110 *p = 0;
111 p++;
112 }
113 }
Christopher Tate702967a2011-05-17 15:52:54 -0700114 bu_args[argc] = NULL;
Christopher Tated2f54152011-04-21 12:53:28 -0700115
116 // Close the half of the socket that we don't care about, route 'bu's console
117 // to the output socket, and off we go
118 adb_close(s[0]);
Christopher Tated2f54152011-04-21 12:53:28 -0700119
120 // off we go
Christopher Tate702967a2011-05-17 15:52:54 -0700121 execvp("/system/bin/bu", (char * const *)bu_args);
Christopher Tated2f54152011-04-21 12:53:28 -0700122 // oops error - close up shop and go home
123 fprintf(stderr, "Unable to exec 'bu', bailing\n");
124 exit(-1);
125 } else {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700126 adb_thread_t t;
127
Christopher Tated2f54152011-04-21 12:53:28 -0700128 // parent, i.e. adbd -- close the sending half of the socket
Christopher Tate5b811fa2011-06-10 11:38:37 -0700129 D("fork() returned pid %d\n", pid);
Christopher Tated2f54152011-04-21 12:53:28 -0700130 adb_close(s[1]);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700131
132 // spin a thread to harvest the child process
133 if (adb_thread_create(&t, backup_child_waiter, (void*)pid)) {
134 adb_close(s[0]);
135 D("Unable to create child harvester\n");
136 return -1;
137 }
Christopher Tated2f54152011-04-21 12:53:28 -0700138 }
139
140 // we'll be reading from s[0] as the data is sent by the child process
141 return s[0];
142}