blob: 51c039efc07b94433dddcf760c1174b02b2f64c8 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov31664102009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -070044 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey960df972014-06-09 17:30:57 -070046int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
48
49static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080050extern int gListenAll;
The Android Open Source Projectdd7bc332009-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 Gumbeld7b33082012-11-14 10:16:17 -080085 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-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 Andersone109d262012-04-20 11:21:14 -070090 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070091 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070092 " environment variable.\n"
The Android Open Source Projectdd7bc332009-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 Gumbeld7b33082012-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 Andersone109d262012-04-20 11:21:14 -0700101 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700102 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79ad2010-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-Fischer6715a432011-04-26 12:46:05 +0200107 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -0400108 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109 "\n"
110 "device commands:\n"
Mark Lindner76f2a932014-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 Molnarde8ff4a2013-04-19 12:41:09 -0700114 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700115 " - copy file/dir from device\n"
116 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700117 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600119 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-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' Turner0d82fbf2012-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 Projectdd7bc332009-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' Turner0d82fbf2012-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' Turner25258692013-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 Projectdd7bc332009-03-03 19:32:55 -0800154 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700155 " adb install [-lrtsd] <file>\n"
156 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700157 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-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 Projectdd7bc332009-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 Tate0c06eb52013-03-06 16:40:52 -0800169 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-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 Tated2f54152011-04-21 12:53:28 -0700173 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700174 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-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 Tated2f54152011-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 Tate56885092011-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 Tated2f54152011-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 Tate56885092011-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 Tated2f54152011-04-21 12:53:28 -0700188 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700189 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700190 "\n"
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-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 Andersone109d262012-04-20 11:21:14 -0700200 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800201 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700202 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400203 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800204 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700205 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800206 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700207 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 "\n"
209 "networking:\n"
210 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500211 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-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 Rosenberg686bce62014-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 Projectdd7bc332009-03-03 19:32:55 -0800219 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700220 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 " is updated.\n"
Timcd643152010-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 Projectdd7bc332009-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 Abgrall408fa572011-03-16 15:57:42 -0700270 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800271 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700272 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-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 Lockwooddd6b36e2009-09-22 01:18:40 -0400281 fwrite(buf, 1, len, stdout);
282 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800283 }
284}
285
Jeff Sharkey960df972014-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 Tated2f54152011-04-21 12:53:28 -0700304static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700305 const size_t BUFSIZE = 32 * 1024;
306 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700307 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700308 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700309
310 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkey5d9d4342014-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 Tated2f54152011-04-21 12:53:28 -0700316 for (;;) {
Jeff Sharkey5d9d4342014-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 Tated2f54152011-04-21 12:53:28 -0700322 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700323 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700324 break;
325 }
326 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700327 if (errno == EINTR) {
328 D("copy_to_file() : EINTR, retrying\n");
329 continue;
330 }
Christopher Tated2f54152011-04-21 12:53:28 -0700331 D("copy_to_file() : error %d\n", errno);
332 break;
333 }
Jeff Sharkey5d9d4342014-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 Tatec9cd3b92011-06-01 17:56:23 -0700340 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700341 }
Jeff Sharkey5d9d4342014-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 Tatec9cd3b92011-06-01 17:56:23 -0700347 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700348 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700349}
350
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-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 Projectdd7bc332009-03-03 19:32:55 -0800363 for(;;) {
364 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700365 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800366 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700367 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800368 if(r == 0) break;
369 if(r < 0) {
370 if(errno == EINTR) continue;
371 break;
372 }
Mike Lockwood67d53582010-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 Projectdd7bc332009-03-03 19:32:55 -0800389#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400390 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800391 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400392 default:
393 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800394 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800395 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 r = adb_write(fd, buf, r);
397 if(r <= 0) {
398 break;
399 }
400 }
The Android Open Source Projectdd7bc332009-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 Eriksson86ae6d52013-03-05 07:37:32 +0100448int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-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 Salyzyn60299df2014-04-30 09:10:31 -0700464 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-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 Eriksson86ae6d52013-03-05 07:37:32 +0100484 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-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 Eriksson86ae6d52013-03-05 07:37:32 +0100516 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800517 return -1;
518 }
519
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100520 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800521 free(data);
522 return status;
523}
524
Doug Zongker71fe5842014-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 Zongker4b39c6a2014-07-07 15:28:43 -0700576 for (;;) {
Doug Zongker71fe5842014-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 Cross6d6a8982014-07-07 14:12:41 -0700626 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-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 Projectdd7bc332009-03-03 19:32:55 -0800634static void status_window(transport_type ttype, const char* serial)
635{
636 char command[4096];
637 char *state = 0;
638 char *laststate = 0;
639
640 /* silence stderr */
641#ifdef _WIN32
642 /* XXX: TODO */
643#else
644 int fd;
645 fd = unix_open("/dev/null", O_WRONLY);
646 dup2(fd, 2);
647 adb_close(fd);
648#endif
649
650 format_host_command(command, sizeof command, "get-state", ttype, serial);
651
652 for(;;) {
653 adb_sleep_ms(250);
654
655 if(state) {
656 free(state);
657 state = 0;
658 }
659
660 state = adb_query(command);
661
662 if(state) {
663 if(laststate && !strcmp(state,laststate)){
664 continue;
665 } else {
666 if(laststate) free(laststate);
667 laststate = strdup(state);
668 }
669 }
670
671 printf("%c[2J%c[2H", 27, 27);
672 printf("Android Debug Bridge\n");
673 printf("State: %s\n", state ? state : "offline");
674 fflush(stdout);
675 }
676}
677
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700678static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700679{
680 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
681}
682
683/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700684static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800685{
686 const char *ts;
687 size_t alloc_len;
688 char *ret;
689 char *dest;
690
Jeff Sharkey7c460352014-06-10 16:22:17 -0700691 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700692 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700694 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800695 alloc_len++;
696 }
697 }
698
Jeff Sharkey7c460352014-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 Sharkeyfd546e82014-06-10 11:31:24 -0700708 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800709 dest = ret;
710
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700711 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700712 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713 *dest++ = '\\';
714 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715 *dest++ = *ts;
716 }
The Android Open Source Projectdd7bc332009-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 Sharkeyfd546e82014-06-10 11:31:24 -0700823 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800824
825 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700826 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800827 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700828 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700829 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800830
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700831 if (!strcmp(argv[0], "longcat")) {
832 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800833 }
834
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835 argc -= 1;
836 argv += 1;
837 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700838 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700839 strncat(buf, " ", sizeof(buf) - 1);
840 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841 free(quoted);
842 }
843
844 send_shellcommand(transport, serial, buf);
845 return 0;
846}
847
Mark Salyzyn60299df2014-04-30 09:10:31 -0700848static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800849{
850 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700851 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-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 Tated2f54152011-04-21 12:53:28 -0700867static int backup(int argc, char** argv) {
868 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800869 char default_name[32];
870 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700871 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700872 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700873
Christopher Tatec9cd3b92011-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 Tated2f54152011-04-21 12:53:28 -0700888 }
889
Christopher Tatebb86bc52011-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 Tateb1dfffe2011-12-08 19:04:34 -0800893 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700894 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800895 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-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 Tatebffa4ca2012-01-06 15:43:03 -0800915 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-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 Tate702967a2011-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 Carlstrom93c91fa2013-10-18 13:58:48 -0700938 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700939 adb_close(tarFd);
940 return -1;
941 }
942
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800943 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-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 Projectdd7bc332009-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 Tarasov31664102009-10-22 02:55:00 +11001016 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-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 Molnarde8ff4a2013-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 Lindner76f2a932014-03-11 17:55:59 -07001094 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001095 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001096
Lajos Molnarde8ff4a2013-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 Lindner76f2a932014-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 Projectdd7bc332009-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' Turner305b4b02011-01-31 14:23:56 +01001125 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001126 int persist = 0;
1127 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001128 transport_type ttype = kTransportAny;
1129 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001130 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-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 Pellydb449262009-05-07 12:48:03 -07001144 serial = getenv("ANDROID_SERIAL");
1145
Stefan Hilzingera84a42e2010-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 Gumbeld7b33082012-11-14 10:16:17 -08001151 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001152 fprintf(stderr,
Matt Gumbeld7b33082012-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 Hilzingera84a42e2010-04-19 12:21:12 +01001154 server_port_str);
1155 return usage();
1156 }
1157 }
1158
1159 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001160 while(argc > 0) {
David 'Digit' Turner305b4b02011-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 Projectdd7bc332009-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 Srinivasan81273232012-08-04 16:40:50 -07001178 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-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 Hilzingera84a42e2010-04-19 12:21:12 +01001190 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-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 Gumbeld7b33082012-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 Projectdd7bc332009-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 Hilzingera84a42e2010-04-19 12:21:12 +01001244 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001245
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001246 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001247 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001248 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001249 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001250 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-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 Andersone109d262012-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 Projectdd7bc332009-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 Lockwoodcbbe79ad2010-05-24 10:44:35 -04001287 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001288 char *tmp;
1289 if (argc != 2) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001290 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001291 return 1;
1292 }
Mike Lockwoodcbbe79ad2010-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 Lockwoodff196702009-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 Projectdd7bc332009-03-03 19:32:55 -08001323 if (!strcmp(argv[0], "emu")) {
1324 return adb_send_emulator_command(argc, argv);
1325 }
1326
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001327 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001328 int r;
1329 int fd;
1330
Daniel Sandlerff91ab82010-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 Projectdd7bc332009-03-03 19:32:55 -08001338 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001339 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-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 Projectdd7bc332009-03-03 19:32:55 -08001346 }
1347
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001348 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001349 argc -= 2;
1350 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001351 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001352 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-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 Projectdd7bc332009-03-03 19:32:55 -08001356 }
1357
1358 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001359 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001360 fd = adb_connect(buf);
1361 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001362 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001363 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001364 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-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 Sandlerff91ab82010-08-19 01:10:18 -04001377 if (h) {
1378 printf("\x1b[0m");
1379 fflush(stdout);
1380 }
JP Abgrall408fa572011-03-16 15:57:42 -07001381 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001382 return r;
1383 }
1384 }
1385 }
1386
Jeff Sharkey5d9d4342014-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 Sharkey7c460352014-06-10 16:22:17 -07001395 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-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 Projectdd7bc332009-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 Zongker447f0612012-01-09 14:54:53 -08001427 if(!strcmp(argv[0], "sideload")) {
1428 if(argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001429 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001430 return 1;
1431 } else {
1432 return 0;
1433 }
1434 }
1435
Mike Lockwoodff196702009-08-24 15:58:40 -07001436 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001437 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001438 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001439 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001440 char command[100];
Romain Guy311add42009-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 Lockwoodff196702009-08-24 15:58:40 -07001444 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001445 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001446 snprintf(command, sizeof(command), "%s:", argv[0]);
1447 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-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 Lockwoodf56d1b52009-09-03 14:54:58 -04001457 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001458 if (argc != 1) return usage();
1459 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001460 return 0;
1461 }
1462
The Android Open Source Projectdd7bc332009-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' Turner25258692013-03-21 21:07:42 +01001496 if(!strcmp(argv[0], "forward") ||
1497 !strcmp(argv[0], "reverse"))
1498 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001499 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001500 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-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 Projectdd7bc332009-03-03 19:32:55 -08001521 }
David 'Digit' Turner0d82fbf2012-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' Turner25258692013-03-21 21:07:42 +01001529 if (reverse) {
1530 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001531 } else {
David 'Digit' Turner25258692013-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' Turner0d82fbf2012-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 Projectdd7bc332009-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 Lindner76f2a932014-03-11 17:55:59 -07001598 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001599 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001600 const char* lpath = NULL, *rpath = NULL;
1601
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001602 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001603
1604 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001605 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001606 }
1607
1608 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001609 }
1610
1611 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001612 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001613 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001614 const char* rpath = NULL, *lpath = ".";
1615
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001616 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001617
1618 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001619 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001620 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001621
1622 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 }
1624
Jeff Sharkey960df972014-06-09 17:30:57 -07001625 if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001626 if (argc < 2) return usage();
1627 return install_app(ttype, serial, argc, argv);
1628 }
1629
Jeff Sharkey960df972014-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 Projectdd7bc332009-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 Rosenberg686bce62014-06-30 20:29:40 -07001641 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001642 int listonly = 0;
1643
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001644 int ret;
1645 if(argc < 2) {
1646 /* No local path was specified. */
1647 srcarg = NULL;
Anthony Newnam705c9442010-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 Projectdd7bc332009-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 Rosenberg686bce62014-06-30 20:29:40 -07001661 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001662 if(ret != 0) return usage();
1663
1664 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001665 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberg686bce62014-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 Projectdd7bc332009-03-03 19:32:55 -08001668 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001669 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001670
1671 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001672 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-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 Andersone109d262012-04-20 11:21:14 -07001680 !strcmp(argv[0],"get-serialno") ||
1681 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-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 Tatedb0a8802011-11-30 13:00:33 -08001702 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-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 Tated2f54152011-04-21 12:53:28 -07001714 if (!strcmp(argv[0], "backup")) {
1715 return backup(argc, argv);
1716 }
1717
Christopher Tate702967a2011-05-17 15:52:54 -07001718 if (!strcmp(argv[0], "restore")) {
1719 return restore(argc, argv);
1720 }
1721
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001722 if (!strcmp(argv[0], "jdwp")) {
1723 int fd = adb_connect("jdwp");
1724 if (fd >= 0) {
1725 read_and_dump(fd);
1726 adb_close(fd);
1727 return 0;
1728 } else {
1729 fprintf(stderr, "error: %s\n", adb_error());
1730 return -1;
1731 }
1732 }
1733
1734 /* "adb /?" is a common idiom under Windows */
1735 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1736 help();
1737 return 0;
1738 }
1739
1740 if(!strcmp(argv[0], "version")) {
1741 version(stdout);
1742 return 0;
1743 }
1744
1745 usage();
1746 return 1;
1747}
1748
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001749#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001750static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1751{
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001752 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001753 int argc;
1754 va_list ap;
1755
1756 va_start(ap, cmd);
1757 argc = 0;
1758
1759 if (serial) {
1760 argv[argc++] = "-s";
1761 argv[argc++] = serial;
1762 } else if (ttype == kTransportUsb) {
1763 argv[argc++] = "-d";
1764 } else if (ttype == kTransportLocal) {
1765 argv[argc++] = "-e";
1766 }
1767
1768 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001769 while(argc < MAX_ARGV_LENGTH &&
1770 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1771 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001772 va_end(ap);
1773
1774#if 0
1775 int n;
1776 fprintf(stderr,"argc = %d\n",argc);
1777 for(n = 0; n < argc; n++) {
1778 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1779 }
1780#endif
1781
1782 return adb_commandline(argc, argv);
1783}
1784
1785int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001786 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001787{
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001788 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1789 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001790
1791 if(srcarg == NULL) {
1792 android_srcdir = product_file("system");
1793 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001794 vendor_srcdir = product_file("vendor");
1795 /* Check if vendor partition exists */
1796 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1797 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001798 } else {
1799 /* srcarg may be "data", "system" or NULL.
1800 * if srcarg is NULL, then both data and system are synced
1801 */
1802 if(strcmp(srcarg, "system") == 0) {
1803 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001804 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001805 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001806 } else if(strcmp(srcarg, "vendor") == 0) {
1807 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001808 } else {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001809 /* It's not "system", "vendor", or "data".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001810 */
1811 return 1;
1812 }
1813 }
1814
1815 if(android_srcdir_out != NULL)
1816 *android_srcdir_out = android_srcdir;
1817 else
1818 free(android_srcdir);
1819
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001820 if(vendor_srcdir_out != NULL)
1821 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001822 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001823 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001824
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001825 if(data_srcdir_out != NULL)
1826 *data_srcdir_out = data_srcdir;
1827 else
1828 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001829 return 0;
1830}
1831
1832static int pm_command(transport_type transport, char* serial,
1833 int argc, char** argv)
1834{
1835 char buf[4096];
1836
1837 snprintf(buf, sizeof(buf), "shell:pm");
1838
1839 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001840 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001841 strncat(buf, " ", sizeof(buf) - 1);
1842 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001843 free(quoted);
1844 }
1845
1846 send_shellcommand(transport, serial, buf);
1847 return 0;
1848}
1849
1850int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1851{
1852 /* if the user choose the -k option, we refuse to do it until devices are
1853 out with the option to uninstall the remaining data somehow (adb/ui) */
1854 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1855 {
1856 printf(
1857 "The -k option uninstalls the application while retaining the data/cache.\n"
1858 "At the moment, there is no way to remove the remaining data.\n"
1859 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1860 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1861 return -1;
1862 }
1863
1864 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1865 return pm_command(transport, serial, argc, argv);
1866}
1867
1868static int delete_file(transport_type transport, char* serial, char* filename)
1869{
1870 char buf[4096];
1871 char* quoted;
1872
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001873 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001874 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001875 strncat(buf, quoted, sizeof(buf)-1);
1876 free(quoted);
1877
1878 send_shellcommand(transport, serial, buf);
1879 return 0;
1880}
1881
Kenny Root597ea5b2011-08-05 11:19:45 -07001882static const char* get_basename(const char* filename)
1883{
1884 const char* basename = adb_dirstop(filename);
1885 if (basename) {
1886 basename++;
1887 return basename;
1888 } else {
1889 return filename;
1890 }
1891}
1892
Kenny Root597ea5b2011-08-05 11:19:45 -07001893int install_app(transport_type transport, char* serial, int argc, char** argv)
1894{
1895 static const char *const DATA_DEST = "/data/local/tmp/%s";
1896 static const char *const SD_DEST = "/sdcard/tmp/%s";
1897 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001898 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001899 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001900
1901 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001902 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001903 where = SD_DEST;
1904 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001905 }
1906
Jeff Sharkey960df972014-06-09 17:30:57 -07001907 // Find last APK argument.
1908 // All other arguments passed through verbatim.
1909 int last_apk = -1;
1910 for (i = argc - 1; i >= 0; i--) {
1911 char* file = argv[i];
1912 char* dot = strrchr(file, '.');
1913 if (dot && !strcasecmp(dot, ".apk")) {
1914 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1915 fprintf(stderr, "Invalid APK file: %s\n", file);
1916 return -1;
1917 }
1918
1919 last_apk = i;
1920 break;
1921 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001922 }
1923
Jeff Sharkey960df972014-06-09 17:30:57 -07001924 if (last_apk == -1) {
1925 fprintf(stderr, "Missing APK file\n");
1926 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001927 }
1928
Jeff Sharkey960df972014-06-09 17:30:57 -07001929 char* apk_file = argv[last_apk];
1930 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001931 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001932 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001933 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001934 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001935 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001936 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001937 }
1938
1939 pm_command(transport, serial, argc, argv);
1940
Kenny Root60733e92012-03-26 16:14:02 -07001941cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001942 delete_file(transport, serial, apk_dest);
1943 return err;
1944}
1945
1946int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1947{
1948 char buf[1024];
1949 int i;
1950 struct stat sb;
1951 unsigned long long total_size = 0;
1952
1953 // Find all APK arguments starting at end.
1954 // All other arguments passed through verbatim.
1955 int first_apk = -1;
1956 for (i = argc - 1; i >= 0; i--) {
1957 char* file = argv[i];
1958 char* dot = strrchr(file, '.');
1959 if (dot && !strcasecmp(dot, ".apk")) {
1960 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1961 fprintf(stderr, "Invalid APK file: %s\n", file);
1962 return -1;
1963 }
1964
1965 total_size += sb.st_size;
1966 first_apk = i;
1967 } else {
1968 break;
1969 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001970 }
1971
Jeff Sharkey960df972014-06-09 17:30:57 -07001972 if (first_apk == -1) {
1973 fprintf(stderr, "Missing APK file\n");
1974 return 1;
1975 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001976
Jeff Sharkey960df972014-06-09 17:30:57 -07001977 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1978 for (i = 1; i < first_apk; i++) {
1979 char *quoted = escape_arg(argv[i]);
1980 strncat(buf, " ", sizeof(buf) - 1);
1981 strncat(buf, quoted, sizeof(buf) - 1);
1982 free(quoted);
1983 }
1984
1985 // Create install session
1986 int fd = adb_connect(buf);
1987 if (fd < 0) {
1988 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1989 return -1;
1990 }
1991 read_status_line(fd, buf, sizeof(buf));
1992 adb_close(fd);
1993
1994 int session_id = -1;
1995 if (!strncmp("Success", buf, 7)) {
1996 char* start = strrchr(buf, '[');
1997 char* end = strrchr(buf, ']');
1998 if (start && end) {
1999 *end = '\0';
2000 session_id = strtol(start + 1, NULL, 10);
2001 }
2002 }
2003 if (session_id < 0) {
2004 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002005 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002006 return -1;
2007 }
2008
2009 // Valid session, now stream the APKs
2010 int success = 1;
2011 for (i = first_apk; i < argc; i++) {
2012 char* file = argv[i];
2013 if (stat(file, &sb) == -1) {
2014 fprintf(stderr, "Failed to stat %s\n", file);
2015 success = 0;
2016 goto finalize_session;
2017 }
2018
2019 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002020 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002021
2022 int localFd = adb_open(file, O_RDONLY);
2023 if (localFd < 0) {
2024 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2025 success = 0;
2026 goto finalize_session;
2027 }
2028
2029 int remoteFd = adb_connect(buf);
2030 if (remoteFd < 0) {
2031 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2032 adb_close(localFd);
2033 success = 0;
2034 goto finalize_session;
2035 }
2036
2037 copy_to_file(localFd, remoteFd);
2038 read_status_line(remoteFd, buf, sizeof(buf));
2039
2040 adb_close(localFd);
2041 adb_close(remoteFd);
2042
2043 if (strncmp("Success", buf, 7)) {
2044 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002045 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002046 success = 0;
2047 goto finalize_session;
2048 }
2049 }
2050
2051finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002052 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002053 if (success) {
2054 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2055 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002056 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002057 }
2058
2059 fd = adb_connect(buf);
2060 if (fd < 0) {
2061 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2062 return -1;
2063 }
2064 read_status_line(fd, buf, sizeof(buf));
2065 adb_close(fd);
2066
2067 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002068 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002069 return 0;
2070 } else {
2071 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002072 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002073 return -1;
2074 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002075}