blob: 830f2900e4fded543374213ff676929b05c5cdf4 [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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 <stdio.h>
Andrew Hsiehb73d0e02014-05-07 20:21:11 +080018#include <stdint.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080019#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <unistd.h>
23#include <limits.h>
24#include <stdarg.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <ctype.h>
28#include <assert.h>
29
30#include "sysdeps.h"
31
Yabin Cui6704a3c2014-11-17 14:48:25 -080032#if !defined(_WIN32)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080033#include <termios.h>
34#endif
35
36#define TRACE_TAG TRACE_ADB
37#include "adb.h"
38#include "adb_client.h"
Nick Kralevich6183c962014-11-13 15:17:29 -080039#include "adb_auth.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040#include "file_sync_service.h"
41
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080042static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
43
Alexey Tarasov857f17a2009-10-22 02:55:00 +110044void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080045int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -070046 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080047int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -070048int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080049int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
50
51static const char *gProductOutPath = NULL;
Matt Gumbel411775c2012-11-14 10:16:17 -080052extern int gListenAll;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080053
54static char *product_file(const char *extra)
55{
56 int n;
57 char *x;
58
59 if (gProductOutPath == NULL) {
60 fprintf(stderr, "adb: Product directory not specified; "
61 "use -p or define ANDROID_PRODUCT_OUT\n");
62 exit(1);
63 }
64
65 n = strlen(gProductOutPath) + strlen(extra) + 2;
66 x = malloc(n);
67 if (x == 0) {
68 fprintf(stderr, "adb: Out of memory (product_file())\n");
69 exit(1);
70 }
71
72 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
73 return x;
74}
75
76void version(FILE * out) {
77 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
78 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
79}
80
81void help()
82{
83 version(stderr);
84
85 fprintf(stderr,
86 "\n"
Matt Gumbel411775c2012-11-14 10:16:17 -080087 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080088 " -d - directs command to the only connected USB device\n"
89 " returns an error if more than one USB device is present.\n"
90 " -e - directs command to the only running emulator.\n"
91 " returns an error if more than one emulator is running.\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -070092 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson27042382012-05-30 18:11:27 -070093 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070094 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080095 " -p <product name or path> - simple product name like 'sooner', or\n"
96 " a relative/absolute path to a product\n"
97 " out directory like 'out/target/product/sooner'.\n"
98 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
99 " environment variable is used, which must\n"
100 " be an absolute path.\n"
Matt Gumbel411775c2012-11-14 10:16:17 -0800101 " -H - Name of adb server host (default: localhost)\n"
102 " -P - Port of adb server (default: 5037)\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700103 " devices [-l] - list all connected devices\n"
Scott Anderson27042382012-05-30 18:11:27 -0700104 " ('-l' will also list device qualifiers)\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400105 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
106 " Port 5555 is used by default if no port number is specified.\n"
107 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
108 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischerc3e82b82011-04-26 12:46:05 +0200109 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400110 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800111 "\n"
112 "device commands:\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700113 " adb push [-p] <local> <remote>\n"
114 " - copy file/dir to device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700116 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700117 " - copy file/dir from device\n"
118 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700119 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800120 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600121 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800122 " (see 'adb help all')\n"
123 " adb shell - run remote shell interactively\n"
124 " adb shell <command> - run remote shell command\n"
125 " adb emu <command> - run emulator console command\n"
126 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100127 " adb forward --list - list all forward socket connections.\n"
128 " the format is a list of lines with the following format:\n"
129 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800130 " adb forward <local> <remote> - forward socket connections\n"
131 " forward specs are one of: \n"
132 " tcp:<port>\n"
133 " localabstract:<unix domain socket name>\n"
134 " localreserved:<unix domain socket name>\n"
135 " localfilesystem:<unix domain socket name>\n"
136 " dev:<character device name>\n"
137 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100138 " adb forward --no-rebind <local> <remote>\n"
139 " - same as 'adb forward <local> <remote>' but fails\n"
140 " if <local> is already forwarded\n"
141 " adb forward --remove <local> - remove a specific forward socket connection\n"
142 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner963a4492013-03-21 21:07:42 +0100143 " adb reverse --list - list all reverse socket connections from device\n"
144 " adb reverse <remote> <local> - reverse socket connections\n"
145 " reverse specs are one of:\n"
146 " tcp:<port>\n"
147 " localabstract:<unix domain socket name>\n"
148 " localreserved:<unix domain socket name>\n"
149 " localfilesystem:<unix domain socket name>\n"
150 " adb reverse --norebind <remote> <local>\n"
151 " - same as 'adb reverse <remote> <local>' but fails\n"
152 " if <remote> is already reversed.\n"
153 " adb reverse --remove <remote>\n"
154 " - remove a specific reversed socket connection\n"
155 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800156 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700157 " adb install [-lrtsd] <file>\n"
158 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700159 " - push this package file to the device and install it\n"
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700160 " (-l: forward lock application)\n"
161 " (-r: replace existing application)\n"
162 " (-t: allow test packages)\n"
163 " (-s: install application on sdcard)\n"
164 " (-d: allow version code downgrade)\n"
165 " (-p: partial application install)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800166 " adb uninstall [-k] <package> - remove this app package from the device\n"
167 " ('-k' means keep the data and cache directories)\n"
168 " adb bugreport - return all information from the device\n"
169 " that should be included in a bug report.\n"
170 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800171 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700172 " - write an archive of the device's data to <file>.\n"
173 " If no -f option is supplied then the data is written\n"
174 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700175 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700176 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800177 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
178 " (aka .obb) files associated with each application; the default\n"
179 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700180 " (-shared|-noshared enable/disable backup of the device's\n"
181 " shared storage / SD card contents; the default is noshared.)\n"
182 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700183 " (-system|-nosystem toggles whether -all automatically includes\n"
184 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700185 " (<packages...> is the list of applications to be backed up. If\n"
186 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700187 " list is optional. Applications explicitly given on the\n"
188 " command line will be included even if -nosystem would\n"
189 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700190 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700191 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700192 "\n"
Paul Lawrence8ba2b022014-12-03 15:31:57 -0800193 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
194 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevich6183c962014-11-13 15:17:29 -0800195 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
196 " and the public key is stored in <file>.pub. Any existing files\n"
197 " are overwritten.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800198 " adb help - show this help message\n"
199 " adb version - show version num\n"
200 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800201 "scripting:\n"
202 " adb wait-for-device - block until device is online\n"
203 " adb start-server - ensure that there is a server running\n"
204 " adb kill-server - kill the server if it is running\n"
205 " adb get-state - prints: offline | bootloader | device\n"
206 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700207 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800208 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700209 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400210 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800211 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700212 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanenfb787d92014-10-06 12:57:20 -0500213 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800214 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrence5f356482014-10-09 14:22:49 +0000215 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800216 "networking:\n"
217 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500218 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800219 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
220 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
221 "\n"
222 "adb sync notes: adb sync [ <directory> ]\n"
223 " <localdir> can be interpreted in several ways:\n"
224 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700225 " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800226 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700227 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800228 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000229 "\n"
230 "environmental variables:\n"
231 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
232 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
233 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
234 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800235 );
236}
237
238int usage()
239{
240 help();
241 return 1;
242}
243
Yabin Cui6704a3c2014-11-17 14:48:25 -0800244#if defined(_WIN32)
245
246// Windows does not have <termio.h>.
247static void stdin_raw_init(int fd) {
248
249}
250
251static void stdin_raw_restore(int fd) {
252
253}
254
255#else
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800256static struct termios tio_save;
257
258static void stdin_raw_init(int fd)
259{
260 struct termios tio;
261
262 if(tcgetattr(fd, &tio)) return;
263 if(tcgetattr(fd, &tio_save)) return;
264
265 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
266
267 /* no timeout but request at least one character per read */
268 tio.c_cc[VTIME] = 0;
269 tio.c_cc[VMIN] = 1;
270
271 tcsetattr(fd, TCSANOW, &tio);
272 tcflush(fd, TCIFLUSH);
273}
274
275static void stdin_raw_restore(int fd)
276{
277 tcsetattr(fd, TCSANOW, &tio_save);
278 tcflush(fd, TCIFLUSH);
279}
280#endif
281
282static void read_and_dump(int fd)
283{
284 char buf[4096];
285 int len;
286
287 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700288 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800289 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700290 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800291 if(len == 0) {
292 break;
293 }
294
295 if(len < 0) {
296 if(errno == EINTR) continue;
297 break;
298 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400299 fwrite(buf, 1, len, stdout);
300 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800301 }
302}
303
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700304static void read_status_line(int fd, char* buf, size_t count)
305{
306 count--;
307 while (count > 0) {
308 int len = adb_read(fd, buf, count);
309 if (len == 0) {
310 break;
311 } else if (len < 0) {
312 if (errno == EINTR) continue;
313 break;
314 }
315
316 buf += len;
317 count -= len;
318 }
319 *buf = '\0';
320}
321
Christopher Tate73779122011-04-21 12:53:28 -0700322static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700323 const size_t BUFSIZE = 32 * 1024;
324 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700325 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700326 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700327
328 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cui6704a3c2014-11-17 14:48:25 -0800329
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700330 if (inFd == STDIN_FILENO) {
331 stdin_raw_init(STDIN_FILENO);
332 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800333
Christopher Tate73779122011-04-21 12:53:28 -0700334 for (;;) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700335 if (inFd == STDIN_FILENO) {
336 len = unix_read(inFd, buf, BUFSIZE);
337 } else {
338 len = adb_read(inFd, buf, BUFSIZE);
339 }
Christopher Tate73779122011-04-21 12:53:28 -0700340 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700341 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700342 break;
343 }
344 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700345 if (errno == EINTR) {
346 D("copy_to_file() : EINTR, retrying\n");
347 continue;
348 }
Christopher Tate73779122011-04-21 12:53:28 -0700349 D("copy_to_file() : error %d\n", errno);
350 break;
351 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700352 if (outFd == STDOUT_FILENO) {
353 fwrite(buf, 1, len, stdout);
354 fflush(stdout);
355 } else {
356 adb_write(outFd, buf, len);
357 }
Christopher Tatefba22972011-06-01 17:56:23 -0700358 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700359 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800360
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700361 if (inFd == STDIN_FILENO) {
362 stdin_raw_restore(STDIN_FILENO);
363 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800364
Christopher Tatefba22972011-06-01 17:56:23 -0700365 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700366 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700367}
368
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800369static void *stdin_read_thread(void *x)
370{
371 int fd, fdi;
372 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800373 int r, n;
374 int state = 0;
375
376 int *fds = (int*) x;
377 fd = fds[0];
378 fdi = fds[1];
379 free(fds);
380
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800381 for(;;) {
382 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700383 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800384 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700385 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800386 if(r == 0) break;
387 if(r < 0) {
388 if(errno == EINTR) continue;
389 break;
390 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400391 for(n = 0; n < r; n++){
392 switch(buf[n]) {
393 case '\n':
394 state = 1;
395 break;
396 case '\r':
397 state = 1;
398 break;
399 case '~':
400 if(state == 1) state++;
401 break;
402 case '.':
403 if(state == 2) {
404 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400405 stdin_raw_restore(fdi);
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400406 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800407 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400408 default:
409 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800410 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800411 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800412 r = adb_write(fd, buf, r);
413 if(r <= 0) {
414 break;
415 }
416 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800417 return 0;
418}
419
420int interactive_shell(void)
421{
422 adb_thread_t thr;
423 int fdi, fd;
424 int *fds;
425
426 fd = adb_connect("shell:");
427 if(fd < 0) {
428 fprintf(stderr,"error: %s\n", adb_error());
429 return 1;
430 }
431 fdi = 0; //dup(0);
432
433 fds = malloc(sizeof(int) * 2);
434 fds[0] = fd;
435 fds[1] = fdi;
436
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800437 stdin_raw_init(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800438 adb_thread_create(&thr, stdin_read_thread, fds);
439 read_and_dump(fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800440 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800441 return 0;
442}
443
444
445static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
446{
447 if (serial) {
448 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
449 } else {
450 const char* prefix = "host";
451 if (ttype == kTransportUsb)
452 prefix = "host-usb";
453 else if (ttype == kTransportLocal)
454 prefix = "host-local";
455
456 snprintf(buffer, buflen, "%s:%s", prefix, command);
457 }
458}
459
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100460int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800461 unsigned progress)
462{
463 char buf[4096];
464 unsigned total;
465 int fd;
466 const unsigned char *ptr;
467
468 sprintf(buf,"%s:%d", service, sz);
469 fd = adb_connect(buf);
470 if(fd < 0) {
471 fprintf(stderr,"error: %s\n", adb_error());
472 return -1;
473 }
474
475 int opt = CHUNK_SIZE;
Spencer Low31aafa62015-01-25 14:40:16 -0800476 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800477
478 total = sz;
479 ptr = data;
480
481 if(progress) {
482 char *x = strrchr(service, ':');
483 if(x) service = x + 1;
484 }
485
486 while(sz > 0) {
487 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
488 if(writex(fd, ptr, xfer)) {
489 adb_status(fd);
490 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
491 return -1;
492 }
493 sz -= xfer;
494 ptr += xfer;
495 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100496 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800497 fflush(stdout);
498 }
499 }
500 if(progress) {
501 printf("\n");
502 }
503
504 if(readx(fd, buf, 4)){
505 fprintf(stderr,"* error reading response *\n");
506 adb_close(fd);
507 return -1;
508 }
509 if(memcmp(buf, "OKAY", 4)) {
510 buf[4] = 0;
511 fprintf(stderr,"* error response '%s' *\n", buf);
512 adb_close(fd);
513 return -1;
514 }
515
516 adb_close(fd);
517 return 0;
518}
519
520
521int adb_download(const char *service, const char *fn, unsigned progress)
522{
523 void *data;
524 unsigned sz;
525
526 data = load_file(fn, &sz);
527 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100528 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800529 return -1;
530 }
531
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100532 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800533 free(data);
534 return status;
535}
536
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700537#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
538
539/*
540 * The sideload-host protocol serves the data in a file (given on the
541 * command line) to the client, using a simple protocol:
542 *
543 * - The connect message includes the total number of bytes in the
544 * file and a block size chosen by us.
545 *
546 * - The other side sends the desired block number as eight decimal
547 * digits (eg "00000023" for block 23). Blocks are numbered from
548 * zero.
549 *
550 * - We send back the data of the requested block. The last block is
551 * likely to be partial; when the last block is requested we only
552 * send the part of the block that exists, it's not padded up to the
553 * block size.
554 *
555 * - When the other side sends "DONEDONE" instead of a block number,
556 * we hang up.
557 */
558int adb_sideload_host(const char* fn) {
559 uint8_t* data;
560 unsigned sz;
561 size_t xfer = 0;
562 int status;
563
564 printf("loading: '%s'", fn);
565 fflush(stdout);
566 data = load_file(fn, &sz);
567 if (data == 0) {
568 printf("\n");
569 fprintf(stderr, "* cannot read '%s' *\n", fn);
570 return -1;
571 }
572
573 char buf[100];
574 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
575 int fd = adb_connect(buf);
576 if (fd < 0) {
577 // Try falling back to the older sideload method. Maybe this
578 // is an older device that doesn't support sideload-host.
579 printf("\n");
580 status = adb_download_buffer("sideload", fn, data, sz, 1);
581 goto done;
582 }
583
584 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Spencer Low31aafa62015-01-25 14:40:16 -0800585 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700586
587 int last_percent = -1;
Doug Zongkera27ee6c2014-07-07 15:28:43 -0700588 for (;;) {
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700589 if (readx(fd, buf, 8)) {
590 fprintf(stderr, "* failed to read command: %s\n", adb_error());
591 status = -1;
592 goto done;
593 }
594
595 if (strncmp("DONEDONE", buf, 8) == 0) {
596 status = 0;
597 break;
598 }
599
600 buf[8] = '\0';
601 int block = strtol(buf, NULL, 10);
602
603 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
604 if (offset >= sz) {
605 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
606 status = -1;
607 goto done;
608 }
609 uint8_t* start = data + offset;
610 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
611 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
612 if (offset_end > sz) {
613 to_write = sz - offset;
614 }
615
616 if(writex(fd, start, to_write)) {
617 adb_status(fd);
618 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
619 status = -1;
620 goto done;
621 }
622 xfer += to_write;
623
624 // For normal OTA packages, we expect to transfer every byte
625 // twice, plus a bit of overhead (one read during
626 // verification, one read of each byte for installation, plus
627 // extra access to things like the zip central directory).
628 // This estimate of the completion becomes 100% when we've
629 // transferred ~2.13 (=100/47) times the package size.
630 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
631 if (percent != last_percent) {
632 printf("\rserving: '%s' (~%d%%) ", fn, percent);
633 fflush(stdout);
634 last_percent = percent;
635 }
636 }
637
Colin Cross2328bea2014-07-07 14:12:41 -0700638 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700639
640 done:
641 if (fd >= 0) adb_close(fd);
642 free(data);
643 return status;
644}
645
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800646static void status_window(transport_type ttype, const char* serial)
647{
648 char command[4096];
649 char *state = 0;
650 char *laststate = 0;
651
652 /* silence stderr */
653#ifdef _WIN32
654 /* XXX: TODO */
655#else
656 int fd;
657 fd = unix_open("/dev/null", O_WRONLY);
658 dup2(fd, 2);
659 adb_close(fd);
660#endif
661
662 format_host_command(command, sizeof command, "get-state", ttype, serial);
663
664 for(;;) {
665 adb_sleep_ms(250);
666
667 if(state) {
668 free(state);
669 state = 0;
670 }
671
672 state = adb_query(command);
673
674 if(state) {
675 if(laststate && !strcmp(state,laststate)){
676 continue;
677 } else {
678 if(laststate) free(laststate);
679 laststate = strdup(state);
680 }
681 }
682
683 printf("%c[2J%c[2H", 27, 27);
684 printf("Android Debug Bridge\n");
685 printf("State: %s\n", state ? state : "offline");
686 fflush(stdout);
687 }
688}
689
Brian Carlstrom529fca82014-08-05 22:51:18 -0700690static int should_escape(const char c)
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700691{
692 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
693}
694
695/* Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700696static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800697{
698 const char *ts;
699 size_t alloc_len;
700 char *ret;
701 char *dest;
702
Jeff Sharkey026d9622014-06-10 16:22:17 -0700703 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700704 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800705 alloc_len++;
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700706 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800707 alloc_len++;
708 }
709 }
710
Jeff Sharkey026d9622014-06-10 16:22:17 -0700711 if (alloc_len == 0) {
712 // Preserve empty arguments
713 ret = (char *) malloc(3);
714 ret[0] = '\"';
715 ret[1] = '\"';
716 ret[2] = '\0';
717 return ret;
718 }
719
Jeff Sharkey824d1062014-06-10 11:31:24 -0700720 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800721 dest = ret;
722
Jeff Sharkey824d1062014-06-10 11:31:24 -0700723 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700724 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800725 *dest++ = '\\';
726 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800727 *dest++ = *ts;
728 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800729 *dest++ = '\0';
730
731 return ret;
732}
733
734/**
735 * Run ppp in "notty" mode against a resource listed as the first parameter
736 * eg:
737 *
738 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
739 *
740 */
741int ppp(int argc, char **argv)
742{
Yabin Cui2fa43212014-11-11 09:24:11 -0800743#if defined(_WIN32)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800744 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
745 return -1;
746#else
747 char *adb_service_name;
748 pid_t pid;
749 int fd;
750
751 if (argc < 2) {
752 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
753 argv[0]);
754
755 return 1;
756 }
757
758 adb_service_name = argv[1];
759
760 fd = adb_connect(adb_service_name);
761
762 if(fd < 0) {
763 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
764 adb_service_name, adb_error());
765 return 1;
766 }
767
768 pid = fork();
769
770 if (pid < 0) {
771 perror("from fork()");
772 return 1;
773 } else if (pid == 0) {
774 int err;
775 int i;
776 const char **ppp_args;
777
778 // copy args
779 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
780 ppp_args[0] = "pppd";
781 for (i = 2 ; i < argc ; i++) {
782 //argv[2] and beyond become ppp_args[1] and beyond
783 ppp_args[i - 1] = argv[i];
784 }
785 ppp_args[i-1] = NULL;
786
787 // child side
788
789 dup2(fd, STDIN_FILENO);
790 dup2(fd, STDOUT_FILENO);
791 adb_close(STDERR_FILENO);
792 adb_close(fd);
793
794 err = execvp("pppd", (char * const *)ppp_args);
795
796 if (err < 0) {
797 perror("execing pppd");
798 }
799 exit(-1);
800 } else {
801 // parent side
802
803 adb_close(fd);
804 return 0;
805 }
Yabin Cui2fa43212014-11-11 09:24:11 -0800806#endif /* !defined(_WIN32) */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800807}
808
809static int send_shellcommand(transport_type transport, char* serial, char* buf)
810{
811 int fd, ret;
812
813 for(;;) {
814 fd = adb_connect(buf);
815 if(fd >= 0)
816 break;
817 fprintf(stderr,"- waiting for device -\n");
818 adb_sleep_ms(1000);
819 do_cmd(transport, serial, "wait-for-device", 0);
820 }
821
822 read_and_dump(fd);
823 ret = adb_close(fd);
824 if (ret)
825 perror("close");
826
827 return ret;
828}
829
830static int logcat(transport_type transport, char* serial, int argc, char **argv)
831{
832 char buf[4096];
833
834 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700835 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800836
837 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700838 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800839 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700840 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700841 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800842
Jeff Sharkey824d1062014-06-10 11:31:24 -0700843 if (!strcmp(argv[0], "longcat")) {
844 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800845 }
846
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800847 argc -= 1;
848 argv += 1;
849 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700850 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700851 strncat(buf, " ", sizeof(buf) - 1);
852 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800853 free(quoted);
854 }
855
856 send_shellcommand(transport, serial, buf);
857 return 0;
858}
859
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700860static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800861{
862 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700863 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800864
865 for(;;) {
866 x = adb_dirstart(x);
867 if(x == 0) return 0;
868 *x = 0;
869 ret = adb_mkdir(path, 0775);
870 *x = OS_PATH_SEPARATOR;
871 if((ret < 0) && (errno != EEXIST)) {
872 return ret;
873 }
874 x++;
875 }
876 return 0;
877}
878
Christopher Tate73779122011-04-21 12:53:28 -0700879static int backup(int argc, char** argv) {
880 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800881 char default_name[32];
882 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700883 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700884 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700885
Christopher Tatefba22972011-06-01 17:56:23 -0700886 /* find, extract, and use any -f argument */
887 for (i = 1; i < argc; i++) {
888 if (!strcmp("-f", argv[i])) {
889 if (i == argc-1) {
890 fprintf(stderr, "adb: -f passed with no filename\n");
891 return usage();
892 }
893 filename = argv[i+1];
894 for (j = i+2; j <= argc; ) {
895 argv[i++] = argv[j++];
896 }
897 argc -= 2;
898 argv[argc] = NULL;
899 }
Christopher Tate73779122011-04-21 12:53:28 -0700900 }
901
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700902 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
903 if (argc < 2) return usage();
904
Christopher Tate1e9f2392011-12-08 19:04:34 -0800905 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700906 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800907 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700908 if (outFd < 0) {
909 fprintf(stderr, "adb: unable to open file %s\n", filename);
910 return -1;
911 }
912
913 snprintf(buf, sizeof(buf), "backup");
914 for (argc--, argv++; argc; argc--, argv++) {
915 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
916 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
917 }
918
919 D("backup. filename=%s buf=%s\n", filename, buf);
920 fd = adb_connect(buf);
921 if (fd < 0) {
922 fprintf(stderr, "adb: unable to connect for backup\n");
923 adb_close(outFd);
924 return -1;
925 }
926
Christopher Tate9c829102012-01-06 15:43:03 -0800927 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700928 copy_to_file(fd, outFd);
929
930 adb_close(fd);
931 adb_close(outFd);
932 return 0;
933}
934
Christopher Tatecf5379b2011-05-17 15:52:54 -0700935static int restore(int argc, char** argv) {
936 const char* filename;
937 int fd, tarFd;
938
939 if (argc != 2) return usage();
940
941 filename = argv[1];
942 tarFd = adb_open(filename, O_RDONLY);
943 if (tarFd < 0) {
944 fprintf(stderr, "adb: unable to open file %s\n", filename);
945 return -1;
946 }
947
948 fd = adb_connect("restore:");
949 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700950 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700951 adb_close(tarFd);
952 return -1;
953 }
954
Christopher Tate9c829102012-01-06 15:43:03 -0800955 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700956 copy_to_file(tarFd, fd);
957
958 adb_close(fd);
959 adb_close(tarFd);
960 return 0;
961}
962
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800963#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
964static int top_works(const char *top)
965{
966 if (top != NULL && adb_is_absolute_host_path(top)) {
967 char path_buf[PATH_MAX];
968 snprintf(path_buf, sizeof(path_buf),
969 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
970 return access(path_buf, F_OK) == 0;
971 }
972 return 0;
973}
974
975static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
976{
977 strcpy(path_buf, indir);
978 while (1) {
979 if (top_works(path_buf)) {
980 return path_buf;
981 }
982 char *s = adb_dirstop(path_buf);
983 if (s != NULL) {
984 *s = '\0';
985 } else {
986 path_buf[0] = '\0';
987 return NULL;
988 }
989 }
990}
991
992static char *find_top(char path_buf[PATH_MAX])
993{
994 char *top = getenv("ANDROID_BUILD_TOP");
995 if (top != NULL && top[0] != '\0') {
996 if (!top_works(top)) {
997 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
998 return NULL;
999 }
1000 } else {
1001 top = getenv("TOP");
1002 if (top != NULL && top[0] != '\0') {
1003 if (!top_works(top)) {
1004 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1005 return NULL;
1006 }
1007 } else {
1008 top = NULL;
1009 }
1010 }
1011
1012 if (top != NULL) {
1013 /* The environment pointed to a top directory that works.
1014 */
1015 strcpy(path_buf, top);
1016 return path_buf;
1017 }
1018
1019 /* The environment didn't help. Walk up the tree from the CWD
1020 * to see if we can find the top.
1021 */
1022 char dir[PATH_MAX];
1023 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1024 if (top == NULL) {
1025 /* If the CWD isn't under a good-looking top, see if the
1026 * executable is.
1027 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +11001028 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001029 top = find_top_from(dir, path_buf);
1030 }
1031 return top;
1032}
1033
1034/* <hint> may be:
1035 * - A simple product name
1036 * e.g., "sooner"
1037TODO: debug? sooner-debug, sooner:debug?
1038 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1039 * e.g., "out/target/product/sooner"
1040 * - An absolute path to the PRODUCT_OUT dir
1041 * e.g., "/src/device/out/target/product/sooner"
1042 *
1043 * Given <hint>, try to construct an absolute path to the
1044 * ANDROID_PRODUCT_OUT dir.
1045 */
1046static const char *find_product_out_path(const char *hint)
1047{
1048 static char path_buf[PATH_MAX];
1049
1050 if (hint == NULL || hint[0] == '\0') {
1051 return NULL;
1052 }
1053
1054 /* If it's already absolute, don't bother doing any work.
1055 */
1056 if (adb_is_absolute_host_path(hint)) {
1057 strcpy(path_buf, hint);
1058 return path_buf;
1059 }
1060
1061 /* If there are any slashes in it, assume it's a relative path;
1062 * make it absolute.
1063 */
1064 if (adb_dirstart(hint) != NULL) {
1065 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1066 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1067 return NULL;
1068 }
1069 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1070 fprintf(stderr, "adb: Couldn't assemble path\n");
1071 return NULL;
1072 }
1073 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1074 strcat(path_buf, hint);
1075 return path_buf;
1076 }
1077
1078 /* It's a string without any slashes. Try to do something with it.
1079 *
1080 * Try to find the root of the build tree, and build a PRODUCT_OUT
1081 * path from there.
1082 */
1083 char top_buf[PATH_MAX];
1084 const char *top = find_top(top_buf);
1085 if (top == NULL) {
1086 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1087 return NULL;
1088 }
1089//TODO: if we have a way to indicate debug, look in out/debug/target/...
1090 snprintf(path_buf, sizeof(path_buf),
1091 "%s" OS_PATH_SEPARATOR_STR
1092 "out" OS_PATH_SEPARATOR_STR
1093 "target" OS_PATH_SEPARATOR_STR
1094 "product" OS_PATH_SEPARATOR_STR
1095 "%s", top_buf, hint);
1096 if (access(path_buf, F_OK) < 0) {
1097 fprintf(stderr, "adb: Couldn't find a product dir "
1098 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1099 return NULL;
1100 }
1101 return path_buf;
1102}
1103
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001104static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1105 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001106 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001107 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001108
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001109 while (narg > 0) {
1110 if (!strcmp(*arg, "-p")) {
1111 *show_progress = 1;
1112 } else if (!strcmp(*arg, "-a")) {
1113 *copy_attrs = 1;
1114 } else {
1115 break;
1116 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001117 ++arg;
1118 --narg;
1119 }
1120
1121 if (narg > 0) {
1122 *path1 = *arg;
1123 ++arg;
1124 --narg;
1125 }
1126
1127 if (narg > 0) {
1128 *path2 = *arg;
1129 }
1130}
1131
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001132int adb_commandline(int argc, char **argv)
1133{
1134 char buf[4096];
1135 int no_daemon = 0;
1136 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001137 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001138 int persist = 0;
1139 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001140 transport_type ttype = kTransportAny;
1141 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001142 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001143
1144 /* If defined, this should be an absolute path to
1145 * the directory containing all of the various system images
1146 * for a particular product. If not defined, and the adb
1147 * command requires this information, then the user must
1148 * specify the path using "-p".
1149 */
1150 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1151 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1152 gProductOutPath = NULL;
1153 }
1154 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1155
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001156 serial = getenv("ANDROID_SERIAL");
1157
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001158 /* Validate and assign the server port */
1159 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1160 int server_port = DEFAULT_ADB_PORT;
1161 if (server_port_str && strlen(server_port_str) > 0) {
1162 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001163 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001164 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001165 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001166 server_port_str);
1167 return usage();
1168 }
1169 }
1170
1171 /* modifiers and flags */
Riley Andrews03b4b372014-12-05 17:37:24 -08001172 while (argc > 0) {
1173 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001174 is_server = 1;
Riley Andrews03b4b372014-12-05 17:37:24 -08001175 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001176 no_daemon = 1;
1177 } else if (!strcmp(argv[0], "fork-server")) {
1178 /* this is a special flag used only when the ADB client launches the ADB Server */
1179 is_daemon = 1;
Riley Andrews03b4b372014-12-05 17:37:24 -08001180 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001181 persist = 1;
Riley Andrews03b4b372014-12-05 17:37:24 -08001182 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001183 const char *product = NULL;
1184 if (argv[0][2] == '\0') {
1185 if (argc < 2) return usage();
1186 product = argv[1];
1187 argc--;
1188 argv++;
1189 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001190 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001191 }
1192 gProductOutPath = find_product_out_path(product);
1193 if (gProductOutPath == NULL) {
1194 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1195 product);
1196 return usage();
1197 }
1198 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1199 if (isdigit(argv[0][2])) {
1200 serial = argv[0] + 2;
1201 } else {
Riley Andrews03b4b372014-12-05 17:37:24 -08001202 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001203 serial = argv[1];
1204 argc--;
1205 argv++;
1206 }
1207 } else if (!strcmp(argv[0],"-d")) {
1208 ttype = kTransportUsb;
1209 } else if (!strcmp(argv[0],"-e")) {
1210 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001211 } else if (!strcmp(argv[0],"-a")) {
1212 gListenAll = 1;
Riley Andrews03b4b372014-12-05 17:37:24 -08001213 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbel411775c2012-11-14 10:16:17 -08001214 const char *hostname = NULL;
1215 if (argv[0][2] == '\0') {
1216 if (argc < 2) return usage();
1217 hostname = argv[1];
1218 argc--;
1219 argv++;
1220 } else {
1221 hostname = argv[0] + 2;
1222 }
1223 adb_set_tcp_name(hostname);
1224
Riley Andrews03b4b372014-12-05 17:37:24 -08001225 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbel411775c2012-11-14 10:16:17 -08001226 if (argv[0][2] == '\0') {
1227 if (argc < 2) return usage();
1228 server_port_str = argv[1];
1229 argc--;
1230 argv++;
1231 } else {
1232 server_port_str = argv[0] + 2;
1233 }
1234 if (strlen(server_port_str) > 0) {
1235 server_port = (int) strtol(server_port_str, NULL, 0);
1236 if (server_port <= 0 || server_port > 65535) {
1237 fprintf(stderr,
1238 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1239 server_port_str);
1240 return usage();
1241 }
1242 } else {
1243 fprintf(stderr,
1244 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1245 return usage();
1246 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001247 } else {
1248 /* out of recognized modifiers and flags */
1249 break;
1250 }
1251 argc--;
1252 argv++;
1253 }
1254
1255 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001256 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001257
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001258 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001259 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001260 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001261 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001262 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001263 }
Riley Andrews03b4b372014-12-05 17:37:24 -08001264 if (r) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001265 fprintf(stderr,"* could not start server *\n");
1266 }
1267 return r;
1268 }
1269
Riley Andrews03b4b372014-12-05 17:37:24 -08001270 if (argc == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001271 return usage();
1272 }
1273
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001274 /* handle wait-for-* prefix */
1275 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1276 char* service = argv[0];
1277 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1278 if (ttype == kTransportUsb) {
1279 service = "wait-for-usb";
1280 } else if (ttype == kTransportLocal) {
1281 service = "wait-for-local";
1282 } else {
1283 service = "wait-for-any";
1284 }
1285 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001286
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001287 format_host_command(buf, sizeof buf, service, ttype, serial);
1288
1289 if (adb_command(buf)) {
1290 D("failure: %s *\n",adb_error());
1291 fprintf(stderr,"error: %s\n", adb_error());
1292 return 1;
1293 }
1294
1295 /* Allow a command to be run after wait-for-device,
1296 * e.g. 'adb wait-for-device shell'.
1297 */
1298 if (argc == 1) {
1299 return 0;
1300 }
1301
1302 /* Fall through */
1303 argc--;
1304 argv++;
1305 }
1306
1307 /* adb_connect() commands */
Riley Andrews03b4b372014-12-05 17:37:24 -08001308 if (!strcmp(argv[0], "devices")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001309 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001310 char *listopt;
1311 if (argc < 2)
1312 listopt = "";
1313 else if (argc == 2 && !strcmp(argv[1], "-l"))
1314 listopt = argv[1];
1315 else {
1316 fprintf(stderr, "Usage: adb devices [-l]\n");
1317 return 1;
1318 }
1319 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001320 tmp = adb_query(buf);
Riley Andrews03b4b372014-12-05 17:37:24 -08001321 if (tmp) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001322 printf("List of devices attached \n");
1323 printf("%s\n", tmp);
1324 return 0;
1325 } else {
1326 return 1;
1327 }
1328 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001329 else if (!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001330 char *tmp;
1331 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001332 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001333 return 1;
1334 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001335 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1336 tmp = adb_query(buf);
Riley Andrews03b4b372014-12-05 17:37:24 -08001337 if (tmp) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001338 printf("%s\n", tmp);
1339 return 0;
1340 } else {
1341 return 1;
1342 }
1343 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001344 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001345 char *tmp;
1346 if (argc > 2) {
1347 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1348 return 1;
1349 }
1350 if (argc == 2) {
1351 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1352 } else {
1353 snprintf(buf, sizeof buf, "host:disconnect:");
1354 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001355 tmp = adb_query(buf);
Riley Andrews03b4b372014-12-05 17:37:24 -08001356 if (tmp) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001357 printf("%s\n", tmp);
1358 return 0;
1359 } else {
1360 return 1;
1361 }
1362 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001363 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001364 return adb_send_emulator_command(argc, argv);
1365 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001366 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001367 int r;
1368 int fd;
1369
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001370 char h = (argv[0][0] == 'h');
1371
1372 if (h) {
1373 printf("\x1b[41;33m");
1374 fflush(stdout);
1375 }
1376
Riley Andrews03b4b372014-12-05 17:37:24 -08001377 if (argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001378 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001379 r = interactive_shell();
1380 if (h) {
1381 printf("\x1b[0m");
1382 fflush(stdout);
1383 }
1384 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001385 }
1386
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001387 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001388 argc -= 2;
1389 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001390 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001391 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001392 strncat(buf, " ", sizeof(buf) - 1);
1393 strncat(buf, quoted, sizeof(buf) - 1);
1394 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001395 }
1396
1397 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001398 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001399 fd = adb_connect(buf);
Riley Andrews03b4b372014-12-05 17:37:24 -08001400 if (fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001401 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001402 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001403 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001404 adb_close(fd);
1405 r = 0;
1406 } else {
1407 fprintf(stderr,"error: %s\n", adb_error());
1408 r = -1;
1409 }
1410
Riley Andrews03b4b372014-12-05 17:37:24 -08001411 if (persist) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001412 fprintf(stderr,"\n- waiting for device -\n");
1413 adb_sleep_ms(1000);
1414 do_cmd(ttype, serial, "wait-for-device", 0);
1415 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001416 if (h) {
1417 printf("\x1b[0m");
1418 fflush(stdout);
1419 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001420 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001421 return r;
1422 }
1423 }
1424 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001425 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001426 int exec_in = !strcmp(argv[0], "exec-in");
1427 int fd;
1428
1429 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1430 argc -= 2;
1431 argv += 2;
1432 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001433 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001434 strncat(buf, " ", sizeof(buf) - 1);
1435 strncat(buf, quoted, sizeof(buf) - 1);
1436 free(quoted);
1437 }
1438
1439 fd = adb_connect(buf);
1440 if (fd < 0) {
1441 fprintf(stderr, "error: %s\n", adb_error());
1442 return -1;
1443 }
1444
1445 if (exec_in) {
1446 copy_to_file(STDIN_FILENO, fd);
1447 } else {
1448 copy_to_file(fd, STDOUT_FILENO);
1449 }
1450
1451 adb_close(fd);
1452 return 0;
1453 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001454 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001455 int fd;
1456 fd = _adb_connect("host:kill");
Riley Andrews03b4b372014-12-05 17:37:24 -08001457 if (fd == -1) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001458 fprintf(stderr,"* server not running *\n");
1459 return 1;
1460 }
1461 return 0;
1462 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001463 else if (!strcmp(argv[0], "sideload")) {
1464 if (argc != 2) return usage();
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001465 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001466 return 1;
1467 } else {
1468 return 0;
1469 }
1470 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001471 else if (!strcmp(argv[0], "remount") ||
1472 !strcmp(argv[0], "reboot") ||
1473 !strcmp(argv[0], "reboot-bootloader") ||
1474 !strcmp(argv[0], "tcpip") ||
1475 !strcmp(argv[0], "usb") ||
1476 !strcmp(argv[0], "root") ||
Dan Pasanenfb787d92014-10-06 12:57:20 -05001477 !strcmp(argv[0], "unroot") ||
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001478 !strcmp(argv[0], "disable-verity") ||
1479 !strcmp(argv[0], "enable-verity")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001480 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001481 if (!strcmp(argv[0], "reboot-bootloader"))
1482 snprintf(command, sizeof(command), "reboot:bootloader");
1483 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001484 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001485 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001486 snprintf(command, sizeof(command), "%s:", argv[0]);
1487 int fd = adb_connect(command);
Riley Andrews03b4b372014-12-05 17:37:24 -08001488 if (fd >= 0) {
The Android Open Source Project9c753402009-03-13 13:04:37 -07001489 read_and_dump(fd);
1490 adb_close(fd);
1491 return 0;
1492 }
1493 fprintf(stderr,"error: %s\n", adb_error());
1494 return 1;
1495 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001496 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001497 if (argc != 1) return usage();
1498 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001499 return 0;
1500 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001501 /* adb_command() wrapper commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001502 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001503 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001504 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001505 char remove = 0;
1506 char remove_all = 0;
1507 char list = 0;
1508 char no_rebind = 0;
1509
1510 // Parse options here.
1511 while (argc > 1 && argv[1][0] == '-') {
1512 if (!strcmp(argv[1], "--list"))
1513 list = 1;
1514 else if (!strcmp(argv[1], "--remove"))
1515 remove = 1;
1516 else if (!strcmp(argv[1], "--remove-all"))
1517 remove_all = 1;
1518 else if (!strcmp(argv[1], "--no-rebind"))
1519 no_rebind = 1;
1520 else {
1521 return usage();
1522 }
1523 argc--;
1524 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001525 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001526
1527 // Ensure we can only use one option at a time.
1528 if (list + remove + remove_all + no_rebind > 1) {
1529 return usage();
1530 }
1531
1532 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001533 if (reverse) {
1534 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001535 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001536 if (serial) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1538 serial);
1539 } else if (ttype == kTransportUsb) {
1540 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1541 } else if (ttype == kTransportLocal) {
1542 snprintf(host_prefix, sizeof host_prefix, "host-local");
1543 } else {
1544 snprintf(host_prefix, sizeof host_prefix, "host");
1545 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001546 }
1547
1548 // Implement forward --list
1549 if (list) {
1550 if (argc != 1)
1551 return usage();
1552 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1553 char* forwards = adb_query(buf);
1554 if (forwards == NULL) {
1555 fprintf(stderr, "error: %s\n", adb_error());
1556 return 1;
1557 }
1558 printf("%s", forwards);
1559 free(forwards);
1560 return 0;
1561 }
1562
1563 // Implement forward --remove-all
1564 else if (remove_all) {
1565 if (argc != 1)
1566 return usage();
1567 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1568 }
1569
1570 // Implement forward --remove <local>
1571 else if (remove) {
1572 if (argc != 2)
1573 return usage();
1574 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1575 }
1576 // Or implement one of:
1577 // forward <local> <remote>
1578 // forward --no-rebind <local> <remote>
1579 else
1580 {
1581 if (argc != 3)
1582 return usage();
David 'Digit' Turnerf64d0822015-01-22 09:07:41 +01001583 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001584 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1585 }
1586
Riley Andrews03b4b372014-12-05 17:37:24 -08001587 if (adb_command(buf)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001588 fprintf(stderr,"error: %s\n", adb_error());
1589 return 1;
1590 }
1591 return 0;
1592 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001593 /* do_sync_*() commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001594 else if (!strcmp(argv[0], "ls")) {
1595 if (argc != 2) return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001596 return do_sync_ls(argv[1]);
1597 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001598 else if (!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001599 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001600 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001601 const char* lpath = NULL, *rpath = NULL;
1602
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001603 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001604
1605 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001606 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001607 }
1608
1609 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001610 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001611 else if (!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001612 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001613 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001614 const char* rpath = NULL, *lpath = ".";
1615
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001616 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001617
1618 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001619 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001620 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001621
1622 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001623 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001624 else if (!strcmp(argv[0], "install")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001625 if (argc < 2) return usage();
1626 return install_app(ttype, serial, argc, argv);
1627 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001628 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001629 if (argc < 2) return usage();
1630 return install_multiple_app(ttype, serial, argc, argv);
1631 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001632 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001633 if (argc < 2) return usage();
1634 return uninstall_app(ttype, serial, argc, argv);
1635 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001636 else if (!strcmp(argv[0], "sync")) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001637 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001638 int listonly = 0;
1639
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001640 int ret;
Riley Andrews03b4b372014-12-05 17:37:24 -08001641 if (argc < 2) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001642 /* No local path was specified. */
1643 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001644 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1645 listonly = 1;
1646 if (argc == 3) {
1647 srcarg = argv[2];
1648 } else {
1649 srcarg = NULL;
1650 }
Riley Andrews03b4b372014-12-05 17:37:24 -08001651 } else if (argc == 2) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001652 /* A local path or "android"/"data" arg was specified. */
1653 srcarg = argv[1];
1654 } else {
1655 return usage();
1656 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001657 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
Riley Andrews03b4b372014-12-05 17:37:24 -08001658 if (ret != 0) return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001659
Riley Andrews03b4b372014-12-05 17:37:24 -08001660 if (android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001661 ret = do_sync_sync(android_srcpath, "/system", listonly);
Riley Andrews03b4b372014-12-05 17:37:24 -08001662 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001663 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Riley Andrews03b4b372014-12-05 17:37:24 -08001664 if (ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001665 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001666
1667 free(android_srcpath);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001668 free(vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001669 free(data_srcpath);
1670 return ret;
1671 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001672 /* passthrough commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001673 else if (!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001674 !strcmp(argv[0],"get-serialno") ||
1675 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001676 {
1677 char *tmp;
1678
1679 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1680 tmp = adb_query(buf);
Riley Andrews03b4b372014-12-05 17:37:24 -08001681 if (tmp) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001682 printf("%s\n", tmp);
1683 return 0;
1684 } else {
1685 return 1;
1686 }
1687 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001688 /* other commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001689 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001690 status_window(ttype, serial);
1691 return 0;
1692 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001693 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001694 return logcat(ttype, serial, argc, argv);
1695 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001696 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001697 return ppp(argc, argv);
1698 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001699 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001700 return adb_connect("host:start-server");
1701 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0], "backup")) {
Christopher Tate73779122011-04-21 12:53:28 -07001703 return backup(argc, argv);
1704 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "restore")) {
Christopher Tatecf5379b2011-05-17 15:52:54 -07001706 return restore(argc, argv);
1707 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevich6183c962014-11-13 15:17:29 -08001709 if (argc < 2) return usage();
1710 return adb_auth_keygen(argv[1]);
1711 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001712 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001713 int fd = adb_connect("jdwp");
1714 if (fd >= 0) {
1715 read_and_dump(fd);
1716 adb_close(fd);
1717 return 0;
1718 } else {
1719 fprintf(stderr, "error: %s\n", adb_error());
1720 return -1;
1721 }
1722 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001723 /* "adb /?" is a common idiom under Windows */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001724 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001725 help();
1726 return 0;
1727 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001728 else if (!strcmp(argv[0], "version")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001729 version(stdout);
1730 return 0;
1731 }
1732
1733 usage();
1734 return 1;
1735}
1736
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001737#define MAX_ARGV_LENGTH 16
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001738static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1739{
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001740 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001741 int argc;
1742 va_list ap;
1743
1744 va_start(ap, cmd);
1745 argc = 0;
1746
1747 if (serial) {
1748 argv[argc++] = "-s";
1749 argv[argc++] = serial;
1750 } else if (ttype == kTransportUsb) {
1751 argv[argc++] = "-d";
1752 } else if (ttype == kTransportLocal) {
1753 argv[argc++] = "-e";
1754 }
1755
1756 argv[argc++] = cmd;
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001757 while(argc < MAX_ARGV_LENGTH &&
1758 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1759 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001760 va_end(ap);
1761
1762#if 0
1763 int n;
1764 fprintf(stderr,"argc = %d\n",argc);
1765 for(n = 0; n < argc; n++) {
1766 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1767 }
1768#endif
1769
1770 return adb_commandline(argc, argv);
1771}
1772
1773int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001774 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001775{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001776 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1777 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001778
1779 if(srcarg == NULL) {
1780 android_srcdir = product_file("system");
1781 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001782 vendor_srcdir = product_file("vendor");
1783 /* Check if vendor partition exists */
1784 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1785 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001786 } else {
1787 /* srcarg may be "data", "system" or NULL.
1788 * if srcarg is NULL, then both data and system are synced
1789 */
1790 if(strcmp(srcarg, "system") == 0) {
1791 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001792 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001793 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001794 } else if(strcmp(srcarg, "vendor") == 0) {
1795 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001796 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001797 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001798 */
1799 return 1;
1800 }
1801 }
1802
1803 if(android_srcdir_out != NULL)
1804 *android_srcdir_out = android_srcdir;
1805 else
1806 free(android_srcdir);
1807
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001808 if(vendor_srcdir_out != NULL)
1809 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001810 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001811 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001812
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001813 if(data_srcdir_out != NULL)
1814 *data_srcdir_out = data_srcdir;
1815 else
1816 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001817 return 0;
1818}
1819
1820static int pm_command(transport_type transport, char* serial,
1821 int argc, char** argv)
1822{
1823 char buf[4096];
1824
1825 snprintf(buf, sizeof(buf), "shell:pm");
1826
1827 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001828 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001829 strncat(buf, " ", sizeof(buf) - 1);
1830 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001831 free(quoted);
1832 }
1833
1834 send_shellcommand(transport, serial, buf);
1835 return 0;
1836}
1837
1838int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1839{
1840 /* if the user choose the -k option, we refuse to do it until devices are
1841 out with the option to uninstall the remaining data somehow (adb/ui) */
1842 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1843 {
1844 printf(
1845 "The -k option uninstalls the application while retaining the data/cache.\n"
1846 "At the moment, there is no way to remove the remaining data.\n"
1847 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1848 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1849 return -1;
1850 }
1851
1852 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1853 return pm_command(transport, serial, argc, argv);
1854}
1855
1856static int delete_file(transport_type transport, char* serial, char* filename)
1857{
1858 char buf[4096];
1859 char* quoted;
1860
Jeff Sharkeyce474652014-09-09 12:38:30 -07001861 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001862 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001863 strncat(buf, quoted, sizeof(buf)-1);
1864 free(quoted);
1865
1866 send_shellcommand(transport, serial, buf);
1867 return 0;
1868}
1869
Kenny Root3802c992011-08-05 11:19:45 -07001870static const char* get_basename(const char* filename)
1871{
1872 const char* basename = adb_dirstop(filename);
1873 if (basename) {
1874 basename++;
1875 return basename;
1876 } else {
1877 return filename;
1878 }
1879}
1880
Kenny Root3802c992011-08-05 11:19:45 -07001881int install_app(transport_type transport, char* serial, int argc, char** argv)
1882{
1883 static const char *const DATA_DEST = "/data/local/tmp/%s";
1884 static const char *const SD_DEST = "/sdcard/tmp/%s";
1885 const char* where = DATA_DEST;
Kenny Root3802c992011-08-05 11:19:45 -07001886 int i;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001887 struct stat sb;
Kenny Root3802c992011-08-05 11:19:45 -07001888
1889 for (i = 1; i < argc; i++) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001890 if (!strcmp(argv[i], "-s")) {
Kenny Root3802c992011-08-05 11:19:45 -07001891 where = SD_DEST;
1892 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001893 }
1894
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001895 // Find last APK argument.
1896 // All other arguments passed through verbatim.
1897 int last_apk = -1;
1898 for (i = argc - 1; i >= 0; i--) {
1899 char* file = argv[i];
1900 char* dot = strrchr(file, '.');
1901 if (dot && !strcasecmp(dot, ".apk")) {
1902 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1903 fprintf(stderr, "Invalid APK file: %s\n", file);
1904 return -1;
1905 }
1906
1907 last_apk = i;
1908 break;
1909 }
Kenny Root3802c992011-08-05 11:19:45 -07001910 }
1911
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001912 if (last_apk == -1) {
1913 fprintf(stderr, "Missing APK file\n");
1914 return -1;
Kenny Root3802c992011-08-05 11:19:45 -07001915 }
1916
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001917 char* apk_file = argv[last_apk];
1918 char apk_dest[PATH_MAX];
Kenny Root3802c992011-08-05 11:19:45 -07001919 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001920 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001921 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001922 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001923 } else {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001924 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root3802c992011-08-05 11:19:45 -07001925 }
1926
1927 pm_command(transport, serial, argc, argv);
1928
Kenny Root58d5f222012-03-26 16:14:02 -07001929cleanup_apk:
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001930 delete_file(transport, serial, apk_dest);
1931 return err;
1932}
1933
1934int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1935{
1936 char buf[1024];
1937 int i;
1938 struct stat sb;
1939 unsigned long long total_size = 0;
1940
1941 // Find all APK arguments starting at end.
1942 // All other arguments passed through verbatim.
1943 int first_apk = -1;
1944 for (i = argc - 1; i >= 0; i--) {
1945 char* file = argv[i];
1946 char* dot = strrchr(file, '.');
1947 if (dot && !strcasecmp(dot, ".apk")) {
1948 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1949 fprintf(stderr, "Invalid APK file: %s\n", file);
1950 return -1;
1951 }
1952
1953 total_size += sb.st_size;
1954 first_apk = i;
1955 } else {
1956 break;
1957 }
Kenny Root3802c992011-08-05 11:19:45 -07001958 }
1959
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001960 if (first_apk == -1) {
1961 fprintf(stderr, "Missing APK file\n");
1962 return 1;
1963 }
Kenny Root3802c992011-08-05 11:19:45 -07001964
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001965 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1966 for (i = 1; i < first_apk; i++) {
1967 char *quoted = escape_arg(argv[i]);
1968 strncat(buf, " ", sizeof(buf) - 1);
1969 strncat(buf, quoted, sizeof(buf) - 1);
1970 free(quoted);
1971 }
1972
1973 // Create install session
1974 int fd = adb_connect(buf);
1975 if (fd < 0) {
1976 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1977 return -1;
1978 }
1979 read_status_line(fd, buf, sizeof(buf));
1980 adb_close(fd);
1981
1982 int session_id = -1;
1983 if (!strncmp("Success", buf, 7)) {
1984 char* start = strrchr(buf, '[');
1985 char* end = strrchr(buf, ']');
1986 if (start && end) {
1987 *end = '\0';
1988 session_id = strtol(start + 1, NULL, 10);
1989 }
1990 }
1991 if (session_id < 0) {
1992 fprintf(stderr, "Failed to create session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07001993 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001994 return -1;
1995 }
1996
1997 // Valid session, now stream the APKs
1998 int success = 1;
1999 for (i = first_apk; i < argc; i++) {
2000 char* file = argv[i];
2001 if (stat(file, &sb) == -1) {
2002 fprintf(stderr, "Failed to stat %s\n", file);
2003 success = 0;
2004 goto finalize_session;
2005 }
2006
2007 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkey4a7ddb62014-07-14 13:57:54 -07002008 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002009
2010 int localFd = adb_open(file, O_RDONLY);
2011 if (localFd < 0) {
2012 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2013 success = 0;
2014 goto finalize_session;
2015 }
2016
2017 int remoteFd = adb_connect(buf);
2018 if (remoteFd < 0) {
2019 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2020 adb_close(localFd);
2021 success = 0;
2022 goto finalize_session;
2023 }
2024
2025 copy_to_file(localFd, remoteFd);
2026 read_status_line(remoteFd, buf, sizeof(buf));
2027
2028 adb_close(localFd);
2029 adb_close(remoteFd);
2030
2031 if (strncmp("Success", buf, 7)) {
2032 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate29721da2014-07-14 16:45:13 -07002033 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002034 success = 0;
2035 goto finalize_session;
2036 }
2037 }
2038
2039finalize_session:
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002040 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002041 if (success) {
2042 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2043 } else {
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002044 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002045 }
2046
2047 fd = adb_connect(buf);
2048 if (fd < 0) {
2049 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2050 return -1;
2051 }
2052 read_status_line(fd, buf, sizeof(buf));
2053 adb_close(fd);
2054
2055 if (!strncmp("Success", buf, 7)) {
Christopher Tate29721da2014-07-14 16:45:13 -07002056 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002057 return 0;
2058 } else {
2059 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002060 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002061 return -1;
2062 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08002063}