blob: 51c039efc07b94433dddcf760c1174b02b2f64c8 [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>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov857f17a2009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -070044 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080045int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -070046int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080047int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
48
49static const char *gProductOutPath = NULL;
Matt Gumbel411775c2012-11-14 10:16:17 -080050extern int gListenAll;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080051
52static char *product_file(const char *extra)
53{
54 int n;
55 char *x;
56
57 if (gProductOutPath == NULL) {
58 fprintf(stderr, "adb: Product directory not specified; "
59 "use -p or define ANDROID_PRODUCT_OUT\n");
60 exit(1);
61 }
62
63 n = strlen(gProductOutPath) + strlen(extra) + 2;
64 x = malloc(n);
65 if (x == 0) {
66 fprintf(stderr, "adb: Out of memory (product_file())\n");
67 exit(1);
68 }
69
70 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
71 return x;
72}
73
74void version(FILE * out) {
75 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
76 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
77}
78
79void help()
80{
81 version(stderr);
82
83 fprintf(stderr,
84 "\n"
Matt Gumbel411775c2012-11-14 10:16:17 -080085 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080086 " -d - directs command to the only connected USB device\n"
87 " returns an error if more than one USB device is present.\n"
88 " -e - directs command to the only running emulator.\n"
89 " returns an error if more than one emulator is running.\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -070090 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson27042382012-05-30 18:11:27 -070091 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070092 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080093 " -p <product name or path> - simple product name like 'sooner', or\n"
94 " a relative/absolute path to a product\n"
95 " out directory like 'out/target/product/sooner'.\n"
96 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
97 " environment variable is used, which must\n"
98 " be an absolute path.\n"
Matt Gumbel411775c2012-11-14 10:16:17 -080099 " -H - Name of adb server host (default: localhost)\n"
100 " -P - Port of adb server (default: 5037)\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700101 " devices [-l] - list all connected devices\n"
Scott Anderson27042382012-05-30 18:11:27 -0700102 " ('-l' will also list device qualifiers)\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400103 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
104 " Port 5555 is used by default if no port number is specified.\n"
105 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
106 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischerc3e82b82011-04-26 12:46:05 +0200107 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400108 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800109 "\n"
110 "device commands:\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700111 " adb push [-p] <local> <remote>\n"
112 " - copy file/dir to device\n"
113 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700114 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700115 " - copy file/dir from device\n"
116 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700117 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800118 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600119 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800120 " (see 'adb help all')\n"
121 " adb shell - run remote shell interactively\n"
122 " adb shell <command> - run remote shell command\n"
123 " adb emu <command> - run emulator console command\n"
124 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100125 " adb forward --list - list all forward socket connections.\n"
126 " the format is a list of lines with the following format:\n"
127 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800128 " adb forward <local> <remote> - forward socket connections\n"
129 " forward specs are one of: \n"
130 " tcp:<port>\n"
131 " localabstract:<unix domain socket name>\n"
132 " localreserved:<unix domain socket name>\n"
133 " localfilesystem:<unix domain socket name>\n"
134 " dev:<character device name>\n"
135 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100136 " adb forward --no-rebind <local> <remote>\n"
137 " - same as 'adb forward <local> <remote>' but fails\n"
138 " if <local> is already forwarded\n"
139 " adb forward --remove <local> - remove a specific forward socket connection\n"
140 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner963a4492013-03-21 21:07:42 +0100141 " adb reverse --list - list all reverse socket connections from device\n"
142 " adb reverse <remote> <local> - reverse socket connections\n"
143 " reverse specs are one of:\n"
144 " tcp:<port>\n"
145 " localabstract:<unix domain socket name>\n"
146 " localreserved:<unix domain socket name>\n"
147 " localfilesystem:<unix domain socket name>\n"
148 " adb reverse --norebind <remote> <local>\n"
149 " - same as 'adb reverse <remote> <local>' but fails\n"
150 " if <remote> is already reversed.\n"
151 " adb reverse --remove <remote>\n"
152 " - remove a specific reversed socket connection\n"
153 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800154 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700155 " adb install [-lrtsd] <file>\n"
156 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700157 " - push this package file to the device and install it\n"
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700158 " (-l: forward lock application)\n"
159 " (-r: replace existing application)\n"
160 " (-t: allow test packages)\n"
161 " (-s: install application on sdcard)\n"
162 " (-d: allow version code downgrade)\n"
163 " (-p: partial application install)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800164 " adb uninstall [-k] <package> - remove this app package from the device\n"
165 " ('-k' means keep the data and cache directories)\n"
166 " adb bugreport - return all information from the device\n"
167 " that should be included in a bug report.\n"
168 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800169 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700170 " - write an archive of the device's data to <file>.\n"
171 " If no -f option is supplied then the data is written\n"
172 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700173 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700174 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800175 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
176 " (aka .obb) files associated with each application; the default\n"
177 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700178 " (-shared|-noshared enable/disable backup of the device's\n"
179 " shared storage / SD card contents; the default is noshared.)\n"
180 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700181 " (-system|-nosystem toggles whether -all automatically includes\n"
182 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700183 " (<packages...> is the list of applications to be backed up. If\n"
184 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700185 " list is optional. Applications explicitly given on the\n"
186 " command line will be included even if -nosystem would\n"
187 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700188 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700189 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700190 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800191 " adb help - show this help message\n"
192 " adb version - show version num\n"
193 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800194 "scripting:\n"
195 " adb wait-for-device - block until device is online\n"
196 " adb start-server - ensure that there is a server running\n"
197 " adb kill-server - kill the server if it is running\n"
198 " adb get-state - prints: offline | bootloader | device\n"
199 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700200 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800201 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700202 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400203 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800204 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700205 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800206 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700207 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800208 "\n"
209 "networking:\n"
210 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500211 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800212 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
213 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
214 "\n"
215 "adb sync notes: adb sync [ <directory> ]\n"
216 " <localdir> can be interpreted in several ways:\n"
217 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700218 " - 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 -0800219 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700220 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800221 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000222 "\n"
223 "environmental variables:\n"
224 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
225 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
226 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
227 " 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 -0800228 );
229}
230
231int usage()
232{
233 help();
234 return 1;
235}
236
237#ifdef HAVE_TERMIO_H
238static struct termios tio_save;
239
240static void stdin_raw_init(int fd)
241{
242 struct termios tio;
243
244 if(tcgetattr(fd, &tio)) return;
245 if(tcgetattr(fd, &tio_save)) return;
246
247 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
248
249 /* no timeout but request at least one character per read */
250 tio.c_cc[VTIME] = 0;
251 tio.c_cc[VMIN] = 1;
252
253 tcsetattr(fd, TCSANOW, &tio);
254 tcflush(fd, TCIFLUSH);
255}
256
257static void stdin_raw_restore(int fd)
258{
259 tcsetattr(fd, TCSANOW, &tio_save);
260 tcflush(fd, TCIFLUSH);
261}
262#endif
263
264static void read_and_dump(int fd)
265{
266 char buf[4096];
267 int len;
268
269 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700270 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800271 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700272 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800273 if(len == 0) {
274 break;
275 }
276
277 if(len < 0) {
278 if(errno == EINTR) continue;
279 break;
280 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400281 fwrite(buf, 1, len, stdout);
282 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800283 }
284}
285
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700286static void read_status_line(int fd, char* buf, size_t count)
287{
288 count--;
289 while (count > 0) {
290 int len = adb_read(fd, buf, count);
291 if (len == 0) {
292 break;
293 } else if (len < 0) {
294 if (errno == EINTR) continue;
295 break;
296 }
297
298 buf += len;
299 count -= len;
300 }
301 *buf = '\0';
302}
303
Christopher Tate73779122011-04-21 12:53:28 -0700304static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700305 const size_t BUFSIZE = 32 * 1024;
306 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700307 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700308 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700309
310 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700311#ifdef HAVE_TERMIO_H
312 if (inFd == STDIN_FILENO) {
313 stdin_raw_init(STDIN_FILENO);
314 }
315#endif
Christopher Tate73779122011-04-21 12:53:28 -0700316 for (;;) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700317 if (inFd == STDIN_FILENO) {
318 len = unix_read(inFd, buf, BUFSIZE);
319 } else {
320 len = adb_read(inFd, buf, BUFSIZE);
321 }
Christopher Tate73779122011-04-21 12:53:28 -0700322 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700323 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700324 break;
325 }
326 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700327 if (errno == EINTR) {
328 D("copy_to_file() : EINTR, retrying\n");
329 continue;
330 }
Christopher Tate73779122011-04-21 12:53:28 -0700331 D("copy_to_file() : error %d\n", errno);
332 break;
333 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700334 if (outFd == STDOUT_FILENO) {
335 fwrite(buf, 1, len, stdout);
336 fflush(stdout);
337 } else {
338 adb_write(outFd, buf, len);
339 }
Christopher Tatefba22972011-06-01 17:56:23 -0700340 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700341 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700342#ifdef HAVE_TERMIO_H
343 if (inFd == STDIN_FILENO) {
344 stdin_raw_restore(STDIN_FILENO);
345 }
346#endif
Christopher Tatefba22972011-06-01 17:56:23 -0700347 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700348 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700349}
350
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800351static void *stdin_read_thread(void *x)
352{
353 int fd, fdi;
354 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800355 int r, n;
356 int state = 0;
357
358 int *fds = (int*) x;
359 fd = fds[0];
360 fdi = fds[1];
361 free(fds);
362
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800363 for(;;) {
364 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700365 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800366 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700367 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800368 if(r == 0) break;
369 if(r < 0) {
370 if(errno == EINTR) continue;
371 break;
372 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400373 for(n = 0; n < r; n++){
374 switch(buf[n]) {
375 case '\n':
376 state = 1;
377 break;
378 case '\r':
379 state = 1;
380 break;
381 case '~':
382 if(state == 1) state++;
383 break;
384 case '.':
385 if(state == 2) {
386 fprintf(stderr,"\n* disconnect *\n");
387#ifdef HAVE_TERMIO_H
388 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800389#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400390 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800391 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400392 default:
393 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800394 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800395 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800396 r = adb_write(fd, buf, r);
397 if(r <= 0) {
398 break;
399 }
400 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800401 return 0;
402}
403
404int interactive_shell(void)
405{
406 adb_thread_t thr;
407 int fdi, fd;
408 int *fds;
409
410 fd = adb_connect("shell:");
411 if(fd < 0) {
412 fprintf(stderr,"error: %s\n", adb_error());
413 return 1;
414 }
415 fdi = 0; //dup(0);
416
417 fds = malloc(sizeof(int) * 2);
418 fds[0] = fd;
419 fds[1] = fdi;
420
421#ifdef HAVE_TERMIO_H
422 stdin_raw_init(fdi);
423#endif
424 adb_thread_create(&thr, stdin_read_thread, fds);
425 read_and_dump(fd);
426#ifdef HAVE_TERMIO_H
427 stdin_raw_restore(fdi);
428#endif
429 return 0;
430}
431
432
433static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
434{
435 if (serial) {
436 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
437 } else {
438 const char* prefix = "host";
439 if (ttype == kTransportUsb)
440 prefix = "host-usb";
441 else if (ttype == kTransportLocal)
442 prefix = "host-local";
443
444 snprintf(buffer, buflen, "%s:%s", prefix, command);
445 }
446}
447
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100448int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800449 unsigned progress)
450{
451 char buf[4096];
452 unsigned total;
453 int fd;
454 const unsigned char *ptr;
455
456 sprintf(buf,"%s:%d", service, sz);
457 fd = adb_connect(buf);
458 if(fd < 0) {
459 fprintf(stderr,"error: %s\n", adb_error());
460 return -1;
461 }
462
463 int opt = CHUNK_SIZE;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700464 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800465
466 total = sz;
467 ptr = data;
468
469 if(progress) {
470 char *x = strrchr(service, ':');
471 if(x) service = x + 1;
472 }
473
474 while(sz > 0) {
475 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
476 if(writex(fd, ptr, xfer)) {
477 adb_status(fd);
478 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
479 return -1;
480 }
481 sz -= xfer;
482 ptr += xfer;
483 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100484 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800485 fflush(stdout);
486 }
487 }
488 if(progress) {
489 printf("\n");
490 }
491
492 if(readx(fd, buf, 4)){
493 fprintf(stderr,"* error reading response *\n");
494 adb_close(fd);
495 return -1;
496 }
497 if(memcmp(buf, "OKAY", 4)) {
498 buf[4] = 0;
499 fprintf(stderr,"* error response '%s' *\n", buf);
500 adb_close(fd);
501 return -1;
502 }
503
504 adb_close(fd);
505 return 0;
506}
507
508
509int adb_download(const char *service, const char *fn, unsigned progress)
510{
511 void *data;
512 unsigned sz;
513
514 data = load_file(fn, &sz);
515 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100516 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800517 return -1;
518 }
519
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100520 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800521 free(data);
522 return status;
523}
524
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700525#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
526
527/*
528 * The sideload-host protocol serves the data in a file (given on the
529 * command line) to the client, using a simple protocol:
530 *
531 * - The connect message includes the total number of bytes in the
532 * file and a block size chosen by us.
533 *
534 * - The other side sends the desired block number as eight decimal
535 * digits (eg "00000023" for block 23). Blocks are numbered from
536 * zero.
537 *
538 * - We send back the data of the requested block. The last block is
539 * likely to be partial; when the last block is requested we only
540 * send the part of the block that exists, it's not padded up to the
541 * block size.
542 *
543 * - When the other side sends "DONEDONE" instead of a block number,
544 * we hang up.
545 */
546int adb_sideload_host(const char* fn) {
547 uint8_t* data;
548 unsigned sz;
549 size_t xfer = 0;
550 int status;
551
552 printf("loading: '%s'", fn);
553 fflush(stdout);
554 data = load_file(fn, &sz);
555 if (data == 0) {
556 printf("\n");
557 fprintf(stderr, "* cannot read '%s' *\n", fn);
558 return -1;
559 }
560
561 char buf[100];
562 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
563 int fd = adb_connect(buf);
564 if (fd < 0) {
565 // Try falling back to the older sideload method. Maybe this
566 // is an older device that doesn't support sideload-host.
567 printf("\n");
568 status = adb_download_buffer("sideload", fn, data, sz, 1);
569 goto done;
570 }
571
572 int opt = SIDELOAD_HOST_BLOCK_SIZE;
573 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
574
575 int last_percent = -1;
Doug Zongkera27ee6c2014-07-07 15:28:43 -0700576 for (;;) {
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700577 if (readx(fd, buf, 8)) {
578 fprintf(stderr, "* failed to read command: %s\n", adb_error());
579 status = -1;
580 goto done;
581 }
582
583 if (strncmp("DONEDONE", buf, 8) == 0) {
584 status = 0;
585 break;
586 }
587
588 buf[8] = '\0';
589 int block = strtol(buf, NULL, 10);
590
591 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
592 if (offset >= sz) {
593 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
594 status = -1;
595 goto done;
596 }
597 uint8_t* start = data + offset;
598 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
599 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
600 if (offset_end > sz) {
601 to_write = sz - offset;
602 }
603
604 if(writex(fd, start, to_write)) {
605 adb_status(fd);
606 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
607 status = -1;
608 goto done;
609 }
610 xfer += to_write;
611
612 // For normal OTA packages, we expect to transfer every byte
613 // twice, plus a bit of overhead (one read during
614 // verification, one read of each byte for installation, plus
615 // extra access to things like the zip central directory).
616 // This estimate of the completion becomes 100% when we've
617 // transferred ~2.13 (=100/47) times the package size.
618 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
619 if (percent != last_percent) {
620 printf("\rserving: '%s' (~%d%%) ", fn, percent);
621 fflush(stdout);
622 last_percent = percent;
623 }
624 }
625
Colin Cross2328bea2014-07-07 14:12:41 -0700626 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700627
628 done:
629 if (fd >= 0) adb_close(fd);
630 free(data);
631 return status;
632}
633
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800634static void status_window(transport_type ttype, const char* serial)
635{
636 char command[4096];
637 char *state = 0;
638 char *laststate = 0;
639
640 /* silence stderr */
641#ifdef _WIN32
642 /* XXX: TODO */
643#else
644 int fd;
645 fd = unix_open("/dev/null", O_WRONLY);
646 dup2(fd, 2);
647 adb_close(fd);
648#endif
649
650 format_host_command(command, sizeof command, "get-state", ttype, serial);
651
652 for(;;) {
653 adb_sleep_ms(250);
654
655 if(state) {
656 free(state);
657 state = 0;
658 }
659
660 state = adb_query(command);
661
662 if(state) {
663 if(laststate && !strcmp(state,laststate)){
664 continue;
665 } else {
666 if(laststate) free(laststate);
667 laststate = strdup(state);
668 }
669 }
670
671 printf("%c[2J%c[2H", 27, 27);
672 printf("Android Debug Bridge\n");
673 printf("State: %s\n", state ? state : "offline");
674 fflush(stdout);
675 }
676}
677
Brian Carlstrom529fca82014-08-05 22:51:18 -0700678static int should_escape(const char c)
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700679{
680 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
681}
682
683/* Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700684static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800685{
686 const char *ts;
687 size_t alloc_len;
688 char *ret;
689 char *dest;
690
Jeff Sharkey026d9622014-06-10 16:22:17 -0700691 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700692 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800693 alloc_len++;
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700694 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800695 alloc_len++;
696 }
697 }
698
Jeff Sharkey026d9622014-06-10 16:22:17 -0700699 if (alloc_len == 0) {
700 // Preserve empty arguments
701 ret = (char *) malloc(3);
702 ret[0] = '\"';
703 ret[1] = '\"';
704 ret[2] = '\0';
705 return ret;
706 }
707
Jeff Sharkey824d1062014-06-10 11:31:24 -0700708 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800709 dest = ret;
710
Jeff Sharkey824d1062014-06-10 11:31:24 -0700711 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700712 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800713 *dest++ = '\\';
714 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800715 *dest++ = *ts;
716 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800717 *dest++ = '\0';
718
719 return ret;
720}
721
722/**
723 * Run ppp in "notty" mode against a resource listed as the first parameter
724 * eg:
725 *
726 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
727 *
728 */
729int ppp(int argc, char **argv)
730{
731#ifdef HAVE_WIN32_PROC
732 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
733 return -1;
734#else
735 char *adb_service_name;
736 pid_t pid;
737 int fd;
738
739 if (argc < 2) {
740 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
741 argv[0]);
742
743 return 1;
744 }
745
746 adb_service_name = argv[1];
747
748 fd = adb_connect(adb_service_name);
749
750 if(fd < 0) {
751 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
752 adb_service_name, adb_error());
753 return 1;
754 }
755
756 pid = fork();
757
758 if (pid < 0) {
759 perror("from fork()");
760 return 1;
761 } else if (pid == 0) {
762 int err;
763 int i;
764 const char **ppp_args;
765
766 // copy args
767 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
768 ppp_args[0] = "pppd";
769 for (i = 2 ; i < argc ; i++) {
770 //argv[2] and beyond become ppp_args[1] and beyond
771 ppp_args[i - 1] = argv[i];
772 }
773 ppp_args[i-1] = NULL;
774
775 // child side
776
777 dup2(fd, STDIN_FILENO);
778 dup2(fd, STDOUT_FILENO);
779 adb_close(STDERR_FILENO);
780 adb_close(fd);
781
782 err = execvp("pppd", (char * const *)ppp_args);
783
784 if (err < 0) {
785 perror("execing pppd");
786 }
787 exit(-1);
788 } else {
789 // parent side
790
791 adb_close(fd);
792 return 0;
793 }
794#endif /* !HAVE_WIN32_PROC */
795}
796
797static int send_shellcommand(transport_type transport, char* serial, char* buf)
798{
799 int fd, ret;
800
801 for(;;) {
802 fd = adb_connect(buf);
803 if(fd >= 0)
804 break;
805 fprintf(stderr,"- waiting for device -\n");
806 adb_sleep_ms(1000);
807 do_cmd(transport, serial, "wait-for-device", 0);
808 }
809
810 read_and_dump(fd);
811 ret = adb_close(fd);
812 if (ret)
813 perror("close");
814
815 return ret;
816}
817
818static int logcat(transport_type transport, char* serial, int argc, char **argv)
819{
820 char buf[4096];
821
822 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700823 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800824
825 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700826 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800827 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700828 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700829 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800830
Jeff Sharkey824d1062014-06-10 11:31:24 -0700831 if (!strcmp(argv[0], "longcat")) {
832 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800833 }
834
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800835 argc -= 1;
836 argv += 1;
837 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700838 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700839 strncat(buf, " ", sizeof(buf) - 1);
840 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800841 free(quoted);
842 }
843
844 send_shellcommand(transport, serial, buf);
845 return 0;
846}
847
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700848static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800849{
850 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700851 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800852
853 for(;;) {
854 x = adb_dirstart(x);
855 if(x == 0) return 0;
856 *x = 0;
857 ret = adb_mkdir(path, 0775);
858 *x = OS_PATH_SEPARATOR;
859 if((ret < 0) && (errno != EEXIST)) {
860 return ret;
861 }
862 x++;
863 }
864 return 0;
865}
866
Christopher Tate73779122011-04-21 12:53:28 -0700867static int backup(int argc, char** argv) {
868 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800869 char default_name[32];
870 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700871 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700872 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700873
Christopher Tatefba22972011-06-01 17:56:23 -0700874 /* find, extract, and use any -f argument */
875 for (i = 1; i < argc; i++) {
876 if (!strcmp("-f", argv[i])) {
877 if (i == argc-1) {
878 fprintf(stderr, "adb: -f passed with no filename\n");
879 return usage();
880 }
881 filename = argv[i+1];
882 for (j = i+2; j <= argc; ) {
883 argv[i++] = argv[j++];
884 }
885 argc -= 2;
886 argv[argc] = NULL;
887 }
Christopher Tate73779122011-04-21 12:53:28 -0700888 }
889
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700890 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
891 if (argc < 2) return usage();
892
Christopher Tate1e9f2392011-12-08 19:04:34 -0800893 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700894 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800895 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700896 if (outFd < 0) {
897 fprintf(stderr, "adb: unable to open file %s\n", filename);
898 return -1;
899 }
900
901 snprintf(buf, sizeof(buf), "backup");
902 for (argc--, argv++; argc; argc--, argv++) {
903 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
904 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
905 }
906
907 D("backup. filename=%s buf=%s\n", filename, buf);
908 fd = adb_connect(buf);
909 if (fd < 0) {
910 fprintf(stderr, "adb: unable to connect for backup\n");
911 adb_close(outFd);
912 return -1;
913 }
914
Christopher Tate9c829102012-01-06 15:43:03 -0800915 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700916 copy_to_file(fd, outFd);
917
918 adb_close(fd);
919 adb_close(outFd);
920 return 0;
921}
922
Christopher Tatecf5379b2011-05-17 15:52:54 -0700923static int restore(int argc, char** argv) {
924 const char* filename;
925 int fd, tarFd;
926
927 if (argc != 2) return usage();
928
929 filename = argv[1];
930 tarFd = adb_open(filename, O_RDONLY);
931 if (tarFd < 0) {
932 fprintf(stderr, "adb: unable to open file %s\n", filename);
933 return -1;
934 }
935
936 fd = adb_connect("restore:");
937 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700938 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700939 adb_close(tarFd);
940 return -1;
941 }
942
Christopher Tate9c829102012-01-06 15:43:03 -0800943 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700944 copy_to_file(tarFd, fd);
945
946 adb_close(fd);
947 adb_close(tarFd);
948 return 0;
949}
950
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800951#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
952static int top_works(const char *top)
953{
954 if (top != NULL && adb_is_absolute_host_path(top)) {
955 char path_buf[PATH_MAX];
956 snprintf(path_buf, sizeof(path_buf),
957 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
958 return access(path_buf, F_OK) == 0;
959 }
960 return 0;
961}
962
963static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
964{
965 strcpy(path_buf, indir);
966 while (1) {
967 if (top_works(path_buf)) {
968 return path_buf;
969 }
970 char *s = adb_dirstop(path_buf);
971 if (s != NULL) {
972 *s = '\0';
973 } else {
974 path_buf[0] = '\0';
975 return NULL;
976 }
977 }
978}
979
980static char *find_top(char path_buf[PATH_MAX])
981{
982 char *top = getenv("ANDROID_BUILD_TOP");
983 if (top != NULL && top[0] != '\0') {
984 if (!top_works(top)) {
985 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
986 return NULL;
987 }
988 } else {
989 top = getenv("TOP");
990 if (top != NULL && top[0] != '\0') {
991 if (!top_works(top)) {
992 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
993 return NULL;
994 }
995 } else {
996 top = NULL;
997 }
998 }
999
1000 if (top != NULL) {
1001 /* The environment pointed to a top directory that works.
1002 */
1003 strcpy(path_buf, top);
1004 return path_buf;
1005 }
1006
1007 /* The environment didn't help. Walk up the tree from the CWD
1008 * to see if we can find the top.
1009 */
1010 char dir[PATH_MAX];
1011 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1012 if (top == NULL) {
1013 /* If the CWD isn't under a good-looking top, see if the
1014 * executable is.
1015 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +11001016 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001017 top = find_top_from(dir, path_buf);
1018 }
1019 return top;
1020}
1021
1022/* <hint> may be:
1023 * - A simple product name
1024 * e.g., "sooner"
1025TODO: debug? sooner-debug, sooner:debug?
1026 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1027 * e.g., "out/target/product/sooner"
1028 * - An absolute path to the PRODUCT_OUT dir
1029 * e.g., "/src/device/out/target/product/sooner"
1030 *
1031 * Given <hint>, try to construct an absolute path to the
1032 * ANDROID_PRODUCT_OUT dir.
1033 */
1034static const char *find_product_out_path(const char *hint)
1035{
1036 static char path_buf[PATH_MAX];
1037
1038 if (hint == NULL || hint[0] == '\0') {
1039 return NULL;
1040 }
1041
1042 /* If it's already absolute, don't bother doing any work.
1043 */
1044 if (adb_is_absolute_host_path(hint)) {
1045 strcpy(path_buf, hint);
1046 return path_buf;
1047 }
1048
1049 /* If there are any slashes in it, assume it's a relative path;
1050 * make it absolute.
1051 */
1052 if (adb_dirstart(hint) != NULL) {
1053 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1054 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1055 return NULL;
1056 }
1057 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1058 fprintf(stderr, "adb: Couldn't assemble path\n");
1059 return NULL;
1060 }
1061 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1062 strcat(path_buf, hint);
1063 return path_buf;
1064 }
1065
1066 /* It's a string without any slashes. Try to do something with it.
1067 *
1068 * Try to find the root of the build tree, and build a PRODUCT_OUT
1069 * path from there.
1070 */
1071 char top_buf[PATH_MAX];
1072 const char *top = find_top(top_buf);
1073 if (top == NULL) {
1074 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1075 return NULL;
1076 }
1077//TODO: if we have a way to indicate debug, look in out/debug/target/...
1078 snprintf(path_buf, sizeof(path_buf),
1079 "%s" OS_PATH_SEPARATOR_STR
1080 "out" OS_PATH_SEPARATOR_STR
1081 "target" OS_PATH_SEPARATOR_STR
1082 "product" OS_PATH_SEPARATOR_STR
1083 "%s", top_buf, hint);
1084 if (access(path_buf, F_OK) < 0) {
1085 fprintf(stderr, "adb: Couldn't find a product dir "
1086 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1087 return NULL;
1088 }
1089 return path_buf;
1090}
1091
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001092static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1093 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001094 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001095 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001096
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001097 while (narg > 0) {
1098 if (!strcmp(*arg, "-p")) {
1099 *show_progress = 1;
1100 } else if (!strcmp(*arg, "-a")) {
1101 *copy_attrs = 1;
1102 } else {
1103 break;
1104 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001105 ++arg;
1106 --narg;
1107 }
1108
1109 if (narg > 0) {
1110 *path1 = *arg;
1111 ++arg;
1112 --narg;
1113 }
1114
1115 if (narg > 0) {
1116 *path2 = *arg;
1117 }
1118}
1119
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001120int adb_commandline(int argc, char **argv)
1121{
1122 char buf[4096];
1123 int no_daemon = 0;
1124 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001125 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001126 int persist = 0;
1127 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001128 transport_type ttype = kTransportAny;
1129 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001130 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001131
1132 /* If defined, this should be an absolute path to
1133 * the directory containing all of the various system images
1134 * for a particular product. If not defined, and the adb
1135 * command requires this information, then the user must
1136 * specify the path using "-p".
1137 */
1138 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1139 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1140 gProductOutPath = NULL;
1141 }
1142 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1143
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001144 serial = getenv("ANDROID_SERIAL");
1145
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001146 /* Validate and assign the server port */
1147 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1148 int server_port = DEFAULT_ADB_PORT;
1149 if (server_port_str && strlen(server_port_str) > 0) {
1150 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001151 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001152 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001153 "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 +01001154 server_port_str);
1155 return usage();
1156 }
1157 }
1158
1159 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001160 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001161 if(!strcmp(argv[0],"server")) {
1162 is_server = 1;
1163 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001164 no_daemon = 1;
1165 } else if (!strcmp(argv[0], "fork-server")) {
1166 /* this is a special flag used only when the ADB client launches the ADB Server */
1167 is_daemon = 1;
1168 } else if(!strcmp(argv[0],"persist")) {
1169 persist = 1;
1170 } else if(!strncmp(argv[0], "-p", 2)) {
1171 const char *product = NULL;
1172 if (argv[0][2] == '\0') {
1173 if (argc < 2) return usage();
1174 product = argv[1];
1175 argc--;
1176 argv++;
1177 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001178 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001179 }
1180 gProductOutPath = find_product_out_path(product);
1181 if (gProductOutPath == NULL) {
1182 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1183 product);
1184 return usage();
1185 }
1186 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1187 if (isdigit(argv[0][2])) {
1188 serial = argv[0] + 2;
1189 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001190 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001191 serial = argv[1];
1192 argc--;
1193 argv++;
1194 }
1195 } else if (!strcmp(argv[0],"-d")) {
1196 ttype = kTransportUsb;
1197 } else if (!strcmp(argv[0],"-e")) {
1198 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001199 } else if (!strcmp(argv[0],"-a")) {
1200 gListenAll = 1;
1201 } else if(!strncmp(argv[0], "-H", 2)) {
1202 const char *hostname = NULL;
1203 if (argv[0][2] == '\0') {
1204 if (argc < 2) return usage();
1205 hostname = argv[1];
1206 argc--;
1207 argv++;
1208 } else {
1209 hostname = argv[0] + 2;
1210 }
1211 adb_set_tcp_name(hostname);
1212
1213 } else if(!strncmp(argv[0], "-P", 2)) {
1214 if (argv[0][2] == '\0') {
1215 if (argc < 2) return usage();
1216 server_port_str = argv[1];
1217 argc--;
1218 argv++;
1219 } else {
1220 server_port_str = argv[0] + 2;
1221 }
1222 if (strlen(server_port_str) > 0) {
1223 server_port = (int) strtol(server_port_str, NULL, 0);
1224 if (server_port <= 0 || server_port > 65535) {
1225 fprintf(stderr,
1226 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1227 server_port_str);
1228 return usage();
1229 }
1230 } else {
1231 fprintf(stderr,
1232 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1233 return usage();
1234 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001235 } else {
1236 /* out of recognized modifiers and flags */
1237 break;
1238 }
1239 argc--;
1240 argv++;
1241 }
1242
1243 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001244 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001245
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001246 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001247 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001248 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001249 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001250 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001251 }
1252 if(r) {
1253 fprintf(stderr,"* could not start server *\n");
1254 }
1255 return r;
1256 }
1257
1258top:
1259 if(argc == 0) {
1260 return usage();
1261 }
1262
1263 /* adb_connect() commands */
1264
1265 if(!strcmp(argv[0], "devices")) {
1266 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001267 char *listopt;
1268 if (argc < 2)
1269 listopt = "";
1270 else if (argc == 2 && !strcmp(argv[1], "-l"))
1271 listopt = argv[1];
1272 else {
1273 fprintf(stderr, "Usage: adb devices [-l]\n");
1274 return 1;
1275 }
1276 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001277 tmp = adb_query(buf);
1278 if(tmp) {
1279 printf("List of devices attached \n");
1280 printf("%s\n", tmp);
1281 return 0;
1282 } else {
1283 return 1;
1284 }
1285 }
1286
Mike Lockwood01c2c302010-05-24 10:44:35 -04001287 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001288 char *tmp;
1289 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001290 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001291 return 1;
1292 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001293 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1294 tmp = adb_query(buf);
1295 if(tmp) {
1296 printf("%s\n", tmp);
1297 return 0;
1298 } else {
1299 return 1;
1300 }
1301 }
1302
1303 if(!strcmp(argv[0], "disconnect")) {
1304 char *tmp;
1305 if (argc > 2) {
1306 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1307 return 1;
1308 }
1309 if (argc == 2) {
1310 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1311 } else {
1312 snprintf(buf, sizeof buf, "host:disconnect:");
1313 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001314 tmp = adb_query(buf);
1315 if(tmp) {
1316 printf("%s\n", tmp);
1317 return 0;
1318 } else {
1319 return 1;
1320 }
1321 }
1322
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001323 if (!strcmp(argv[0], "emu")) {
1324 return adb_send_emulator_command(argc, argv);
1325 }
1326
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001327 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001328 int r;
1329 int fd;
1330
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001331 char h = (argv[0][0] == 'h');
1332
1333 if (h) {
1334 printf("\x1b[41;33m");
1335 fflush(stdout);
1336 }
1337
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001338 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001339 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001340 r = interactive_shell();
1341 if (h) {
1342 printf("\x1b[0m");
1343 fflush(stdout);
1344 }
1345 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001346 }
1347
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001348 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001349 argc -= 2;
1350 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001351 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001352 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001353 strncat(buf, " ", sizeof(buf) - 1);
1354 strncat(buf, quoted, sizeof(buf) - 1);
1355 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001356 }
1357
1358 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001359 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001360 fd = adb_connect(buf);
1361 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001362 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001363 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001364 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001365 adb_close(fd);
1366 r = 0;
1367 } else {
1368 fprintf(stderr,"error: %s\n", adb_error());
1369 r = -1;
1370 }
1371
1372 if(persist) {
1373 fprintf(stderr,"\n- waiting for device -\n");
1374 adb_sleep_ms(1000);
1375 do_cmd(ttype, serial, "wait-for-device", 0);
1376 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001377 if (h) {
1378 printf("\x1b[0m");
1379 fflush(stdout);
1380 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001381 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001382 return r;
1383 }
1384 }
1385 }
1386
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001387 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1388 int exec_in = !strcmp(argv[0], "exec-in");
1389 int fd;
1390
1391 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1392 argc -= 2;
1393 argv += 2;
1394 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001395 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001396 strncat(buf, " ", sizeof(buf) - 1);
1397 strncat(buf, quoted, sizeof(buf) - 1);
1398 free(quoted);
1399 }
1400
1401 fd = adb_connect(buf);
1402 if (fd < 0) {
1403 fprintf(stderr, "error: %s\n", adb_error());
1404 return -1;
1405 }
1406
1407 if (exec_in) {
1408 copy_to_file(STDIN_FILENO, fd);
1409 } else {
1410 copy_to_file(fd, STDOUT_FILENO);
1411 }
1412
1413 adb_close(fd);
1414 return 0;
1415 }
1416
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001417 if(!strcmp(argv[0], "kill-server")) {
1418 int fd;
1419 fd = _adb_connect("host:kill");
1420 if(fd == -1) {
1421 fprintf(stderr,"* server not running *\n");
1422 return 1;
1423 }
1424 return 0;
1425 }
1426
Doug Zongker6b217ed2012-01-09 14:54:53 -08001427 if(!strcmp(argv[0], "sideload")) {
1428 if(argc != 2) return usage();
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001429 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001430 return 1;
1431 } else {
1432 return 0;
1433 }
1434 }
1435
Mike Lockwood26b88e32009-08-24 15:58:40 -07001436 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001437 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001438 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001439 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001440 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001441 if (!strcmp(argv[0], "reboot-bootloader"))
1442 snprintf(command, sizeof(command), "reboot:bootloader");
1443 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001444 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001445 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001446 snprintf(command, sizeof(command), "%s:", argv[0]);
1447 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001448 if(fd >= 0) {
1449 read_and_dump(fd);
1450 adb_close(fd);
1451 return 0;
1452 }
1453 fprintf(stderr,"error: %s\n", adb_error());
1454 return 1;
1455 }
1456
Mike Lockwood78589f32009-09-03 14:54:58 -04001457 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001458 if (argc != 1) return usage();
1459 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001460 return 0;
1461 }
1462
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001463 /* adb_command() wrapper commands */
1464
1465 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1466 char* service = argv[0];
1467 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1468 if (ttype == kTransportUsb) {
1469 service = "wait-for-usb";
1470 } else if (ttype == kTransportLocal) {
1471 service = "wait-for-local";
1472 } else {
1473 service = "wait-for-any";
1474 }
1475 }
1476
1477 format_host_command(buf, sizeof buf, service, ttype, serial);
1478
1479 if (adb_command(buf)) {
1480 D("failure: %s *\n",adb_error());
1481 fprintf(stderr,"error: %s\n", adb_error());
1482 return 1;
1483 }
1484
1485 /* Allow a command to be run after wait-for-device,
1486 * e.g. 'adb wait-for-device shell'.
1487 */
1488 if(argc > 1) {
1489 argc--;
1490 argv++;
1491 goto top;
1492 }
1493 return 0;
1494 }
1495
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001496 if(!strcmp(argv[0], "forward") ||
1497 !strcmp(argv[0], "reverse"))
1498 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001499 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001500 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001501 char remove = 0;
1502 char remove_all = 0;
1503 char list = 0;
1504 char no_rebind = 0;
1505
1506 // Parse options here.
1507 while (argc > 1 && argv[1][0] == '-') {
1508 if (!strcmp(argv[1], "--list"))
1509 list = 1;
1510 else if (!strcmp(argv[1], "--remove"))
1511 remove = 1;
1512 else if (!strcmp(argv[1], "--remove-all"))
1513 remove_all = 1;
1514 else if (!strcmp(argv[1], "--no-rebind"))
1515 no_rebind = 1;
1516 else {
1517 return usage();
1518 }
1519 argc--;
1520 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001521 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001522
1523 // Ensure we can only use one option at a time.
1524 if (list + remove + remove_all + no_rebind > 1) {
1525 return usage();
1526 }
1527
1528 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001529 if (reverse) {
1530 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001531 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001532 if (serial) {
1533 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1534 serial);
1535 } else if (ttype == kTransportUsb) {
1536 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1537 } else if (ttype == kTransportLocal) {
1538 snprintf(host_prefix, sizeof host_prefix, "host-local");
1539 } else {
1540 snprintf(host_prefix, sizeof host_prefix, "host");
1541 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001542 }
1543
1544 // Implement forward --list
1545 if (list) {
1546 if (argc != 1)
1547 return usage();
1548 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1549 char* forwards = adb_query(buf);
1550 if (forwards == NULL) {
1551 fprintf(stderr, "error: %s\n", adb_error());
1552 return 1;
1553 }
1554 printf("%s", forwards);
1555 free(forwards);
1556 return 0;
1557 }
1558
1559 // Implement forward --remove-all
1560 else if (remove_all) {
1561 if (argc != 1)
1562 return usage();
1563 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1564 }
1565
1566 // Implement forward --remove <local>
1567 else if (remove) {
1568 if (argc != 2)
1569 return usage();
1570 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1571 }
1572 // Or implement one of:
1573 // forward <local> <remote>
1574 // forward --no-rebind <local> <remote>
1575 else
1576 {
1577 if (argc != 3)
1578 return usage();
1579 const char* command = no_rebind ? "forward:norebind:" : "forward";
1580 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1581 }
1582
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001583 if(adb_command(buf)) {
1584 fprintf(stderr,"error: %s\n", adb_error());
1585 return 1;
1586 }
1587 return 0;
1588 }
1589
1590 /* do_sync_*() commands */
1591
1592 if(!strcmp(argv[0], "ls")) {
1593 if(argc != 2) return usage();
1594 return do_sync_ls(argv[1]);
1595 }
1596
1597 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001598 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001599 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001600 const char* lpath = NULL, *rpath = NULL;
1601
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001602 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001603
1604 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001605 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001606 }
1607
1608 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001609 }
1610
1611 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 }
1624
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001625 if (!strcmp(argv[0], "install")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001626 if (argc < 2) return usage();
1627 return install_app(ttype, serial, argc, argv);
1628 }
1629
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001630 if (!strcmp(argv[0], "install-multiple")) {
1631 if (argc < 2) return usage();
1632 return install_multiple_app(ttype, serial, argc, argv);
1633 }
1634
1635 if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001636 if (argc < 2) return usage();
1637 return uninstall_app(ttype, serial, argc, argv);
1638 }
1639
1640 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001641 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001642 int listonly = 0;
1643
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001644 int ret;
1645 if(argc < 2) {
1646 /* No local path was specified. */
1647 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001648 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1649 listonly = 1;
1650 if (argc == 3) {
1651 srcarg = argv[2];
1652 } else {
1653 srcarg = NULL;
1654 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001655 } else if(argc == 2) {
1656 /* A local path or "android"/"data" arg was specified. */
1657 srcarg = argv[1];
1658 } else {
1659 return usage();
1660 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001661 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001662 if(ret != 0) return usage();
1663
1664 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001665 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001666 if(ret == 0 && vendor_srcpath != NULL)
1667 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001668 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001669 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001670
1671 free(android_srcpath);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001672 free(vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001673 free(data_srcpath);
1674 return ret;
1675 }
1676
1677 /* passthrough commands */
1678
1679 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001680 !strcmp(argv[0],"get-serialno") ||
1681 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001682 {
1683 char *tmp;
1684
1685 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1686 tmp = adb_query(buf);
1687 if(tmp) {
1688 printf("%s\n", tmp);
1689 return 0;
1690 } else {
1691 return 1;
1692 }
1693 }
1694
1695 /* other commands */
1696
1697 if(!strcmp(argv[0],"status-window")) {
1698 status_window(ttype, serial);
1699 return 0;
1700 }
1701
Christopher Tate7b9b5162011-11-30 13:00:33 -08001702 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001703 return logcat(ttype, serial, argc, argv);
1704 }
1705
1706 if(!strcmp(argv[0],"ppp")) {
1707 return ppp(argc, argv);
1708 }
1709
1710 if (!strcmp(argv[0], "start-server")) {
1711 return adb_connect("host:start-server");
1712 }
1713
Christopher Tate73779122011-04-21 12:53:28 -07001714 if (!strcmp(argv[0], "backup")) {
1715 return backup(argc, argv);
1716 }
1717
Christopher Tatecf5379b2011-05-17 15:52:54 -07001718 if (!strcmp(argv[0], "restore")) {
1719 return restore(argc, argv);
1720 }
1721
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001722 if (!strcmp(argv[0], "jdwp")) {
1723 int fd = adb_connect("jdwp");
1724 if (fd >= 0) {
1725 read_and_dump(fd);
1726 adb_close(fd);
1727 return 0;
1728 } else {
1729 fprintf(stderr, "error: %s\n", adb_error());
1730 return -1;
1731 }
1732 }
1733
1734 /* "adb /?" is a common idiom under Windows */
1735 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1736 help();
1737 return 0;
1738 }
1739
1740 if(!strcmp(argv[0], "version")) {
1741 version(stdout);
1742 return 0;
1743 }
1744
1745 usage();
1746 return 1;
1747}
1748
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001749#define MAX_ARGV_LENGTH 16
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001750static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1751{
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001752 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001753 int argc;
1754 va_list ap;
1755
1756 va_start(ap, cmd);
1757 argc = 0;
1758
1759 if (serial) {
1760 argv[argc++] = "-s";
1761 argv[argc++] = serial;
1762 } else if (ttype == kTransportUsb) {
1763 argv[argc++] = "-d";
1764 } else if (ttype == kTransportLocal) {
1765 argv[argc++] = "-e";
1766 }
1767
1768 argv[argc++] = cmd;
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001769 while(argc < MAX_ARGV_LENGTH &&
1770 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1771 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001772 va_end(ap);
1773
1774#if 0
1775 int n;
1776 fprintf(stderr,"argc = %d\n",argc);
1777 for(n = 0; n < argc; n++) {
1778 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1779 }
1780#endif
1781
1782 return adb_commandline(argc, argv);
1783}
1784
1785int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001786 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001787{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001788 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1789 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001790
1791 if(srcarg == NULL) {
1792 android_srcdir = product_file("system");
1793 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001794 vendor_srcdir = product_file("vendor");
1795 /* Check if vendor partition exists */
1796 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1797 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001798 } else {
1799 /* srcarg may be "data", "system" or NULL.
1800 * if srcarg is NULL, then both data and system are synced
1801 */
1802 if(strcmp(srcarg, "system") == 0) {
1803 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001804 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001805 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001806 } else if(strcmp(srcarg, "vendor") == 0) {
1807 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001808 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001809 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001810 */
1811 return 1;
1812 }
1813 }
1814
1815 if(android_srcdir_out != NULL)
1816 *android_srcdir_out = android_srcdir;
1817 else
1818 free(android_srcdir);
1819
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001820 if(vendor_srcdir_out != NULL)
1821 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001822 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001823 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001824
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001825 if(data_srcdir_out != NULL)
1826 *data_srcdir_out = data_srcdir;
1827 else
1828 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001829 return 0;
1830}
1831
1832static int pm_command(transport_type transport, char* serial,
1833 int argc, char** argv)
1834{
1835 char buf[4096];
1836
1837 snprintf(buf, sizeof(buf), "shell:pm");
1838
1839 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001840 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001841 strncat(buf, " ", sizeof(buf) - 1);
1842 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001843 free(quoted);
1844 }
1845
1846 send_shellcommand(transport, serial, buf);
1847 return 0;
1848}
1849
1850int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1851{
1852 /* if the user choose the -k option, we refuse to do it until devices are
1853 out with the option to uninstall the remaining data somehow (adb/ui) */
1854 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1855 {
1856 printf(
1857 "The -k option uninstalls the application while retaining the data/cache.\n"
1858 "At the moment, there is no way to remove the remaining data.\n"
1859 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1860 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1861 return -1;
1862 }
1863
1864 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1865 return pm_command(transport, serial, argc, argv);
1866}
1867
1868static int delete_file(transport_type transport, char* serial, char* filename)
1869{
1870 char buf[4096];
1871 char* quoted;
1872
Jeff Sharkeyce474652014-09-09 12:38:30 -07001873 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001874 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001875 strncat(buf, quoted, sizeof(buf)-1);
1876 free(quoted);
1877
1878 send_shellcommand(transport, serial, buf);
1879 return 0;
1880}
1881
Kenny Root3802c992011-08-05 11:19:45 -07001882static const char* get_basename(const char* filename)
1883{
1884 const char* basename = adb_dirstop(filename);
1885 if (basename) {
1886 basename++;
1887 return basename;
1888 } else {
1889 return filename;
1890 }
1891}
1892
Kenny Root3802c992011-08-05 11:19:45 -07001893int install_app(transport_type transport, char* serial, int argc, char** argv)
1894{
1895 static const char *const DATA_DEST = "/data/local/tmp/%s";
1896 static const char *const SD_DEST = "/sdcard/tmp/%s";
1897 const char* where = DATA_DEST;
Kenny Root3802c992011-08-05 11:19:45 -07001898 int i;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001899 struct stat sb;
Kenny Root3802c992011-08-05 11:19:45 -07001900
1901 for (i = 1; i < argc; i++) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001902 if (!strcmp(argv[i], "-s")) {
Kenny Root3802c992011-08-05 11:19:45 -07001903 where = SD_DEST;
1904 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001905 }
1906
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001907 // Find last APK argument.
1908 // All other arguments passed through verbatim.
1909 int last_apk = -1;
1910 for (i = argc - 1; i >= 0; i--) {
1911 char* file = argv[i];
1912 char* dot = strrchr(file, '.');
1913 if (dot && !strcasecmp(dot, ".apk")) {
1914 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1915 fprintf(stderr, "Invalid APK file: %s\n", file);
1916 return -1;
1917 }
1918
1919 last_apk = i;
1920 break;
1921 }
Kenny Root3802c992011-08-05 11:19:45 -07001922 }
1923
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001924 if (last_apk == -1) {
1925 fprintf(stderr, "Missing APK file\n");
1926 return -1;
Kenny Root3802c992011-08-05 11:19:45 -07001927 }
1928
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001929 char* apk_file = argv[last_apk];
1930 char apk_dest[PATH_MAX];
Kenny Root3802c992011-08-05 11:19:45 -07001931 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001932 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001933 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001934 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001935 } else {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001936 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root3802c992011-08-05 11:19:45 -07001937 }
1938
1939 pm_command(transport, serial, argc, argv);
1940
Kenny Root58d5f222012-03-26 16:14:02 -07001941cleanup_apk:
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001942 delete_file(transport, serial, apk_dest);
1943 return err;
1944}
1945
1946int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1947{
1948 char buf[1024];
1949 int i;
1950 struct stat sb;
1951 unsigned long long total_size = 0;
1952
1953 // Find all APK arguments starting at end.
1954 // All other arguments passed through verbatim.
1955 int first_apk = -1;
1956 for (i = argc - 1; i >= 0; i--) {
1957 char* file = argv[i];
1958 char* dot = strrchr(file, '.');
1959 if (dot && !strcasecmp(dot, ".apk")) {
1960 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1961 fprintf(stderr, "Invalid APK file: %s\n", file);
1962 return -1;
1963 }
1964
1965 total_size += sb.st_size;
1966 first_apk = i;
1967 } else {
1968 break;
1969 }
Kenny Root3802c992011-08-05 11:19:45 -07001970 }
1971
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001972 if (first_apk == -1) {
1973 fprintf(stderr, "Missing APK file\n");
1974 return 1;
1975 }
Kenny Root3802c992011-08-05 11:19:45 -07001976
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001977 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1978 for (i = 1; i < first_apk; i++) {
1979 char *quoted = escape_arg(argv[i]);
1980 strncat(buf, " ", sizeof(buf) - 1);
1981 strncat(buf, quoted, sizeof(buf) - 1);
1982 free(quoted);
1983 }
1984
1985 // Create install session
1986 int fd = adb_connect(buf);
1987 if (fd < 0) {
1988 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1989 return -1;
1990 }
1991 read_status_line(fd, buf, sizeof(buf));
1992 adb_close(fd);
1993
1994 int session_id = -1;
1995 if (!strncmp("Success", buf, 7)) {
1996 char* start = strrchr(buf, '[');
1997 char* end = strrchr(buf, ']');
1998 if (start && end) {
1999 *end = '\0';
2000 session_id = strtol(start + 1, NULL, 10);
2001 }
2002 }
2003 if (session_id < 0) {
2004 fprintf(stderr, "Failed to create session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002005 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002006 return -1;
2007 }
2008
2009 // Valid session, now stream the APKs
2010 int success = 1;
2011 for (i = first_apk; i < argc; i++) {
2012 char* file = argv[i];
2013 if (stat(file, &sb) == -1) {
2014 fprintf(stderr, "Failed to stat %s\n", file);
2015 success = 0;
2016 goto finalize_session;
2017 }
2018
2019 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkey4a7ddb62014-07-14 13:57:54 -07002020 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002021
2022 int localFd = adb_open(file, O_RDONLY);
2023 if (localFd < 0) {
2024 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2025 success = 0;
2026 goto finalize_session;
2027 }
2028
2029 int remoteFd = adb_connect(buf);
2030 if (remoteFd < 0) {
2031 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2032 adb_close(localFd);
2033 success = 0;
2034 goto finalize_session;
2035 }
2036
2037 copy_to_file(localFd, remoteFd);
2038 read_status_line(remoteFd, buf, sizeof(buf));
2039
2040 adb_close(localFd);
2041 adb_close(remoteFd);
2042
2043 if (strncmp("Success", buf, 7)) {
2044 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate29721da2014-07-14 16:45:13 -07002045 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002046 success = 0;
2047 goto finalize_session;
2048 }
2049 }
2050
2051finalize_session:
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002052 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002053 if (success) {
2054 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2055 } else {
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002056 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002057 }
2058
2059 fd = adb_connect(buf);
2060 if (fd < 0) {
2061 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2062 return -1;
2063 }
2064 read_status_line(fd, buf, sizeof(buf));
2065 adb_close(fd);
2066
2067 if (!strncmp("Success", buf, 7)) {
Christopher Tate29721da2014-07-14 16:45:13 -07002068 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002069 return 0;
2070 } else {
2071 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002072 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002073 return -1;
2074 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08002075}