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