1/*
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
25typedef struct {
26    pid_t pid;
27    int fd;
28} backup_harvest_params;
29
30// socketpair but do *not* mark as close_on_exec
31static int backup_socketpair(int sv[2]) {
32    int rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv );
33    if (rc < 0)
34        return -1;
35
36    return 0;
37}
38
39// harvest the child process then close the read end of the socketpair
40static void* backup_child_waiter(void* args) {
41    int status;
42    backup_harvest_params* params = (backup_harvest_params*) args;
43
44    waitpid(params->pid, &status, 0);
45    adb_close(params->fd);
46    free(params);
47    return NULL;
48}
49
50/* returns the data socket passing the backup data here for forwarding */
51int backup_service(BackupOperation op, char* args) {
52    pid_t pid;
53    int s[2];
54    char* operation;
55    int socketnum;
56
57    // Command string and choice of stdin/stdout for the pipe depend on our invocation
58    if (op == BACKUP) {
59        operation = "backup";
60        socketnum = STDOUT_FILENO;
61    } else {
62        operation = "restore";
63        socketnum = STDIN_FILENO;
64    }
65
66    D("backup_service(%s, %s)\n", operation, args);
67
68    // set up the pipe from the subprocess to here
69    // parent will read s[0]; child will write s[1]
70    if (backup_socketpair(s)) {
71        D("can't create backup/restore socketpair\n");
72        fprintf(stderr, "unable to create backup/restore socketpair\n");
73        return -1;
74    }
75
76    D("Backup/restore socket pair: (send=%d, receive=%d)\n", s[1], s[0]);
77    close_on_exec(s[0]);    // only the side we hold on to
78
79    // spin off the child process to run the backup command
80    pid = fork();
81    if (pid < 0) {
82        // failure
83        D("can't fork for %s\n", operation);
84        fprintf(stderr, "unable to fork for %s\n", operation);
85        adb_close(s[0]);
86        adb_close(s[1]);
87        return -1;
88    }
89
90    // Great, we're off and running.
91    if (pid == 0) {
92        // child -- actually run the backup here
93        char* p;
94        int argc;
95        char portnum[16];
96        char** bu_args;
97
98        // fixed args:  [0] is 'bu', [1] is the port number, [2] is the 'operation' string
99        argc = 3;
100        for (p = (char*)args; p && *p; ) {
101            argc++;
102            while (*p && *p != ':') p++;
103            if (*p == ':') p++;
104        }
105
106        bu_args = (char**) alloca(argc*sizeof(char*) + 1);
107
108        // run through again to build the argv array
109        argc = 0;
110        bu_args[argc++] = "bu";
111        snprintf(portnum, sizeof(portnum), "%d", s[1]);
112        bu_args[argc++] = portnum;
113        bu_args[argc++] = operation;
114        for (p = (char*)args; p && *p; ) {
115            bu_args[argc++] = p;
116            while (*p && *p != ':') p++;
117            if (*p == ':') {
118                *p = 0;
119                p++;
120            }
121        }
122        bu_args[argc] = NULL;
123
124        // Close the half of the socket that we don't care about, route 'bu's console
125        // to the output socket, and off we go
126        adb_close(s[0]);
127
128        // off we go
129        execvp("/system/bin/bu", (char * const *)bu_args);
130        // oops error - close up shop and go home
131        fprintf(stderr, "Unable to exec 'bu', bailing\n");
132        exit(-1);
133    } else {
134        adb_thread_t t;
135        backup_harvest_params* params;
136
137        // parent, i.e. adbd -- close the sending half of the socket
138        D("fork() returned pid %d\n", pid);
139        adb_close(s[1]);
140
141        // spin a thread to harvest the child process
142        params = (backup_harvest_params*) malloc(sizeof(backup_harvest_params));
143        params->pid = pid;
144        params->fd = s[0];
145        if (adb_thread_create(&t, backup_child_waiter, params)) {
146            adb_close(s[0]);
147            free(params);
148            D("Unable to create child harvester\n");
149            return -1;
150        }
151    }
152
153    // we'll be reading from s[0] as the data is sent by the child process
154    return s[0];
155}
156