blob: af21e3859584b6e23a1182501871f96f49b13022 [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
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700678static bool should_escape(const char c)
679{
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
1749static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1750{
1751 char *argv[16];
1752 int argc;
1753 va_list ap;
1754
1755 va_start(ap, cmd);
1756 argc = 0;
1757
1758 if (serial) {
1759 argv[argc++] = "-s";
1760 argv[argc++] = serial;
1761 } else if (ttype == kTransportUsb) {
1762 argv[argc++] = "-d";
1763 } else if (ttype == kTransportLocal) {
1764 argv[argc++] = "-e";
1765 }
1766
1767 argv[argc++] = cmd;
1768 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1769 va_end(ap);
1770
1771#if 0
1772 int n;
1773 fprintf(stderr,"argc = %d\n",argc);
1774 for(n = 0; n < argc; n++) {
1775 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1776 }
1777#endif
1778
1779 return adb_commandline(argc, argv);
1780}
1781
1782int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001783 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001784{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001785 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1786 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001787
1788 if(srcarg == NULL) {
1789 android_srcdir = product_file("system");
1790 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001791 vendor_srcdir = product_file("vendor");
1792 /* Check if vendor partition exists */
1793 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1794 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001795 } else {
1796 /* srcarg may be "data", "system" or NULL.
1797 * if srcarg is NULL, then both data and system are synced
1798 */
1799 if(strcmp(srcarg, "system") == 0) {
1800 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001801 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001802 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001803 } else if(strcmp(srcarg, "vendor") == 0) {
1804 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001805 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001806 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001807 */
1808 return 1;
1809 }
1810 }
1811
1812 if(android_srcdir_out != NULL)
1813 *android_srcdir_out = android_srcdir;
1814 else
1815 free(android_srcdir);
1816
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001817 if(vendor_srcdir_out != NULL)
1818 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001819 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001820 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001821
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001822 if(data_srcdir_out != NULL)
1823 *data_srcdir_out = data_srcdir;
1824 else
1825 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001826 return 0;
1827}
1828
1829static int pm_command(transport_type transport, char* serial,
1830 int argc, char** argv)
1831{
1832 char buf[4096];
1833
1834 snprintf(buf, sizeof(buf), "shell:pm");
1835
1836 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001837 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001838 strncat(buf, " ", sizeof(buf) - 1);
1839 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001840 free(quoted);
1841 }
1842
1843 send_shellcommand(transport, serial, buf);
1844 return 0;
1845}
1846
1847int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1848{
1849 /* if the user choose the -k option, we refuse to do it until devices are
1850 out with the option to uninstall the remaining data somehow (adb/ui) */
1851 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1852 {
1853 printf(
1854 "The -k option uninstalls the application while retaining the data/cache.\n"
1855 "At the moment, there is no way to remove the remaining data.\n"
1856 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1857 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1858 return -1;
1859 }
1860
1861 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1862 return pm_command(transport, serial, argc, argv);
1863}
1864
1865static int delete_file(transport_type transport, char* serial, char* filename)
1866{
1867 char buf[4096];
1868 char* quoted;
1869
1870 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001871 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001872 strncat(buf, quoted, sizeof(buf)-1);
1873 free(quoted);
1874
1875 send_shellcommand(transport, serial, buf);
1876 return 0;
1877}
1878
Kenny Root3802c992011-08-05 11:19:45 -07001879static const char* get_basename(const char* filename)
1880{
1881 const char* basename = adb_dirstop(filename);
1882 if (basename) {
1883 basename++;
1884 return basename;
1885 } else {
1886 return filename;
1887 }
1888}
1889
Kenny Root3802c992011-08-05 11:19:45 -07001890int install_app(transport_type transport, char* serial, int argc, char** argv)
1891{
1892 static const char *const DATA_DEST = "/data/local/tmp/%s";
1893 static const char *const SD_DEST = "/sdcard/tmp/%s";
1894 const char* where = DATA_DEST;
Kenny Root3802c992011-08-05 11:19:45 -07001895 int i;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001896 struct stat sb;
Kenny Root3802c992011-08-05 11:19:45 -07001897
1898 for (i = 1; i < argc; i++) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001899 if (!strcmp(argv[i], "-s")) {
Kenny Root3802c992011-08-05 11:19:45 -07001900 where = SD_DEST;
1901 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001902 }
1903
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001904 // Find last APK argument.
1905 // All other arguments passed through verbatim.
1906 int last_apk = -1;
1907 for (i = argc - 1; i >= 0; i--) {
1908 char* file = argv[i];
1909 char* dot = strrchr(file, '.');
1910 if (dot && !strcasecmp(dot, ".apk")) {
1911 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1912 fprintf(stderr, "Invalid APK file: %s\n", file);
1913 return -1;
1914 }
1915
1916 last_apk = i;
1917 break;
1918 }
Kenny Root3802c992011-08-05 11:19:45 -07001919 }
1920
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001921 if (last_apk == -1) {
1922 fprintf(stderr, "Missing APK file\n");
1923 return -1;
Kenny Root3802c992011-08-05 11:19:45 -07001924 }
1925
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001926 char* apk_file = argv[last_apk];
1927 char apk_dest[PATH_MAX];
Kenny Root3802c992011-08-05 11:19:45 -07001928 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001929 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001930 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001931 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001932 } else {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001933 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root3802c992011-08-05 11:19:45 -07001934 }
1935
1936 pm_command(transport, serial, argc, argv);
1937
Kenny Root58d5f222012-03-26 16:14:02 -07001938cleanup_apk:
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001939 delete_file(transport, serial, apk_dest);
1940 return err;
1941}
1942
1943int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1944{
1945 char buf[1024];
1946 int i;
1947 struct stat sb;
1948 unsigned long long total_size = 0;
1949
1950 // Find all APK arguments starting at end.
1951 // All other arguments passed through verbatim.
1952 int first_apk = -1;
1953 for (i = argc - 1; i >= 0; i--) {
1954 char* file = argv[i];
1955 char* dot = strrchr(file, '.');
1956 if (dot && !strcasecmp(dot, ".apk")) {
1957 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1958 fprintf(stderr, "Invalid APK file: %s\n", file);
1959 return -1;
1960 }
1961
1962 total_size += sb.st_size;
1963 first_apk = i;
1964 } else {
1965 break;
1966 }
Kenny Root3802c992011-08-05 11:19:45 -07001967 }
1968
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001969 if (first_apk == -1) {
1970 fprintf(stderr, "Missing APK file\n");
1971 return 1;
1972 }
Kenny Root3802c992011-08-05 11:19:45 -07001973
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001974 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1975 for (i = 1; i < first_apk; i++) {
1976 char *quoted = escape_arg(argv[i]);
1977 strncat(buf, " ", sizeof(buf) - 1);
1978 strncat(buf, quoted, sizeof(buf) - 1);
1979 free(quoted);
1980 }
1981
1982 // Create install session
1983 int fd = adb_connect(buf);
1984 if (fd < 0) {
1985 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1986 return -1;
1987 }
1988 read_status_line(fd, buf, sizeof(buf));
1989 adb_close(fd);
1990
1991 int session_id = -1;
1992 if (!strncmp("Success", buf, 7)) {
1993 char* start = strrchr(buf, '[');
1994 char* end = strrchr(buf, ']');
1995 if (start && end) {
1996 *end = '\0';
1997 session_id = strtol(start + 1, NULL, 10);
1998 }
1999 }
2000 if (session_id < 0) {
2001 fprintf(stderr, "Failed to create session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002002 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002003 return -1;
2004 }
2005
2006 // Valid session, now stream the APKs
2007 int success = 1;
2008 for (i = first_apk; i < argc; i++) {
2009 char* file = argv[i];
2010 if (stat(file, &sb) == -1) {
2011 fprintf(stderr, "Failed to stat %s\n", file);
2012 success = 0;
2013 goto finalize_session;
2014 }
2015
2016 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkey4a7ddb62014-07-14 13:57:54 -07002017 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002018
2019 int localFd = adb_open(file, O_RDONLY);
2020 if (localFd < 0) {
2021 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2022 success = 0;
2023 goto finalize_session;
2024 }
2025
2026 int remoteFd = adb_connect(buf);
2027 if (remoteFd < 0) {
2028 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2029 adb_close(localFd);
2030 success = 0;
2031 goto finalize_session;
2032 }
2033
2034 copy_to_file(localFd, remoteFd);
2035 read_status_line(remoteFd, buf, sizeof(buf));
2036
2037 adb_close(localFd);
2038 adb_close(remoteFd);
2039
2040 if (strncmp("Success", buf, 7)) {
2041 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate29721da2014-07-14 16:45:13 -07002042 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002043 success = 0;
2044 goto finalize_session;
2045 }
2046 }
2047
2048finalize_session:
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002049 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002050 if (success) {
2051 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2052 } else {
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002053 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002054 }
2055
2056 fd = adb_connect(buf);
2057 if (fd < 0) {
2058 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2059 return -1;
2060 }
2061 read_status_line(fd, buf, sizeof(buf));
2062 adb_close(fd);
2063
2064 if (!strncmp("Success", buf, 7)) {
Christopher Tate29721da2014-07-14 16:45:13 -07002065 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002066 return 0;
2067 } else {
2068 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002069 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002070 return -1;
2071 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08002072}