blob: cf02545b193e73f703eda8dc99bbff556c8adb98 [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 Sharkey824d1062014-06-10 11:31:24 -0700678/** Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700679static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800680{
681 const char *ts;
682 size_t alloc_len;
683 char *ret;
684 char *dest;
685
Jeff Sharkey026d9622014-06-10 16:22:17 -0700686 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700687 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800688 alloc_len++;
Jeff Sharkey026d9622014-06-10 16:22:17 -0700689 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800690 alloc_len++;
691 }
692 }
693
Jeff Sharkey026d9622014-06-10 16:22:17 -0700694 if (alloc_len == 0) {
695 // Preserve empty arguments
696 ret = (char *) malloc(3);
697 ret[0] = '\"';
698 ret[1] = '\"';
699 ret[2] = '\0';
700 return ret;
701 }
702
Jeff Sharkey824d1062014-06-10 11:31:24 -0700703 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800704 dest = ret;
705
Jeff Sharkey824d1062014-06-10 11:31:24 -0700706 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700707 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800708 *dest++ = '\\';
709 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800710 *dest++ = *ts;
711 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800712 *dest++ = '\0';
713
714 return ret;
715}
716
717/**
718 * Run ppp in "notty" mode against a resource listed as the first parameter
719 * eg:
720 *
721 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
722 *
723 */
724int ppp(int argc, char **argv)
725{
726#ifdef HAVE_WIN32_PROC
727 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
728 return -1;
729#else
730 char *adb_service_name;
731 pid_t pid;
732 int fd;
733
734 if (argc < 2) {
735 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
736 argv[0]);
737
738 return 1;
739 }
740
741 adb_service_name = argv[1];
742
743 fd = adb_connect(adb_service_name);
744
745 if(fd < 0) {
746 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
747 adb_service_name, adb_error());
748 return 1;
749 }
750
751 pid = fork();
752
753 if (pid < 0) {
754 perror("from fork()");
755 return 1;
756 } else if (pid == 0) {
757 int err;
758 int i;
759 const char **ppp_args;
760
761 // copy args
762 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
763 ppp_args[0] = "pppd";
764 for (i = 2 ; i < argc ; i++) {
765 //argv[2] and beyond become ppp_args[1] and beyond
766 ppp_args[i - 1] = argv[i];
767 }
768 ppp_args[i-1] = NULL;
769
770 // child side
771
772 dup2(fd, STDIN_FILENO);
773 dup2(fd, STDOUT_FILENO);
774 adb_close(STDERR_FILENO);
775 adb_close(fd);
776
777 err = execvp("pppd", (char * const *)ppp_args);
778
779 if (err < 0) {
780 perror("execing pppd");
781 }
782 exit(-1);
783 } else {
784 // parent side
785
786 adb_close(fd);
787 return 0;
788 }
789#endif /* !HAVE_WIN32_PROC */
790}
791
792static int send_shellcommand(transport_type transport, char* serial, char* buf)
793{
794 int fd, ret;
795
796 for(;;) {
797 fd = adb_connect(buf);
798 if(fd >= 0)
799 break;
800 fprintf(stderr,"- waiting for device -\n");
801 adb_sleep_ms(1000);
802 do_cmd(transport, serial, "wait-for-device", 0);
803 }
804
805 read_and_dump(fd);
806 ret = adb_close(fd);
807 if (ret)
808 perror("close");
809
810 return ret;
811}
812
813static int logcat(transport_type transport, char* serial, int argc, char **argv)
814{
815 char buf[4096];
816
817 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700818 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800819
820 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700821 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800822 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700823 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700824 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800825
Jeff Sharkey824d1062014-06-10 11:31:24 -0700826 if (!strcmp(argv[0], "longcat")) {
827 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800828 }
829
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800830 argc -= 1;
831 argv += 1;
832 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700833 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700834 strncat(buf, " ", sizeof(buf) - 1);
835 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800836 free(quoted);
837 }
838
839 send_shellcommand(transport, serial, buf);
840 return 0;
841}
842
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700843static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800844{
845 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700846 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800847
848 for(;;) {
849 x = adb_dirstart(x);
850 if(x == 0) return 0;
851 *x = 0;
852 ret = adb_mkdir(path, 0775);
853 *x = OS_PATH_SEPARATOR;
854 if((ret < 0) && (errno != EEXIST)) {
855 return ret;
856 }
857 x++;
858 }
859 return 0;
860}
861
Christopher Tate73779122011-04-21 12:53:28 -0700862static int backup(int argc, char** argv) {
863 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800864 char default_name[32];
865 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700866 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700867 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700868
Christopher Tatefba22972011-06-01 17:56:23 -0700869 /* find, extract, and use any -f argument */
870 for (i = 1; i < argc; i++) {
871 if (!strcmp("-f", argv[i])) {
872 if (i == argc-1) {
873 fprintf(stderr, "adb: -f passed with no filename\n");
874 return usage();
875 }
876 filename = argv[i+1];
877 for (j = i+2; j <= argc; ) {
878 argv[i++] = argv[j++];
879 }
880 argc -= 2;
881 argv[argc] = NULL;
882 }
Christopher Tate73779122011-04-21 12:53:28 -0700883 }
884
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700885 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
886 if (argc < 2) return usage();
887
Christopher Tate1e9f2392011-12-08 19:04:34 -0800888 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700889 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800890 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700891 if (outFd < 0) {
892 fprintf(stderr, "adb: unable to open file %s\n", filename);
893 return -1;
894 }
895
896 snprintf(buf, sizeof(buf), "backup");
897 for (argc--, argv++; argc; argc--, argv++) {
898 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
899 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
900 }
901
902 D("backup. filename=%s buf=%s\n", filename, buf);
903 fd = adb_connect(buf);
904 if (fd < 0) {
905 fprintf(stderr, "adb: unable to connect for backup\n");
906 adb_close(outFd);
907 return -1;
908 }
909
Christopher Tate9c829102012-01-06 15:43:03 -0800910 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700911 copy_to_file(fd, outFd);
912
913 adb_close(fd);
914 adb_close(outFd);
915 return 0;
916}
917
Christopher Tatecf5379b2011-05-17 15:52:54 -0700918static int restore(int argc, char** argv) {
919 const char* filename;
920 int fd, tarFd;
921
922 if (argc != 2) return usage();
923
924 filename = argv[1];
925 tarFd = adb_open(filename, O_RDONLY);
926 if (tarFd < 0) {
927 fprintf(stderr, "adb: unable to open file %s\n", filename);
928 return -1;
929 }
930
931 fd = adb_connect("restore:");
932 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700933 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700934 adb_close(tarFd);
935 return -1;
936 }
937
Christopher Tate9c829102012-01-06 15:43:03 -0800938 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700939 copy_to_file(tarFd, fd);
940
941 adb_close(fd);
942 adb_close(tarFd);
943 return 0;
944}
945
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800946#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
947static int top_works(const char *top)
948{
949 if (top != NULL && adb_is_absolute_host_path(top)) {
950 char path_buf[PATH_MAX];
951 snprintf(path_buf, sizeof(path_buf),
952 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
953 return access(path_buf, F_OK) == 0;
954 }
955 return 0;
956}
957
958static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
959{
960 strcpy(path_buf, indir);
961 while (1) {
962 if (top_works(path_buf)) {
963 return path_buf;
964 }
965 char *s = adb_dirstop(path_buf);
966 if (s != NULL) {
967 *s = '\0';
968 } else {
969 path_buf[0] = '\0';
970 return NULL;
971 }
972 }
973}
974
975static char *find_top(char path_buf[PATH_MAX])
976{
977 char *top = getenv("ANDROID_BUILD_TOP");
978 if (top != NULL && top[0] != '\0') {
979 if (!top_works(top)) {
980 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
981 return NULL;
982 }
983 } else {
984 top = getenv("TOP");
985 if (top != NULL && top[0] != '\0') {
986 if (!top_works(top)) {
987 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
988 return NULL;
989 }
990 } else {
991 top = NULL;
992 }
993 }
994
995 if (top != NULL) {
996 /* The environment pointed to a top directory that works.
997 */
998 strcpy(path_buf, top);
999 return path_buf;
1000 }
1001
1002 /* The environment didn't help. Walk up the tree from the CWD
1003 * to see if we can find the top.
1004 */
1005 char dir[PATH_MAX];
1006 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1007 if (top == NULL) {
1008 /* If the CWD isn't under a good-looking top, see if the
1009 * executable is.
1010 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +11001011 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001012 top = find_top_from(dir, path_buf);
1013 }
1014 return top;
1015}
1016
1017/* <hint> may be:
1018 * - A simple product name
1019 * e.g., "sooner"
1020TODO: debug? sooner-debug, sooner:debug?
1021 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1022 * e.g., "out/target/product/sooner"
1023 * - An absolute path to the PRODUCT_OUT dir
1024 * e.g., "/src/device/out/target/product/sooner"
1025 *
1026 * Given <hint>, try to construct an absolute path to the
1027 * ANDROID_PRODUCT_OUT dir.
1028 */
1029static const char *find_product_out_path(const char *hint)
1030{
1031 static char path_buf[PATH_MAX];
1032
1033 if (hint == NULL || hint[0] == '\0') {
1034 return NULL;
1035 }
1036
1037 /* If it's already absolute, don't bother doing any work.
1038 */
1039 if (adb_is_absolute_host_path(hint)) {
1040 strcpy(path_buf, hint);
1041 return path_buf;
1042 }
1043
1044 /* If there are any slashes in it, assume it's a relative path;
1045 * make it absolute.
1046 */
1047 if (adb_dirstart(hint) != NULL) {
1048 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1049 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1050 return NULL;
1051 }
1052 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1053 fprintf(stderr, "adb: Couldn't assemble path\n");
1054 return NULL;
1055 }
1056 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1057 strcat(path_buf, hint);
1058 return path_buf;
1059 }
1060
1061 /* It's a string without any slashes. Try to do something with it.
1062 *
1063 * Try to find the root of the build tree, and build a PRODUCT_OUT
1064 * path from there.
1065 */
1066 char top_buf[PATH_MAX];
1067 const char *top = find_top(top_buf);
1068 if (top == NULL) {
1069 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1070 return NULL;
1071 }
1072//TODO: if we have a way to indicate debug, look in out/debug/target/...
1073 snprintf(path_buf, sizeof(path_buf),
1074 "%s" OS_PATH_SEPARATOR_STR
1075 "out" OS_PATH_SEPARATOR_STR
1076 "target" OS_PATH_SEPARATOR_STR
1077 "product" OS_PATH_SEPARATOR_STR
1078 "%s", top_buf, hint);
1079 if (access(path_buf, F_OK) < 0) {
1080 fprintf(stderr, "adb: Couldn't find a product dir "
1081 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1082 return NULL;
1083 }
1084 return path_buf;
1085}
1086
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001087static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1088 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001089 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001090 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001091
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001092 while (narg > 0) {
1093 if (!strcmp(*arg, "-p")) {
1094 *show_progress = 1;
1095 } else if (!strcmp(*arg, "-a")) {
1096 *copy_attrs = 1;
1097 } else {
1098 break;
1099 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001100 ++arg;
1101 --narg;
1102 }
1103
1104 if (narg > 0) {
1105 *path1 = *arg;
1106 ++arg;
1107 --narg;
1108 }
1109
1110 if (narg > 0) {
1111 *path2 = *arg;
1112 }
1113}
1114
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001115int adb_commandline(int argc, char **argv)
1116{
1117 char buf[4096];
1118 int no_daemon = 0;
1119 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001120 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001121 int persist = 0;
1122 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001123 transport_type ttype = kTransportAny;
1124 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001125 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001126
1127 /* If defined, this should be an absolute path to
1128 * the directory containing all of the various system images
1129 * for a particular product. If not defined, and the adb
1130 * command requires this information, then the user must
1131 * specify the path using "-p".
1132 */
1133 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1134 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1135 gProductOutPath = NULL;
1136 }
1137 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1138
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001139 serial = getenv("ANDROID_SERIAL");
1140
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001141 /* Validate and assign the server port */
1142 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1143 int server_port = DEFAULT_ADB_PORT;
1144 if (server_port_str && strlen(server_port_str) > 0) {
1145 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001146 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001147 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001148 "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 +01001149 server_port_str);
1150 return usage();
1151 }
1152 }
1153
1154 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001155 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001156 if(!strcmp(argv[0],"server")) {
1157 is_server = 1;
1158 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001159 no_daemon = 1;
1160 } else if (!strcmp(argv[0], "fork-server")) {
1161 /* this is a special flag used only when the ADB client launches the ADB Server */
1162 is_daemon = 1;
1163 } else if(!strcmp(argv[0],"persist")) {
1164 persist = 1;
1165 } else if(!strncmp(argv[0], "-p", 2)) {
1166 const char *product = NULL;
1167 if (argv[0][2] == '\0') {
1168 if (argc < 2) return usage();
1169 product = argv[1];
1170 argc--;
1171 argv++;
1172 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001173 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001174 }
1175 gProductOutPath = find_product_out_path(product);
1176 if (gProductOutPath == NULL) {
1177 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1178 product);
1179 return usage();
1180 }
1181 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1182 if (isdigit(argv[0][2])) {
1183 serial = argv[0] + 2;
1184 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001185 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001186 serial = argv[1];
1187 argc--;
1188 argv++;
1189 }
1190 } else if (!strcmp(argv[0],"-d")) {
1191 ttype = kTransportUsb;
1192 } else if (!strcmp(argv[0],"-e")) {
1193 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001194 } else if (!strcmp(argv[0],"-a")) {
1195 gListenAll = 1;
1196 } else if(!strncmp(argv[0], "-H", 2)) {
1197 const char *hostname = NULL;
1198 if (argv[0][2] == '\0') {
1199 if (argc < 2) return usage();
1200 hostname = argv[1];
1201 argc--;
1202 argv++;
1203 } else {
1204 hostname = argv[0] + 2;
1205 }
1206 adb_set_tcp_name(hostname);
1207
1208 } else if(!strncmp(argv[0], "-P", 2)) {
1209 if (argv[0][2] == '\0') {
1210 if (argc < 2) return usage();
1211 server_port_str = argv[1];
1212 argc--;
1213 argv++;
1214 } else {
1215 server_port_str = argv[0] + 2;
1216 }
1217 if (strlen(server_port_str) > 0) {
1218 server_port = (int) strtol(server_port_str, NULL, 0);
1219 if (server_port <= 0 || server_port > 65535) {
1220 fprintf(stderr,
1221 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1222 server_port_str);
1223 return usage();
1224 }
1225 } else {
1226 fprintf(stderr,
1227 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1228 return usage();
1229 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001230 } else {
1231 /* out of recognized modifiers and flags */
1232 break;
1233 }
1234 argc--;
1235 argv++;
1236 }
1237
1238 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001239 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001240
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001241 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001242 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001243 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001244 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001245 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001246 }
1247 if(r) {
1248 fprintf(stderr,"* could not start server *\n");
1249 }
1250 return r;
1251 }
1252
1253top:
1254 if(argc == 0) {
1255 return usage();
1256 }
1257
1258 /* adb_connect() commands */
1259
1260 if(!strcmp(argv[0], "devices")) {
1261 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001262 char *listopt;
1263 if (argc < 2)
1264 listopt = "";
1265 else if (argc == 2 && !strcmp(argv[1], "-l"))
1266 listopt = argv[1];
1267 else {
1268 fprintf(stderr, "Usage: adb devices [-l]\n");
1269 return 1;
1270 }
1271 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001272 tmp = adb_query(buf);
1273 if(tmp) {
1274 printf("List of devices attached \n");
1275 printf("%s\n", tmp);
1276 return 0;
1277 } else {
1278 return 1;
1279 }
1280 }
1281
Mike Lockwood01c2c302010-05-24 10:44:35 -04001282 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001283 char *tmp;
1284 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001285 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001286 return 1;
1287 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001288 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1289 tmp = adb_query(buf);
1290 if(tmp) {
1291 printf("%s\n", tmp);
1292 return 0;
1293 } else {
1294 return 1;
1295 }
1296 }
1297
1298 if(!strcmp(argv[0], "disconnect")) {
1299 char *tmp;
1300 if (argc > 2) {
1301 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1302 return 1;
1303 }
1304 if (argc == 2) {
1305 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1306 } else {
1307 snprintf(buf, sizeof buf, "host:disconnect:");
1308 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001309 tmp = adb_query(buf);
1310 if(tmp) {
1311 printf("%s\n", tmp);
1312 return 0;
1313 } else {
1314 return 1;
1315 }
1316 }
1317
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001318 if (!strcmp(argv[0], "emu")) {
1319 return adb_send_emulator_command(argc, argv);
1320 }
1321
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001322 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001323 int r;
1324 int fd;
1325
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001326 char h = (argv[0][0] == 'h');
1327
1328 if (h) {
1329 printf("\x1b[41;33m");
1330 fflush(stdout);
1331 }
1332
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001333 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001334 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001335 r = interactive_shell();
1336 if (h) {
1337 printf("\x1b[0m");
1338 fflush(stdout);
1339 }
1340 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001341 }
1342
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001343 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001344 argc -= 2;
1345 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001346 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001347 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001348 strncat(buf, " ", sizeof(buf) - 1);
1349 strncat(buf, quoted, sizeof(buf) - 1);
1350 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001351 }
1352
1353 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001354 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001355 fd = adb_connect(buf);
1356 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001357 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001358 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001359 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001360 adb_close(fd);
1361 r = 0;
1362 } else {
1363 fprintf(stderr,"error: %s\n", adb_error());
1364 r = -1;
1365 }
1366
1367 if(persist) {
1368 fprintf(stderr,"\n- waiting for device -\n");
1369 adb_sleep_ms(1000);
1370 do_cmd(ttype, serial, "wait-for-device", 0);
1371 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001372 if (h) {
1373 printf("\x1b[0m");
1374 fflush(stdout);
1375 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001376 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001377 return r;
1378 }
1379 }
1380 }
1381
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001382 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1383 int exec_in = !strcmp(argv[0], "exec-in");
1384 int fd;
1385
1386 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1387 argc -= 2;
1388 argv += 2;
1389 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001390 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001391 strncat(buf, " ", sizeof(buf) - 1);
1392 strncat(buf, quoted, sizeof(buf) - 1);
1393 free(quoted);
1394 }
1395
1396 fd = adb_connect(buf);
1397 if (fd < 0) {
1398 fprintf(stderr, "error: %s\n", adb_error());
1399 return -1;
1400 }
1401
1402 if (exec_in) {
1403 copy_to_file(STDIN_FILENO, fd);
1404 } else {
1405 copy_to_file(fd, STDOUT_FILENO);
1406 }
1407
1408 adb_close(fd);
1409 return 0;
1410 }
1411
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001412 if(!strcmp(argv[0], "kill-server")) {
1413 int fd;
1414 fd = _adb_connect("host:kill");
1415 if(fd == -1) {
1416 fprintf(stderr,"* server not running *\n");
1417 return 1;
1418 }
1419 return 0;
1420 }
1421
Doug Zongker6b217ed2012-01-09 14:54:53 -08001422 if(!strcmp(argv[0], "sideload")) {
1423 if(argc != 2) return usage();
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001424 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001425 return 1;
1426 } else {
1427 return 0;
1428 }
1429 }
1430
Mike Lockwood26b88e32009-08-24 15:58:40 -07001431 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001432 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001433 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001434 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001435 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001436 if (!strcmp(argv[0], "reboot-bootloader"))
1437 snprintf(command, sizeof(command), "reboot:bootloader");
1438 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001439 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001440 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001441 snprintf(command, sizeof(command), "%s:", argv[0]);
1442 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001443 if(fd >= 0) {
1444 read_and_dump(fd);
1445 adb_close(fd);
1446 return 0;
1447 }
1448 fprintf(stderr,"error: %s\n", adb_error());
1449 return 1;
1450 }
1451
Mike Lockwood78589f32009-09-03 14:54:58 -04001452 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001453 if (argc != 1) return usage();
1454 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001455 return 0;
1456 }
1457
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001458 /* adb_command() wrapper commands */
1459
1460 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1461 char* service = argv[0];
1462 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1463 if (ttype == kTransportUsb) {
1464 service = "wait-for-usb";
1465 } else if (ttype == kTransportLocal) {
1466 service = "wait-for-local";
1467 } else {
1468 service = "wait-for-any";
1469 }
1470 }
1471
1472 format_host_command(buf, sizeof buf, service, ttype, serial);
1473
1474 if (adb_command(buf)) {
1475 D("failure: %s *\n",adb_error());
1476 fprintf(stderr,"error: %s\n", adb_error());
1477 return 1;
1478 }
1479
1480 /* Allow a command to be run after wait-for-device,
1481 * e.g. 'adb wait-for-device shell'.
1482 */
1483 if(argc > 1) {
1484 argc--;
1485 argv++;
1486 goto top;
1487 }
1488 return 0;
1489 }
1490
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001491 if(!strcmp(argv[0], "forward") ||
1492 !strcmp(argv[0], "reverse"))
1493 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001494 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001495 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001496 char remove = 0;
1497 char remove_all = 0;
1498 char list = 0;
1499 char no_rebind = 0;
1500
1501 // Parse options here.
1502 while (argc > 1 && argv[1][0] == '-') {
1503 if (!strcmp(argv[1], "--list"))
1504 list = 1;
1505 else if (!strcmp(argv[1], "--remove"))
1506 remove = 1;
1507 else if (!strcmp(argv[1], "--remove-all"))
1508 remove_all = 1;
1509 else if (!strcmp(argv[1], "--no-rebind"))
1510 no_rebind = 1;
1511 else {
1512 return usage();
1513 }
1514 argc--;
1515 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001516 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001517
1518 // Ensure we can only use one option at a time.
1519 if (list + remove + remove_all + no_rebind > 1) {
1520 return usage();
1521 }
1522
1523 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001524 if (reverse) {
1525 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001526 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001527 if (serial) {
1528 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1529 serial);
1530 } else if (ttype == kTransportUsb) {
1531 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1532 } else if (ttype == kTransportLocal) {
1533 snprintf(host_prefix, sizeof host_prefix, "host-local");
1534 } else {
1535 snprintf(host_prefix, sizeof host_prefix, "host");
1536 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001537 }
1538
1539 // Implement forward --list
1540 if (list) {
1541 if (argc != 1)
1542 return usage();
1543 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1544 char* forwards = adb_query(buf);
1545 if (forwards == NULL) {
1546 fprintf(stderr, "error: %s\n", adb_error());
1547 return 1;
1548 }
1549 printf("%s", forwards);
1550 free(forwards);
1551 return 0;
1552 }
1553
1554 // Implement forward --remove-all
1555 else if (remove_all) {
1556 if (argc != 1)
1557 return usage();
1558 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1559 }
1560
1561 // Implement forward --remove <local>
1562 else if (remove) {
1563 if (argc != 2)
1564 return usage();
1565 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1566 }
1567 // Or implement one of:
1568 // forward <local> <remote>
1569 // forward --no-rebind <local> <remote>
1570 else
1571 {
1572 if (argc != 3)
1573 return usage();
1574 const char* command = no_rebind ? "forward:norebind:" : "forward";
1575 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1576 }
1577
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001578 if(adb_command(buf)) {
1579 fprintf(stderr,"error: %s\n", adb_error());
1580 return 1;
1581 }
1582 return 0;
1583 }
1584
1585 /* do_sync_*() commands */
1586
1587 if(!strcmp(argv[0], "ls")) {
1588 if(argc != 2) return usage();
1589 return do_sync_ls(argv[1]);
1590 }
1591
1592 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001593 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001594 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001595 const char* lpath = NULL, *rpath = NULL;
1596
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001597 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001598
1599 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001600 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001601 }
1602
1603 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001604 }
1605
1606 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001607 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001608 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001609 const char* rpath = NULL, *lpath = ".";
1610
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001611 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001612
1613 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001614 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001615 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001616
1617 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001618 }
1619
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001620 if (!strcmp(argv[0], "install")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001621 if (argc < 2) return usage();
1622 return install_app(ttype, serial, argc, argv);
1623 }
1624
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001625 if (!strcmp(argv[0], "install-multiple")) {
1626 if (argc < 2) return usage();
1627 return install_multiple_app(ttype, serial, argc, argv);
1628 }
1629
1630 if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001631 if (argc < 2) return usage();
1632 return uninstall_app(ttype, serial, argc, argv);
1633 }
1634
1635 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001636 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001637 int listonly = 0;
1638
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001639 int ret;
1640 if(argc < 2) {
1641 /* No local path was specified. */
1642 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001643 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1644 listonly = 1;
1645 if (argc == 3) {
1646 srcarg = argv[2];
1647 } else {
1648 srcarg = NULL;
1649 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001650 } else if(argc == 2) {
1651 /* A local path or "android"/"data" arg was specified. */
1652 srcarg = argv[1];
1653 } else {
1654 return usage();
1655 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001656 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001657 if(ret != 0) return usage();
1658
1659 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001660 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001661 if(ret == 0 && vendor_srcpath != NULL)
1662 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001663 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001664 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001665
1666 free(android_srcpath);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001667 free(vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001668 free(data_srcpath);
1669 return ret;
1670 }
1671
1672 /* passthrough commands */
1673
1674 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001675 !strcmp(argv[0],"get-serialno") ||
1676 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001677 {
1678 char *tmp;
1679
1680 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1681 tmp = adb_query(buf);
1682 if(tmp) {
1683 printf("%s\n", tmp);
1684 return 0;
1685 } else {
1686 return 1;
1687 }
1688 }
1689
1690 /* other commands */
1691
1692 if(!strcmp(argv[0],"status-window")) {
1693 status_window(ttype, serial);
1694 return 0;
1695 }
1696
Christopher Tate7b9b5162011-11-30 13:00:33 -08001697 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001698 return logcat(ttype, serial, argc, argv);
1699 }
1700
1701 if(!strcmp(argv[0],"ppp")) {
1702 return ppp(argc, argv);
1703 }
1704
1705 if (!strcmp(argv[0], "start-server")) {
1706 return adb_connect("host:start-server");
1707 }
1708
Christopher Tate73779122011-04-21 12:53:28 -07001709 if (!strcmp(argv[0], "backup")) {
1710 return backup(argc, argv);
1711 }
1712
Christopher Tatecf5379b2011-05-17 15:52:54 -07001713 if (!strcmp(argv[0], "restore")) {
1714 return restore(argc, argv);
1715 }
1716
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001717 if (!strcmp(argv[0], "jdwp")) {
1718 int fd = adb_connect("jdwp");
1719 if (fd >= 0) {
1720 read_and_dump(fd);
1721 adb_close(fd);
1722 return 0;
1723 } else {
1724 fprintf(stderr, "error: %s\n", adb_error());
1725 return -1;
1726 }
1727 }
1728
1729 /* "adb /?" is a common idiom under Windows */
1730 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1731 help();
1732 return 0;
1733 }
1734
1735 if(!strcmp(argv[0], "version")) {
1736 version(stdout);
1737 return 0;
1738 }
1739
1740 usage();
1741 return 1;
1742}
1743
1744static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1745{
1746 char *argv[16];
1747 int argc;
1748 va_list ap;
1749
1750 va_start(ap, cmd);
1751 argc = 0;
1752
1753 if (serial) {
1754 argv[argc++] = "-s";
1755 argv[argc++] = serial;
1756 } else if (ttype == kTransportUsb) {
1757 argv[argc++] = "-d";
1758 } else if (ttype == kTransportLocal) {
1759 argv[argc++] = "-e";
1760 }
1761
1762 argv[argc++] = cmd;
1763 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1764 va_end(ap);
1765
1766#if 0
1767 int n;
1768 fprintf(stderr,"argc = %d\n",argc);
1769 for(n = 0; n < argc; n++) {
1770 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1771 }
1772#endif
1773
1774 return adb_commandline(argc, argv);
1775}
1776
1777int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001778 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001779{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001780 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1781 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001782
1783 if(srcarg == NULL) {
1784 android_srcdir = product_file("system");
1785 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001786 vendor_srcdir = product_file("vendor");
1787 /* Check if vendor partition exists */
1788 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1789 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001790 } else {
1791 /* srcarg may be "data", "system" or NULL.
1792 * if srcarg is NULL, then both data and system are synced
1793 */
1794 if(strcmp(srcarg, "system") == 0) {
1795 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001796 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001797 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001798 } else if(strcmp(srcarg, "vendor") == 0) {
1799 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001800 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001801 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001802 */
1803 return 1;
1804 }
1805 }
1806
1807 if(android_srcdir_out != NULL)
1808 *android_srcdir_out = android_srcdir;
1809 else
1810 free(android_srcdir);
1811
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001812 if(vendor_srcdir_out != NULL)
1813 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001814 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001815 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001816
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001817 if(data_srcdir_out != NULL)
1818 *data_srcdir_out = data_srcdir;
1819 else
1820 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001821 return 0;
1822}
1823
1824static int pm_command(transport_type transport, char* serial,
1825 int argc, char** argv)
1826{
1827 char buf[4096];
1828
1829 snprintf(buf, sizeof(buf), "shell:pm");
1830
1831 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001832 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001833 strncat(buf, " ", sizeof(buf) - 1);
1834 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001835 free(quoted);
1836 }
1837
1838 send_shellcommand(transport, serial, buf);
1839 return 0;
1840}
1841
1842int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1843{
1844 /* if the user choose the -k option, we refuse to do it until devices are
1845 out with the option to uninstall the remaining data somehow (adb/ui) */
1846 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1847 {
1848 printf(
1849 "The -k option uninstalls the application while retaining the data/cache.\n"
1850 "At the moment, there is no way to remove the remaining data.\n"
1851 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1852 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1853 return -1;
1854 }
1855
1856 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1857 return pm_command(transport, serial, argc, argv);
1858}
1859
1860static int delete_file(transport_type transport, char* serial, char* filename)
1861{
1862 char buf[4096];
1863 char* quoted;
1864
1865 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001866 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001867 strncat(buf, quoted, sizeof(buf)-1);
1868 free(quoted);
1869
1870 send_shellcommand(transport, serial, buf);
1871 return 0;
1872}
1873
Kenny Root3802c992011-08-05 11:19:45 -07001874static const char* get_basename(const char* filename)
1875{
1876 const char* basename = adb_dirstop(filename);
1877 if (basename) {
1878 basename++;
1879 return basename;
1880 } else {
1881 return filename;
1882 }
1883}
1884
Kenny Root3802c992011-08-05 11:19:45 -07001885int install_app(transport_type transport, char* serial, int argc, char** argv)
1886{
1887 static const char *const DATA_DEST = "/data/local/tmp/%s";
1888 static const char *const SD_DEST = "/sdcard/tmp/%s";
1889 const char* where = DATA_DEST;
Kenny Root3802c992011-08-05 11:19:45 -07001890 int i;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001891 struct stat sb;
Kenny Root3802c992011-08-05 11:19:45 -07001892
1893 for (i = 1; i < argc; i++) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001894 if (!strcmp(argv[i], "-s")) {
Kenny Root3802c992011-08-05 11:19:45 -07001895 where = SD_DEST;
1896 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001897 }
1898
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001899 // Find last APK argument.
1900 // All other arguments passed through verbatim.
1901 int last_apk = -1;
1902 for (i = argc - 1; i >= 0; i--) {
1903 char* file = argv[i];
1904 char* dot = strrchr(file, '.');
1905 if (dot && !strcasecmp(dot, ".apk")) {
1906 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1907 fprintf(stderr, "Invalid APK file: %s\n", file);
1908 return -1;
1909 }
1910
1911 last_apk = i;
1912 break;
1913 }
Kenny Root3802c992011-08-05 11:19:45 -07001914 }
1915
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001916 if (last_apk == -1) {
1917 fprintf(stderr, "Missing APK file\n");
1918 return -1;
Kenny Root3802c992011-08-05 11:19:45 -07001919 }
1920
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001921 char* apk_file = argv[last_apk];
1922 char apk_dest[PATH_MAX];
Kenny Root3802c992011-08-05 11:19:45 -07001923 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001924 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001925 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001926 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001927 } else {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001928 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root3802c992011-08-05 11:19:45 -07001929 }
1930
1931 pm_command(transport, serial, argc, argv);
1932
Kenny Root58d5f222012-03-26 16:14:02 -07001933cleanup_apk:
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001934 delete_file(transport, serial, apk_dest);
1935 return err;
1936}
1937
1938int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1939{
1940 char buf[1024];
1941 int i;
1942 struct stat sb;
1943 unsigned long long total_size = 0;
1944
1945 // Find all APK arguments starting at end.
1946 // All other arguments passed through verbatim.
1947 int first_apk = -1;
1948 for (i = argc - 1; i >= 0; i--) {
1949 char* file = argv[i];
1950 char* dot = strrchr(file, '.');
1951 if (dot && !strcasecmp(dot, ".apk")) {
1952 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1953 fprintf(stderr, "Invalid APK file: %s\n", file);
1954 return -1;
1955 }
1956
1957 total_size += sb.st_size;
1958 first_apk = i;
1959 } else {
1960 break;
1961 }
Kenny Root3802c992011-08-05 11:19:45 -07001962 }
1963
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001964 if (first_apk == -1) {
1965 fprintf(stderr, "Missing APK file\n");
1966 return 1;
1967 }
Kenny Root3802c992011-08-05 11:19:45 -07001968
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001969 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1970 for (i = 1; i < first_apk; i++) {
1971 char *quoted = escape_arg(argv[i]);
1972 strncat(buf, " ", sizeof(buf) - 1);
1973 strncat(buf, quoted, sizeof(buf) - 1);
1974 free(quoted);
1975 }
1976
1977 // Create install session
1978 int fd = adb_connect(buf);
1979 if (fd < 0) {
1980 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1981 return -1;
1982 }
1983 read_status_line(fd, buf, sizeof(buf));
1984 adb_close(fd);
1985
1986 int session_id = -1;
1987 if (!strncmp("Success", buf, 7)) {
1988 char* start = strrchr(buf, '[');
1989 char* end = strrchr(buf, ']');
1990 if (start && end) {
1991 *end = '\0';
1992 session_id = strtol(start + 1, NULL, 10);
1993 }
1994 }
1995 if (session_id < 0) {
1996 fprintf(stderr, "Failed to create session\n");
1997 fprintf(stderr, buf);
1998 return -1;
1999 }
2000
2001 // Valid session, now stream the APKs
2002 int success = 1;
2003 for (i = first_apk; i < argc; i++) {
2004 char* file = argv[i];
2005 if (stat(file, &sb) == -1) {
2006 fprintf(stderr, "Failed to stat %s\n", file);
2007 success = 0;
2008 goto finalize_session;
2009 }
2010
2011 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
2012 sb.st_size, session_id, i, get_basename(file));
2013
2014 int localFd = adb_open(file, O_RDONLY);
2015 if (localFd < 0) {
2016 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2017 success = 0;
2018 goto finalize_session;
2019 }
2020
2021 int remoteFd = adb_connect(buf);
2022 if (remoteFd < 0) {
2023 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2024 adb_close(localFd);
2025 success = 0;
2026 goto finalize_session;
2027 }
2028
2029 copy_to_file(localFd, remoteFd);
2030 read_status_line(remoteFd, buf, sizeof(buf));
2031
2032 adb_close(localFd);
2033 adb_close(remoteFd);
2034
2035 if (strncmp("Success", buf, 7)) {
2036 fprintf(stderr, "Failed to write %s\n", file);
2037 fprintf(stderr, buf);
2038 success = 0;
2039 goto finalize_session;
2040 }
2041 }
2042
2043finalize_session:
2044 // Commit session if we streamed everything okay; otherwise destroy
2045 if (success) {
2046 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2047 } else {
2048 snprintf(buf, sizeof(buf), "exec:pm install-destroy %d", session_id);
2049 }
2050
2051 fd = adb_connect(buf);
2052 if (fd < 0) {
2053 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2054 return -1;
2055 }
2056 read_status_line(fd, buf, sizeof(buf));
2057 adb_close(fd);
2058
2059 if (!strncmp("Success", buf, 7)) {
2060 fprintf(stderr, buf);
2061 return 0;
2062 } else {
2063 fprintf(stderr, "Failed to finalize session\n");
2064 fprintf(stderr, buf);
2065 return -1;
2066 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08002067}