blob: eea882d12f8b59b756e28c1b11df5502fbfeb411 [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
Andrew Hsiehb73d0e02014-05-07 20:21:11 +080018#include <stdint.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080019#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <unistd.h>
23#include <limits.h>
24#include <stdarg.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <ctype.h>
28#include <assert.h>
29
30#include "sysdeps.h"
31
32#ifdef HAVE_TERMIO_H
33#include <termios.h>
34#endif
35
36#define TRACE_TAG TRACE_ADB
37#include "adb.h"
38#include "adb_client.h"
39#include "file_sync_service.h"
40
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080041static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
42
Alexey Tarasov857f17a2009-10-22 02:55:00 +110043void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080044int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -070045 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080046int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -070047int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080048int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
49
50static const char *gProductOutPath = NULL;
Matt Gumbel411775c2012-11-14 10:16:17 -080051extern int gListenAll;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080052
53static char *product_file(const char *extra)
54{
55 int n;
56 char *x;
57
58 if (gProductOutPath == NULL) {
59 fprintf(stderr, "adb: Product directory not specified; "
60 "use -p or define ANDROID_PRODUCT_OUT\n");
61 exit(1);
62 }
63
64 n = strlen(gProductOutPath) + strlen(extra) + 2;
65 x = malloc(n);
66 if (x == 0) {
67 fprintf(stderr, "adb: Out of memory (product_file())\n");
68 exit(1);
69 }
70
71 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
72 return x;
73}
74
75void version(FILE * out) {
76 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
77 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
78}
79
80void help()
81{
82 version(stderr);
83
84 fprintf(stderr,
85 "\n"
Matt Gumbel411775c2012-11-14 10:16:17 -080086 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080087 " -d - directs command to the only connected USB device\n"
88 " returns an error if more than one USB device is present.\n"
89 " -e - directs command to the only running emulator.\n"
90 " returns an error if more than one emulator is running.\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -070091 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson27042382012-05-30 18:11:27 -070092 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070093 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080094 " -p <product name or path> - simple product name like 'sooner', or\n"
95 " a relative/absolute path to a product\n"
96 " out directory like 'out/target/product/sooner'.\n"
97 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
98 " environment variable is used, which must\n"
99 " be an absolute path.\n"
Matt Gumbel411775c2012-11-14 10:16:17 -0800100 " -H - Name of adb server host (default: localhost)\n"
101 " -P - Port of adb server (default: 5037)\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700102 " devices [-l] - list all connected devices\n"
Scott Anderson27042382012-05-30 18:11:27 -0700103 " ('-l' will also list device qualifiers)\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400104 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
105 " Port 5555 is used by default if no port number is specified.\n"
106 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
107 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischerc3e82b82011-04-26 12:46:05 +0200108 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400109 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800110 "\n"
111 "device commands:\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700112 " adb push [-p] <local> <remote>\n"
113 " - copy file/dir to device\n"
114 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700115 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700116 " - copy file/dir from device\n"
117 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700118 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800119 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600120 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800121 " (see 'adb help all')\n"
122 " adb shell - run remote shell interactively\n"
123 " adb shell <command> - run remote shell command\n"
124 " adb emu <command> - run emulator console command\n"
125 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100126 " adb forward --list - list all forward socket connections.\n"
127 " the format is a list of lines with the following format:\n"
128 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800129 " adb forward <local> <remote> - forward socket connections\n"
130 " forward specs are one of: \n"
131 " tcp:<port>\n"
132 " localabstract:<unix domain socket name>\n"
133 " localreserved:<unix domain socket name>\n"
134 " localfilesystem:<unix domain socket name>\n"
135 " dev:<character device name>\n"
136 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100137 " adb forward --no-rebind <local> <remote>\n"
138 " - same as 'adb forward <local> <remote>' but fails\n"
139 " if <local> is already forwarded\n"
140 " adb forward --remove <local> - remove a specific forward socket connection\n"
141 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner963a4492013-03-21 21:07:42 +0100142 " adb reverse --list - list all reverse socket connections from device\n"
143 " adb reverse <remote> <local> - reverse socket connections\n"
144 " reverse specs are one of:\n"
145 " tcp:<port>\n"
146 " localabstract:<unix domain socket name>\n"
147 " localreserved:<unix domain socket name>\n"
148 " localfilesystem:<unix domain socket name>\n"
149 " adb reverse --norebind <remote> <local>\n"
150 " - same as 'adb reverse <remote> <local>' but fails\n"
151 " if <remote> is already reversed.\n"
152 " adb reverse --remove <remote>\n"
153 " - remove a specific reversed socket connection\n"
154 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800155 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700156 " adb install [-lrtsd] <file>\n"
157 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700158 " - push this package file to the device and install it\n"
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700159 " (-l: forward lock application)\n"
160 " (-r: replace existing application)\n"
161 " (-t: allow test packages)\n"
162 " (-s: install application on sdcard)\n"
163 " (-d: allow version code downgrade)\n"
164 " (-p: partial application install)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800165 " adb uninstall [-k] <package> - remove this app package from the device\n"
166 " ('-k' means keep the data and cache directories)\n"
167 " adb bugreport - return all information from the device\n"
168 " that should be included in a bug report.\n"
169 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800170 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700171 " - write an archive of the device's data to <file>.\n"
172 " If no -f option is supplied then the data is written\n"
173 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700174 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700175 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800176 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
177 " (aka .obb) files associated with each application; the default\n"
178 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700179 " (-shared|-noshared enable/disable backup of the device's\n"
180 " shared storage / SD card contents; the default is noshared.)\n"
181 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700182 " (-system|-nosystem toggles whether -all automatically includes\n"
183 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700184 " (<packages...> is the list of applications to be backed up. If\n"
185 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700186 " list is optional. Applications explicitly given on the\n"
187 " command line will be included even if -nosystem would\n"
188 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700189 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700190 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700191 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800192 " adb help - show this help message\n"
193 " adb version - show version num\n"
194 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800195 "scripting:\n"
196 " adb wait-for-device - block until device is online\n"
197 " adb start-server - ensure that there is a server running\n"
198 " adb kill-server - kill the server if it is running\n"
199 " adb get-state - prints: offline | bootloader | device\n"
200 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700201 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800202 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700203 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400204 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800205 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700206 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800207 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700208 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800209 "\n"
210 "networking:\n"
211 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500212 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800213 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
214 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
215 "\n"
216 "adb sync notes: adb sync [ <directory> ]\n"
217 " <localdir> can be interpreted in several ways:\n"
218 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700219 " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800220 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700221 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800222 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000223 "\n"
224 "environmental variables:\n"
225 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
226 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
227 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
228 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800229 );
230}
231
232int usage()
233{
234 help();
235 return 1;
236}
237
238#ifdef HAVE_TERMIO_H
239static struct termios tio_save;
240
241static void stdin_raw_init(int fd)
242{
243 struct termios tio;
244
245 if(tcgetattr(fd, &tio)) return;
246 if(tcgetattr(fd, &tio_save)) return;
247
248 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
249
250 /* no timeout but request at least one character per read */
251 tio.c_cc[VTIME] = 0;
252 tio.c_cc[VMIN] = 1;
253
254 tcsetattr(fd, TCSANOW, &tio);
255 tcflush(fd, TCIFLUSH);
256}
257
258static void stdin_raw_restore(int fd)
259{
260 tcsetattr(fd, TCSANOW, &tio_save);
261 tcflush(fd, TCIFLUSH);
262}
263#endif
264
265static void read_and_dump(int fd)
266{
267 char buf[4096];
268 int len;
269
270 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700271 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800272 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700273 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800274 if(len == 0) {
275 break;
276 }
277
278 if(len < 0) {
279 if(errno == EINTR) continue;
280 break;
281 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400282 fwrite(buf, 1, len, stdout);
283 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800284 }
285}
286
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700287static void read_status_line(int fd, char* buf, size_t count)
288{
289 count--;
290 while (count > 0) {
291 int len = adb_read(fd, buf, count);
292 if (len == 0) {
293 break;
294 } else if (len < 0) {
295 if (errno == EINTR) continue;
296 break;
297 }
298
299 buf += len;
300 count -= len;
301 }
302 *buf = '\0';
303}
304
Christopher Tate73779122011-04-21 12:53:28 -0700305static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700306 const size_t BUFSIZE = 32 * 1024;
307 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700308 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700309 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700310
311 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700312#ifdef HAVE_TERMIO_H
313 if (inFd == STDIN_FILENO) {
314 stdin_raw_init(STDIN_FILENO);
315 }
316#endif
Christopher Tate73779122011-04-21 12:53:28 -0700317 for (;;) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700318 if (inFd == STDIN_FILENO) {
319 len = unix_read(inFd, buf, BUFSIZE);
320 } else {
321 len = adb_read(inFd, buf, BUFSIZE);
322 }
Christopher Tate73779122011-04-21 12:53:28 -0700323 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700324 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700325 break;
326 }
327 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700328 if (errno == EINTR) {
329 D("copy_to_file() : EINTR, retrying\n");
330 continue;
331 }
Christopher Tate73779122011-04-21 12:53:28 -0700332 D("copy_to_file() : error %d\n", errno);
333 break;
334 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700335 if (outFd == STDOUT_FILENO) {
336 fwrite(buf, 1, len, stdout);
337 fflush(stdout);
338 } else {
339 adb_write(outFd, buf, len);
340 }
Christopher Tatefba22972011-06-01 17:56:23 -0700341 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700342 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700343#ifdef HAVE_TERMIO_H
344 if (inFd == STDIN_FILENO) {
345 stdin_raw_restore(STDIN_FILENO);
346 }
347#endif
Christopher Tatefba22972011-06-01 17:56:23 -0700348 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700349 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700350}
351
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800352static void *stdin_read_thread(void *x)
353{
354 int fd, fdi;
355 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800356 int r, n;
357 int state = 0;
358
359 int *fds = (int*) x;
360 fd = fds[0];
361 fdi = fds[1];
362 free(fds);
363
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800364 for(;;) {
365 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700366 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800367 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700368 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800369 if(r == 0) break;
370 if(r < 0) {
371 if(errno == EINTR) continue;
372 break;
373 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400374 for(n = 0; n < r; n++){
375 switch(buf[n]) {
376 case '\n':
377 state = 1;
378 break;
379 case '\r':
380 state = 1;
381 break;
382 case '~':
383 if(state == 1) state++;
384 break;
385 case '.':
386 if(state == 2) {
387 fprintf(stderr,"\n* disconnect *\n");
388#ifdef HAVE_TERMIO_H
389 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800390#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400391 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800392 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400393 default:
394 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800395 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800396 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800397 r = adb_write(fd, buf, r);
398 if(r <= 0) {
399 break;
400 }
401 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800402 return 0;
403}
404
405int interactive_shell(void)
406{
407 adb_thread_t thr;
408 int fdi, fd;
409 int *fds;
410
411 fd = adb_connect("shell:");
412 if(fd < 0) {
413 fprintf(stderr,"error: %s\n", adb_error());
414 return 1;
415 }
416 fdi = 0; //dup(0);
417
418 fds = malloc(sizeof(int) * 2);
419 fds[0] = fd;
420 fds[1] = fdi;
421
422#ifdef HAVE_TERMIO_H
423 stdin_raw_init(fdi);
424#endif
425 adb_thread_create(&thr, stdin_read_thread, fds);
426 read_and_dump(fd);
427#ifdef HAVE_TERMIO_H
428 stdin_raw_restore(fdi);
429#endif
430 return 0;
431}
432
433
434static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
435{
436 if (serial) {
437 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
438 } else {
439 const char* prefix = "host";
440 if (ttype == kTransportUsb)
441 prefix = "host-usb";
442 else if (ttype == kTransportLocal)
443 prefix = "host-local";
444
445 snprintf(buffer, buflen, "%s:%s", prefix, command);
446 }
447}
448
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100449int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800450 unsigned progress)
451{
452 char buf[4096];
453 unsigned total;
454 int fd;
455 const unsigned char *ptr;
456
457 sprintf(buf,"%s:%d", service, sz);
458 fd = adb_connect(buf);
459 if(fd < 0) {
460 fprintf(stderr,"error: %s\n", adb_error());
461 return -1;
462 }
463
464 int opt = CHUNK_SIZE;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700465 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800466
467 total = sz;
468 ptr = data;
469
470 if(progress) {
471 char *x = strrchr(service, ':');
472 if(x) service = x + 1;
473 }
474
475 while(sz > 0) {
476 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
477 if(writex(fd, ptr, xfer)) {
478 adb_status(fd);
479 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
480 return -1;
481 }
482 sz -= xfer;
483 ptr += xfer;
484 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100485 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800486 fflush(stdout);
487 }
488 }
489 if(progress) {
490 printf("\n");
491 }
492
493 if(readx(fd, buf, 4)){
494 fprintf(stderr,"* error reading response *\n");
495 adb_close(fd);
496 return -1;
497 }
498 if(memcmp(buf, "OKAY", 4)) {
499 buf[4] = 0;
500 fprintf(stderr,"* error response '%s' *\n", buf);
501 adb_close(fd);
502 return -1;
503 }
504
505 adb_close(fd);
506 return 0;
507}
508
509
510int adb_download(const char *service, const char *fn, unsigned progress)
511{
512 void *data;
513 unsigned sz;
514
515 data = load_file(fn, &sz);
516 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100517 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800518 return -1;
519 }
520
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100521 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800522 free(data);
523 return status;
524}
525
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700526#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
527
528/*
529 * The sideload-host protocol serves the data in a file (given on the
530 * command line) to the client, using a simple protocol:
531 *
532 * - The connect message includes the total number of bytes in the
533 * file and a block size chosen by us.
534 *
535 * - The other side sends the desired block number as eight decimal
536 * digits (eg "00000023" for block 23). Blocks are numbered from
537 * zero.
538 *
539 * - We send back the data of the requested block. The last block is
540 * likely to be partial; when the last block is requested we only
541 * send the part of the block that exists, it's not padded up to the
542 * block size.
543 *
544 * - When the other side sends "DONEDONE" instead of a block number,
545 * we hang up.
546 */
547int adb_sideload_host(const char* fn) {
548 uint8_t* data;
549 unsigned sz;
550 size_t xfer = 0;
551 int status;
552
553 printf("loading: '%s'", fn);
554 fflush(stdout);
555 data = load_file(fn, &sz);
556 if (data == 0) {
557 printf("\n");
558 fprintf(stderr, "* cannot read '%s' *\n", fn);
559 return -1;
560 }
561
562 char buf[100];
563 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
564 int fd = adb_connect(buf);
565 if (fd < 0) {
566 // Try falling back to the older sideload method. Maybe this
567 // is an older device that doesn't support sideload-host.
568 printf("\n");
569 status = adb_download_buffer("sideload", fn, data, sz, 1);
570 goto done;
571 }
572
573 int opt = SIDELOAD_HOST_BLOCK_SIZE;
574 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
575
576 int last_percent = -1;
Doug Zongkera27ee6c2014-07-07 15:28:43 -0700577 for (;;) {
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700578 if (readx(fd, buf, 8)) {
579 fprintf(stderr, "* failed to read command: %s\n", adb_error());
580 status = -1;
581 goto done;
582 }
583
584 if (strncmp("DONEDONE", buf, 8) == 0) {
585 status = 0;
586 break;
587 }
588
589 buf[8] = '\0';
590 int block = strtol(buf, NULL, 10);
591
592 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
593 if (offset >= sz) {
594 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
595 status = -1;
596 goto done;
597 }
598 uint8_t* start = data + offset;
599 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
600 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
601 if (offset_end > sz) {
602 to_write = sz - offset;
603 }
604
605 if(writex(fd, start, to_write)) {
606 adb_status(fd);
607 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
608 status = -1;
609 goto done;
610 }
611 xfer += to_write;
612
613 // For normal OTA packages, we expect to transfer every byte
614 // twice, plus a bit of overhead (one read during
615 // verification, one read of each byte for installation, plus
616 // extra access to things like the zip central directory).
617 // This estimate of the completion becomes 100% when we've
618 // transferred ~2.13 (=100/47) times the package size.
619 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
620 if (percent != last_percent) {
621 printf("\rserving: '%s' (~%d%%) ", fn, percent);
622 fflush(stdout);
623 last_percent = percent;
624 }
625 }
626
Colin Cross2328bea2014-07-07 14:12:41 -0700627 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700628
629 done:
630 if (fd >= 0) adb_close(fd);
631 free(data);
632 return status;
633}
634
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800635static void status_window(transport_type ttype, const char* serial)
636{
637 char command[4096];
638 char *state = 0;
639 char *laststate = 0;
640
641 /* silence stderr */
642#ifdef _WIN32
643 /* XXX: TODO */
644#else
645 int fd;
646 fd = unix_open("/dev/null", O_WRONLY);
647 dup2(fd, 2);
648 adb_close(fd);
649#endif
650
651 format_host_command(command, sizeof command, "get-state", ttype, serial);
652
653 for(;;) {
654 adb_sleep_ms(250);
655
656 if(state) {
657 free(state);
658 state = 0;
659 }
660
661 state = adb_query(command);
662
663 if(state) {
664 if(laststate && !strcmp(state,laststate)){
665 continue;
666 } else {
667 if(laststate) free(laststate);
668 laststate = strdup(state);
669 }
670 }
671
672 printf("%c[2J%c[2H", 27, 27);
673 printf("Android Debug Bridge\n");
674 printf("State: %s\n", state ? state : "offline");
675 fflush(stdout);
676 }
677}
678
Brian Carlstrom529fca82014-08-05 22:51:18 -0700679static int should_escape(const char c)
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700680{
681 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
682}
683
684/* Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700685static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800686{
687 const char *ts;
688 size_t alloc_len;
689 char *ret;
690 char *dest;
691
Jeff Sharkey026d9622014-06-10 16:22:17 -0700692 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700693 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800694 alloc_len++;
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700695 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800696 alloc_len++;
697 }
698 }
699
Jeff Sharkey026d9622014-06-10 16:22:17 -0700700 if (alloc_len == 0) {
701 // Preserve empty arguments
702 ret = (char *) malloc(3);
703 ret[0] = '\"';
704 ret[1] = '\"';
705 ret[2] = '\0';
706 return ret;
707 }
708
Jeff Sharkey824d1062014-06-10 11:31:24 -0700709 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800710 dest = ret;
711
Jeff Sharkey824d1062014-06-10 11:31:24 -0700712 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700713 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800714 *dest++ = '\\';
715 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800716 *dest++ = *ts;
717 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800718 *dest++ = '\0';
719
720 return ret;
721}
722
723/**
724 * Run ppp in "notty" mode against a resource listed as the first parameter
725 * eg:
726 *
727 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
728 *
729 */
730int ppp(int argc, char **argv)
731{
Yabin Cui2fa43212014-11-11 09:24:11 -0800732#if defined(_WIN32)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800733 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
734 return -1;
735#else
736 char *adb_service_name;
737 pid_t pid;
738 int fd;
739
740 if (argc < 2) {
741 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
742 argv[0]);
743
744 return 1;
745 }
746
747 adb_service_name = argv[1];
748
749 fd = adb_connect(adb_service_name);
750
751 if(fd < 0) {
752 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
753 adb_service_name, adb_error());
754 return 1;
755 }
756
757 pid = fork();
758
759 if (pid < 0) {
760 perror("from fork()");
761 return 1;
762 } else if (pid == 0) {
763 int err;
764 int i;
765 const char **ppp_args;
766
767 // copy args
768 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
769 ppp_args[0] = "pppd";
770 for (i = 2 ; i < argc ; i++) {
771 //argv[2] and beyond become ppp_args[1] and beyond
772 ppp_args[i - 1] = argv[i];
773 }
774 ppp_args[i-1] = NULL;
775
776 // child side
777
778 dup2(fd, STDIN_FILENO);
779 dup2(fd, STDOUT_FILENO);
780 adb_close(STDERR_FILENO);
781 adb_close(fd);
782
783 err = execvp("pppd", (char * const *)ppp_args);
784
785 if (err < 0) {
786 perror("execing pppd");
787 }
788 exit(-1);
789 } else {
790 // parent side
791
792 adb_close(fd);
793 return 0;
794 }
Yabin Cui2fa43212014-11-11 09:24:11 -0800795#endif /* !defined(_WIN32) */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800796}
797
798static int send_shellcommand(transport_type transport, char* serial, char* buf)
799{
800 int fd, ret;
801
802 for(;;) {
803 fd = adb_connect(buf);
804 if(fd >= 0)
805 break;
806 fprintf(stderr,"- waiting for device -\n");
807 adb_sleep_ms(1000);
808 do_cmd(transport, serial, "wait-for-device", 0);
809 }
810
811 read_and_dump(fd);
812 ret = adb_close(fd);
813 if (ret)
814 perror("close");
815
816 return ret;
817}
818
819static int logcat(transport_type transport, char* serial, int argc, char **argv)
820{
821 char buf[4096];
822
823 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700824 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800825
826 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700827 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800828 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700829 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700830 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800831
Jeff Sharkey824d1062014-06-10 11:31:24 -0700832 if (!strcmp(argv[0], "longcat")) {
833 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800834 }
835
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800836 argc -= 1;
837 argv += 1;
838 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700839 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700840 strncat(buf, " ", sizeof(buf) - 1);
841 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800842 free(quoted);
843 }
844
845 send_shellcommand(transport, serial, buf);
846 return 0;
847}
848
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700849static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800850{
851 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700852 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800853
854 for(;;) {
855 x = adb_dirstart(x);
856 if(x == 0) return 0;
857 *x = 0;
858 ret = adb_mkdir(path, 0775);
859 *x = OS_PATH_SEPARATOR;
860 if((ret < 0) && (errno != EEXIST)) {
861 return ret;
862 }
863 x++;
864 }
865 return 0;
866}
867
Christopher Tate73779122011-04-21 12:53:28 -0700868static int backup(int argc, char** argv) {
869 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800870 char default_name[32];
871 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700872 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700873 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700874
Christopher Tatefba22972011-06-01 17:56:23 -0700875 /* find, extract, and use any -f argument */
876 for (i = 1; i < argc; i++) {
877 if (!strcmp("-f", argv[i])) {
878 if (i == argc-1) {
879 fprintf(stderr, "adb: -f passed with no filename\n");
880 return usage();
881 }
882 filename = argv[i+1];
883 for (j = i+2; j <= argc; ) {
884 argv[i++] = argv[j++];
885 }
886 argc -= 2;
887 argv[argc] = NULL;
888 }
Christopher Tate73779122011-04-21 12:53:28 -0700889 }
890
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700891 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
892 if (argc < 2) return usage();
893
Christopher Tate1e9f2392011-12-08 19:04:34 -0800894 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700895 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800896 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700897 if (outFd < 0) {
898 fprintf(stderr, "adb: unable to open file %s\n", filename);
899 return -1;
900 }
901
902 snprintf(buf, sizeof(buf), "backup");
903 for (argc--, argv++; argc; argc--, argv++) {
904 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
905 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
906 }
907
908 D("backup. filename=%s buf=%s\n", filename, buf);
909 fd = adb_connect(buf);
910 if (fd < 0) {
911 fprintf(stderr, "adb: unable to connect for backup\n");
912 adb_close(outFd);
913 return -1;
914 }
915
Christopher Tate9c829102012-01-06 15:43:03 -0800916 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700917 copy_to_file(fd, outFd);
918
919 adb_close(fd);
920 adb_close(outFd);
921 return 0;
922}
923
Christopher Tatecf5379b2011-05-17 15:52:54 -0700924static int restore(int argc, char** argv) {
925 const char* filename;
926 int fd, tarFd;
927
928 if (argc != 2) return usage();
929
930 filename = argv[1];
931 tarFd = adb_open(filename, O_RDONLY);
932 if (tarFd < 0) {
933 fprintf(stderr, "adb: unable to open file %s\n", filename);
934 return -1;
935 }
936
937 fd = adb_connect("restore:");
938 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700939 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700940 adb_close(tarFd);
941 return -1;
942 }
943
Christopher Tate9c829102012-01-06 15:43:03 -0800944 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700945 copy_to_file(tarFd, fd);
946
947 adb_close(fd);
948 adb_close(tarFd);
949 return 0;
950}
951
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800952#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
953static int top_works(const char *top)
954{
955 if (top != NULL && adb_is_absolute_host_path(top)) {
956 char path_buf[PATH_MAX];
957 snprintf(path_buf, sizeof(path_buf),
958 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
959 return access(path_buf, F_OK) == 0;
960 }
961 return 0;
962}
963
964static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
965{
966 strcpy(path_buf, indir);
967 while (1) {
968 if (top_works(path_buf)) {
969 return path_buf;
970 }
971 char *s = adb_dirstop(path_buf);
972 if (s != NULL) {
973 *s = '\0';
974 } else {
975 path_buf[0] = '\0';
976 return NULL;
977 }
978 }
979}
980
981static char *find_top(char path_buf[PATH_MAX])
982{
983 char *top = getenv("ANDROID_BUILD_TOP");
984 if (top != NULL && top[0] != '\0') {
985 if (!top_works(top)) {
986 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
987 return NULL;
988 }
989 } else {
990 top = getenv("TOP");
991 if (top != NULL && top[0] != '\0') {
992 if (!top_works(top)) {
993 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
994 return NULL;
995 }
996 } else {
997 top = NULL;
998 }
999 }
1000
1001 if (top != NULL) {
1002 /* The environment pointed to a top directory that works.
1003 */
1004 strcpy(path_buf, top);
1005 return path_buf;
1006 }
1007
1008 /* The environment didn't help. Walk up the tree from the CWD
1009 * to see if we can find the top.
1010 */
1011 char dir[PATH_MAX];
1012 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1013 if (top == NULL) {
1014 /* If the CWD isn't under a good-looking top, see if the
1015 * executable is.
1016 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +11001017 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001018 top = find_top_from(dir, path_buf);
1019 }
1020 return top;
1021}
1022
1023/* <hint> may be:
1024 * - A simple product name
1025 * e.g., "sooner"
1026TODO: debug? sooner-debug, sooner:debug?
1027 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1028 * e.g., "out/target/product/sooner"
1029 * - An absolute path to the PRODUCT_OUT dir
1030 * e.g., "/src/device/out/target/product/sooner"
1031 *
1032 * Given <hint>, try to construct an absolute path to the
1033 * ANDROID_PRODUCT_OUT dir.
1034 */
1035static const char *find_product_out_path(const char *hint)
1036{
1037 static char path_buf[PATH_MAX];
1038
1039 if (hint == NULL || hint[0] == '\0') {
1040 return NULL;
1041 }
1042
1043 /* If it's already absolute, don't bother doing any work.
1044 */
1045 if (adb_is_absolute_host_path(hint)) {
1046 strcpy(path_buf, hint);
1047 return path_buf;
1048 }
1049
1050 /* If there are any slashes in it, assume it's a relative path;
1051 * make it absolute.
1052 */
1053 if (adb_dirstart(hint) != NULL) {
1054 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1055 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1056 return NULL;
1057 }
1058 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1059 fprintf(stderr, "adb: Couldn't assemble path\n");
1060 return NULL;
1061 }
1062 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1063 strcat(path_buf, hint);
1064 return path_buf;
1065 }
1066
1067 /* It's a string without any slashes. Try to do something with it.
1068 *
1069 * Try to find the root of the build tree, and build a PRODUCT_OUT
1070 * path from there.
1071 */
1072 char top_buf[PATH_MAX];
1073 const char *top = find_top(top_buf);
1074 if (top == NULL) {
1075 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1076 return NULL;
1077 }
1078//TODO: if we have a way to indicate debug, look in out/debug/target/...
1079 snprintf(path_buf, sizeof(path_buf),
1080 "%s" OS_PATH_SEPARATOR_STR
1081 "out" OS_PATH_SEPARATOR_STR
1082 "target" OS_PATH_SEPARATOR_STR
1083 "product" OS_PATH_SEPARATOR_STR
1084 "%s", top_buf, hint);
1085 if (access(path_buf, F_OK) < 0) {
1086 fprintf(stderr, "adb: Couldn't find a product dir "
1087 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1088 return NULL;
1089 }
1090 return path_buf;
1091}
1092
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001093static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1094 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001095 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001096 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001097
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001098 while (narg > 0) {
1099 if (!strcmp(*arg, "-p")) {
1100 *show_progress = 1;
1101 } else if (!strcmp(*arg, "-a")) {
1102 *copy_attrs = 1;
1103 } else {
1104 break;
1105 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001106 ++arg;
1107 --narg;
1108 }
1109
1110 if (narg > 0) {
1111 *path1 = *arg;
1112 ++arg;
1113 --narg;
1114 }
1115
1116 if (narg > 0) {
1117 *path2 = *arg;
1118 }
1119}
1120
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001121int adb_commandline(int argc, char **argv)
1122{
1123 char buf[4096];
1124 int no_daemon = 0;
1125 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001126 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001127 int persist = 0;
1128 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001129 transport_type ttype = kTransportAny;
1130 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001131 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001132
1133 /* If defined, this should be an absolute path to
1134 * the directory containing all of the various system images
1135 * for a particular product. If not defined, and the adb
1136 * command requires this information, then the user must
1137 * specify the path using "-p".
1138 */
1139 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1140 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1141 gProductOutPath = NULL;
1142 }
1143 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1144
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001145 serial = getenv("ANDROID_SERIAL");
1146
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001147 /* Validate and assign the server port */
1148 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1149 int server_port = DEFAULT_ADB_PORT;
1150 if (server_port_str && strlen(server_port_str) > 0) {
1151 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001152 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001153 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001154 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001155 server_port_str);
1156 return usage();
1157 }
1158 }
1159
1160 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001161 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001162 if(!strcmp(argv[0],"server")) {
1163 is_server = 1;
1164 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001165 no_daemon = 1;
1166 } else if (!strcmp(argv[0], "fork-server")) {
1167 /* this is a special flag used only when the ADB client launches the ADB Server */
1168 is_daemon = 1;
1169 } else if(!strcmp(argv[0],"persist")) {
1170 persist = 1;
1171 } else if(!strncmp(argv[0], "-p", 2)) {
1172 const char *product = NULL;
1173 if (argv[0][2] == '\0') {
1174 if (argc < 2) return usage();
1175 product = argv[1];
1176 argc--;
1177 argv++;
1178 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001179 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001180 }
1181 gProductOutPath = find_product_out_path(product);
1182 if (gProductOutPath == NULL) {
1183 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1184 product);
1185 return usage();
1186 }
1187 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1188 if (isdigit(argv[0][2])) {
1189 serial = argv[0] + 2;
1190 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001191 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001192 serial = argv[1];
1193 argc--;
1194 argv++;
1195 }
1196 } else if (!strcmp(argv[0],"-d")) {
1197 ttype = kTransportUsb;
1198 } else if (!strcmp(argv[0],"-e")) {
1199 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001200 } else if (!strcmp(argv[0],"-a")) {
1201 gListenAll = 1;
1202 } else if(!strncmp(argv[0], "-H", 2)) {
1203 const char *hostname = NULL;
1204 if (argv[0][2] == '\0') {
1205 if (argc < 2) return usage();
1206 hostname = argv[1];
1207 argc--;
1208 argv++;
1209 } else {
1210 hostname = argv[0] + 2;
1211 }
1212 adb_set_tcp_name(hostname);
1213
1214 } else if(!strncmp(argv[0], "-P", 2)) {
1215 if (argv[0][2] == '\0') {
1216 if (argc < 2) return usage();
1217 server_port_str = argv[1];
1218 argc--;
1219 argv++;
1220 } else {
1221 server_port_str = argv[0] + 2;
1222 }
1223 if (strlen(server_port_str) > 0) {
1224 server_port = (int) strtol(server_port_str, NULL, 0);
1225 if (server_port <= 0 || server_port > 65535) {
1226 fprintf(stderr,
1227 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1228 server_port_str);
1229 return usage();
1230 }
1231 } else {
1232 fprintf(stderr,
1233 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1234 return usage();
1235 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001236 } else {
1237 /* out of recognized modifiers and flags */
1238 break;
1239 }
1240 argc--;
1241 argv++;
1242 }
1243
1244 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001245 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001246
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001247 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001248 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001249 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001250 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001251 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001252 }
1253 if(r) {
1254 fprintf(stderr,"* could not start server *\n");
1255 }
1256 return r;
1257 }
1258
1259top:
1260 if(argc == 0) {
1261 return usage();
1262 }
1263
1264 /* adb_connect() commands */
1265
1266 if(!strcmp(argv[0], "devices")) {
1267 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001268 char *listopt;
1269 if (argc < 2)
1270 listopt = "";
1271 else if (argc == 2 && !strcmp(argv[1], "-l"))
1272 listopt = argv[1];
1273 else {
1274 fprintf(stderr, "Usage: adb devices [-l]\n");
1275 return 1;
1276 }
1277 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001278 tmp = adb_query(buf);
1279 if(tmp) {
1280 printf("List of devices attached \n");
1281 printf("%s\n", tmp);
1282 return 0;
1283 } else {
1284 return 1;
1285 }
1286 }
1287
Mike Lockwood01c2c302010-05-24 10:44:35 -04001288 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001289 char *tmp;
1290 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001291 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001292 return 1;
1293 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001294 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1295 tmp = adb_query(buf);
1296 if(tmp) {
1297 printf("%s\n", tmp);
1298 return 0;
1299 } else {
1300 return 1;
1301 }
1302 }
1303
1304 if(!strcmp(argv[0], "disconnect")) {
1305 char *tmp;
1306 if (argc > 2) {
1307 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1308 return 1;
1309 }
1310 if (argc == 2) {
1311 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1312 } else {
1313 snprintf(buf, sizeof buf, "host:disconnect:");
1314 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001315 tmp = adb_query(buf);
1316 if(tmp) {
1317 printf("%s\n", tmp);
1318 return 0;
1319 } else {
1320 return 1;
1321 }
1322 }
1323
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001324 if (!strcmp(argv[0], "emu")) {
1325 return adb_send_emulator_command(argc, argv);
1326 }
1327
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001328 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001329 int r;
1330 int fd;
1331
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001332 char h = (argv[0][0] == 'h');
1333
1334 if (h) {
1335 printf("\x1b[41;33m");
1336 fflush(stdout);
1337 }
1338
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001339 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001340 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001341 r = interactive_shell();
1342 if (h) {
1343 printf("\x1b[0m");
1344 fflush(stdout);
1345 }
1346 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001347 }
1348
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001349 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001350 argc -= 2;
1351 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001352 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001353 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001354 strncat(buf, " ", sizeof(buf) - 1);
1355 strncat(buf, quoted, sizeof(buf) - 1);
1356 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001357 }
1358
1359 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001360 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001361 fd = adb_connect(buf);
1362 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001363 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001364 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001365 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001366 adb_close(fd);
1367 r = 0;
1368 } else {
1369 fprintf(stderr,"error: %s\n", adb_error());
1370 r = -1;
1371 }
1372
1373 if(persist) {
1374 fprintf(stderr,"\n- waiting for device -\n");
1375 adb_sleep_ms(1000);
1376 do_cmd(ttype, serial, "wait-for-device", 0);
1377 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001378 if (h) {
1379 printf("\x1b[0m");
1380 fflush(stdout);
1381 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001382 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001383 return r;
1384 }
1385 }
1386 }
1387
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001388 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1389 int exec_in = !strcmp(argv[0], "exec-in");
1390 int fd;
1391
1392 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1393 argc -= 2;
1394 argv += 2;
1395 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001396 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001397 strncat(buf, " ", sizeof(buf) - 1);
1398 strncat(buf, quoted, sizeof(buf) - 1);
1399 free(quoted);
1400 }
1401
1402 fd = adb_connect(buf);
1403 if (fd < 0) {
1404 fprintf(stderr, "error: %s\n", adb_error());
1405 return -1;
1406 }
1407
1408 if (exec_in) {
1409 copy_to_file(STDIN_FILENO, fd);
1410 } else {
1411 copy_to_file(fd, STDOUT_FILENO);
1412 }
1413
1414 adb_close(fd);
1415 return 0;
1416 }
1417
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001418 if(!strcmp(argv[0], "kill-server")) {
1419 int fd;
1420 fd = _adb_connect("host:kill");
1421 if(fd == -1) {
1422 fprintf(stderr,"* server not running *\n");
1423 return 1;
1424 }
1425 return 0;
1426 }
1427
Doug Zongker6b217ed2012-01-09 14:54:53 -08001428 if(!strcmp(argv[0], "sideload")) {
1429 if(argc != 2) return usage();
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001430 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001431 return 1;
1432 } else {
1433 return 0;
1434 }
1435 }
1436
Mike Lockwood26b88e32009-08-24 15:58:40 -07001437 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001438 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001439 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001440 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001441 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001442 if (!strcmp(argv[0], "reboot-bootloader"))
1443 snprintf(command, sizeof(command), "reboot:bootloader");
1444 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001445 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001446 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001447 snprintf(command, sizeof(command), "%s:", argv[0]);
1448 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001449 if(fd >= 0) {
1450 read_and_dump(fd);
1451 adb_close(fd);
1452 return 0;
1453 }
1454 fprintf(stderr,"error: %s\n", adb_error());
1455 return 1;
1456 }
1457
Mike Lockwood78589f32009-09-03 14:54:58 -04001458 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001459 if (argc != 1) return usage();
1460 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001461 return 0;
1462 }
1463
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001464 /* adb_command() wrapper commands */
1465
1466 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1467 char* service = argv[0];
1468 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1469 if (ttype == kTransportUsb) {
1470 service = "wait-for-usb";
1471 } else if (ttype == kTransportLocal) {
1472 service = "wait-for-local";
1473 } else {
1474 service = "wait-for-any";
1475 }
1476 }
1477
1478 format_host_command(buf, sizeof buf, service, ttype, serial);
1479
1480 if (adb_command(buf)) {
1481 D("failure: %s *\n",adb_error());
1482 fprintf(stderr,"error: %s\n", adb_error());
1483 return 1;
1484 }
1485
1486 /* Allow a command to be run after wait-for-device,
1487 * e.g. 'adb wait-for-device shell'.
1488 */
1489 if(argc > 1) {
1490 argc--;
1491 argv++;
1492 goto top;
1493 }
1494 return 0;
1495 }
1496
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001497 if(!strcmp(argv[0], "forward") ||
1498 !strcmp(argv[0], "reverse"))
1499 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001500 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001501 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001502 char remove = 0;
1503 char remove_all = 0;
1504 char list = 0;
1505 char no_rebind = 0;
1506
1507 // Parse options here.
1508 while (argc > 1 && argv[1][0] == '-') {
1509 if (!strcmp(argv[1], "--list"))
1510 list = 1;
1511 else if (!strcmp(argv[1], "--remove"))
1512 remove = 1;
1513 else if (!strcmp(argv[1], "--remove-all"))
1514 remove_all = 1;
1515 else if (!strcmp(argv[1], "--no-rebind"))
1516 no_rebind = 1;
1517 else {
1518 return usage();
1519 }
1520 argc--;
1521 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001522 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001523
1524 // Ensure we can only use one option at a time.
1525 if (list + remove + remove_all + no_rebind > 1) {
1526 return usage();
1527 }
1528
1529 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001530 if (reverse) {
1531 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001532 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001533 if (serial) {
1534 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1535 serial);
1536 } else if (ttype == kTransportUsb) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1538 } else if (ttype == kTransportLocal) {
1539 snprintf(host_prefix, sizeof host_prefix, "host-local");
1540 } else {
1541 snprintf(host_prefix, sizeof host_prefix, "host");
1542 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001543 }
1544
1545 // Implement forward --list
1546 if (list) {
1547 if (argc != 1)
1548 return usage();
1549 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1550 char* forwards = adb_query(buf);
1551 if (forwards == NULL) {
1552 fprintf(stderr, "error: %s\n", adb_error());
1553 return 1;
1554 }
1555 printf("%s", forwards);
1556 free(forwards);
1557 return 0;
1558 }
1559
1560 // Implement forward --remove-all
1561 else if (remove_all) {
1562 if (argc != 1)
1563 return usage();
1564 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1565 }
1566
1567 // Implement forward --remove <local>
1568 else if (remove) {
1569 if (argc != 2)
1570 return usage();
1571 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1572 }
1573 // Or implement one of:
1574 // forward <local> <remote>
1575 // forward --no-rebind <local> <remote>
1576 else
1577 {
1578 if (argc != 3)
1579 return usage();
1580 const char* command = no_rebind ? "forward:norebind:" : "forward";
1581 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1582 }
1583
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001584 if(adb_command(buf)) {
1585 fprintf(stderr,"error: %s\n", adb_error());
1586 return 1;
1587 }
1588 return 0;
1589 }
1590
1591 /* do_sync_*() commands */
1592
1593 if(!strcmp(argv[0], "ls")) {
1594 if(argc != 2) return usage();
1595 return do_sync_ls(argv[1]);
1596 }
1597
1598 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001599 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001600 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001601 const char* lpath = NULL, *rpath = NULL;
1602
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001603 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001604
1605 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001606 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001607 }
1608
1609 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001610 }
1611
1612 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001613 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001614 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001615 const char* rpath = NULL, *lpath = ".";
1616
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001617 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001618
1619 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001620 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001621 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001622
1623 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001624 }
1625
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001626 if (!strcmp(argv[0], "install")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001627 if (argc < 2) return usage();
1628 return install_app(ttype, serial, argc, argv);
1629 }
1630
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001631 if (!strcmp(argv[0], "install-multiple")) {
1632 if (argc < 2) return usage();
1633 return install_multiple_app(ttype, serial, argc, argv);
1634 }
1635
1636 if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001637 if (argc < 2) return usage();
1638 return uninstall_app(ttype, serial, argc, argv);
1639 }
1640
1641 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001642 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001643 int listonly = 0;
1644
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001645 int ret;
1646 if(argc < 2) {
1647 /* No local path was specified. */
1648 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001649 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1650 listonly = 1;
1651 if (argc == 3) {
1652 srcarg = argv[2];
1653 } else {
1654 srcarg = NULL;
1655 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001656 } else if(argc == 2) {
1657 /* A local path or "android"/"data" arg was specified. */
1658 srcarg = argv[1];
1659 } else {
1660 return usage();
1661 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001662 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001663 if(ret != 0) return usage();
1664
1665 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001666 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001667 if(ret == 0 && vendor_srcpath != NULL)
1668 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001669 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001670 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001671
1672 free(android_srcpath);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001673 free(vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001674 free(data_srcpath);
1675 return ret;
1676 }
1677
1678 /* passthrough commands */
1679
1680 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001681 !strcmp(argv[0],"get-serialno") ||
1682 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001683 {
1684 char *tmp;
1685
1686 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1687 tmp = adb_query(buf);
1688 if(tmp) {
1689 printf("%s\n", tmp);
1690 return 0;
1691 } else {
1692 return 1;
1693 }
1694 }
1695
1696 /* other commands */
1697
1698 if(!strcmp(argv[0],"status-window")) {
1699 status_window(ttype, serial);
1700 return 0;
1701 }
1702
Christopher Tate7b9b5162011-11-30 13:00:33 -08001703 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001704 return logcat(ttype, serial, argc, argv);
1705 }
1706
1707 if(!strcmp(argv[0],"ppp")) {
1708 return ppp(argc, argv);
1709 }
1710
1711 if (!strcmp(argv[0], "start-server")) {
1712 return adb_connect("host:start-server");
1713 }
1714
Christopher Tate73779122011-04-21 12:53:28 -07001715 if (!strcmp(argv[0], "backup")) {
1716 return backup(argc, argv);
1717 }
1718
Christopher Tatecf5379b2011-05-17 15:52:54 -07001719 if (!strcmp(argv[0], "restore")) {
1720 return restore(argc, argv);
1721 }
1722
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001723 if (!strcmp(argv[0], "jdwp")) {
1724 int fd = adb_connect("jdwp");
1725 if (fd >= 0) {
1726 read_and_dump(fd);
1727 adb_close(fd);
1728 return 0;
1729 } else {
1730 fprintf(stderr, "error: %s\n", adb_error());
1731 return -1;
1732 }
1733 }
1734
1735 /* "adb /?" is a common idiom under Windows */
1736 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1737 help();
1738 return 0;
1739 }
1740
1741 if(!strcmp(argv[0], "version")) {
1742 version(stdout);
1743 return 0;
1744 }
1745
1746 usage();
1747 return 1;
1748}
1749
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001750#define MAX_ARGV_LENGTH 16
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001751static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1752{
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001753 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001754 int argc;
1755 va_list ap;
1756
1757 va_start(ap, cmd);
1758 argc = 0;
1759
1760 if (serial) {
1761 argv[argc++] = "-s";
1762 argv[argc++] = serial;
1763 } else if (ttype == kTransportUsb) {
1764 argv[argc++] = "-d";
1765 } else if (ttype == kTransportLocal) {
1766 argv[argc++] = "-e";
1767 }
1768
1769 argv[argc++] = cmd;
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001770 while(argc < MAX_ARGV_LENGTH &&
1771 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1772 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001773 va_end(ap);
1774
1775#if 0
1776 int n;
1777 fprintf(stderr,"argc = %d\n",argc);
1778 for(n = 0; n < argc; n++) {
1779 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1780 }
1781#endif
1782
1783 return adb_commandline(argc, argv);
1784}
1785
1786int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001787 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001788{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001789 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1790 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001791
1792 if(srcarg == NULL) {
1793 android_srcdir = product_file("system");
1794 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001795 vendor_srcdir = product_file("vendor");
1796 /* Check if vendor partition exists */
1797 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1798 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001799 } else {
1800 /* srcarg may be "data", "system" or NULL.
1801 * if srcarg is NULL, then both data and system are synced
1802 */
1803 if(strcmp(srcarg, "system") == 0) {
1804 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001805 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001806 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001807 } else if(strcmp(srcarg, "vendor") == 0) {
1808 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001809 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001810 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001811 */
1812 return 1;
1813 }
1814 }
1815
1816 if(android_srcdir_out != NULL)
1817 *android_srcdir_out = android_srcdir;
1818 else
1819 free(android_srcdir);
1820
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001821 if(vendor_srcdir_out != NULL)
1822 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001823 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001824 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001825
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001826 if(data_srcdir_out != NULL)
1827 *data_srcdir_out = data_srcdir;
1828 else
1829 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001830 return 0;
1831}
1832
1833static int pm_command(transport_type transport, char* serial,
1834 int argc, char** argv)
1835{
1836 char buf[4096];
1837
1838 snprintf(buf, sizeof(buf), "shell:pm");
1839
1840 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001841 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001842 strncat(buf, " ", sizeof(buf) - 1);
1843 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001844 free(quoted);
1845 }
1846
1847 send_shellcommand(transport, serial, buf);
1848 return 0;
1849}
1850
1851int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1852{
1853 /* if the user choose the -k option, we refuse to do it until devices are
1854 out with the option to uninstall the remaining data somehow (adb/ui) */
1855 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1856 {
1857 printf(
1858 "The -k option uninstalls the application while retaining the data/cache.\n"
1859 "At the moment, there is no way to remove the remaining data.\n"
1860 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1861 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1862 return -1;
1863 }
1864
1865 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1866 return pm_command(transport, serial, argc, argv);
1867}
1868
1869static int delete_file(transport_type transport, char* serial, char* filename)
1870{
1871 char buf[4096];
1872 char* quoted;
1873
Jeff Sharkeyce474652014-09-09 12:38:30 -07001874 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001875 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001876 strncat(buf, quoted, sizeof(buf)-1);
1877 free(quoted);
1878
1879 send_shellcommand(transport, serial, buf);
1880 return 0;
1881}
1882
Kenny Root3802c992011-08-05 11:19:45 -07001883static const char* get_basename(const char* filename)
1884{
1885 const char* basename = adb_dirstop(filename);
1886 if (basename) {
1887 basename++;
1888 return basename;
1889 } else {
1890 return filename;
1891 }
1892}
1893
Kenny Root3802c992011-08-05 11:19:45 -07001894int install_app(transport_type transport, char* serial, int argc, char** argv)
1895{
1896 static const char *const DATA_DEST = "/data/local/tmp/%s";
1897 static const char *const SD_DEST = "/sdcard/tmp/%s";
1898 const char* where = DATA_DEST;
Kenny Root3802c992011-08-05 11:19:45 -07001899 int i;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001900 struct stat sb;
Kenny Root3802c992011-08-05 11:19:45 -07001901
1902 for (i = 1; i < argc; i++) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001903 if (!strcmp(argv[i], "-s")) {
Kenny Root3802c992011-08-05 11:19:45 -07001904 where = SD_DEST;
1905 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001906 }
1907
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001908 // Find last APK argument.
1909 // All other arguments passed through verbatim.
1910 int last_apk = -1;
1911 for (i = argc - 1; i >= 0; i--) {
1912 char* file = argv[i];
1913 char* dot = strrchr(file, '.');
1914 if (dot && !strcasecmp(dot, ".apk")) {
1915 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1916 fprintf(stderr, "Invalid APK file: %s\n", file);
1917 return -1;
1918 }
1919
1920 last_apk = i;
1921 break;
1922 }
Kenny Root3802c992011-08-05 11:19:45 -07001923 }
1924
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001925 if (last_apk == -1) {
1926 fprintf(stderr, "Missing APK file\n");
1927 return -1;
Kenny Root3802c992011-08-05 11:19:45 -07001928 }
1929
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001930 char* apk_file = argv[last_apk];
1931 char apk_dest[PATH_MAX];
Kenny Root3802c992011-08-05 11:19:45 -07001932 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001933 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001934 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001935 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001936 } else {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001937 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root3802c992011-08-05 11:19:45 -07001938 }
1939
1940 pm_command(transport, serial, argc, argv);
1941
Kenny Root58d5f222012-03-26 16:14:02 -07001942cleanup_apk:
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001943 delete_file(transport, serial, apk_dest);
1944 return err;
1945}
1946
1947int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1948{
1949 char buf[1024];
1950 int i;
1951 struct stat sb;
1952 unsigned long long total_size = 0;
1953
1954 // Find all APK arguments starting at end.
1955 // All other arguments passed through verbatim.
1956 int first_apk = -1;
1957 for (i = argc - 1; i >= 0; i--) {
1958 char* file = argv[i];
1959 char* dot = strrchr(file, '.');
1960 if (dot && !strcasecmp(dot, ".apk")) {
1961 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1962 fprintf(stderr, "Invalid APK file: %s\n", file);
1963 return -1;
1964 }
1965
1966 total_size += sb.st_size;
1967 first_apk = i;
1968 } else {
1969 break;
1970 }
Kenny Root3802c992011-08-05 11:19:45 -07001971 }
1972
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001973 if (first_apk == -1) {
1974 fprintf(stderr, "Missing APK file\n");
1975 return 1;
1976 }
Kenny Root3802c992011-08-05 11:19:45 -07001977
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001978 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1979 for (i = 1; i < first_apk; i++) {
1980 char *quoted = escape_arg(argv[i]);
1981 strncat(buf, " ", sizeof(buf) - 1);
1982 strncat(buf, quoted, sizeof(buf) - 1);
1983 free(quoted);
1984 }
1985
1986 // Create install session
1987 int fd = adb_connect(buf);
1988 if (fd < 0) {
1989 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1990 return -1;
1991 }
1992 read_status_line(fd, buf, sizeof(buf));
1993 adb_close(fd);
1994
1995 int session_id = -1;
1996 if (!strncmp("Success", buf, 7)) {
1997 char* start = strrchr(buf, '[');
1998 char* end = strrchr(buf, ']');
1999 if (start && end) {
2000 *end = '\0';
2001 session_id = strtol(start + 1, NULL, 10);
2002 }
2003 }
2004 if (session_id < 0) {
2005 fprintf(stderr, "Failed to create session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002006 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002007 return -1;
2008 }
2009
2010 // Valid session, now stream the APKs
2011 int success = 1;
2012 for (i = first_apk; i < argc; i++) {
2013 char* file = argv[i];
2014 if (stat(file, &sb) == -1) {
2015 fprintf(stderr, "Failed to stat %s\n", file);
2016 success = 0;
2017 goto finalize_session;
2018 }
2019
2020 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkey4a7ddb62014-07-14 13:57:54 -07002021 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002022
2023 int localFd = adb_open(file, O_RDONLY);
2024 if (localFd < 0) {
2025 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2026 success = 0;
2027 goto finalize_session;
2028 }
2029
2030 int remoteFd = adb_connect(buf);
2031 if (remoteFd < 0) {
2032 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2033 adb_close(localFd);
2034 success = 0;
2035 goto finalize_session;
2036 }
2037
2038 copy_to_file(localFd, remoteFd);
2039 read_status_line(remoteFd, buf, sizeof(buf));
2040
2041 adb_close(localFd);
2042 adb_close(remoteFd);
2043
2044 if (strncmp("Success", buf, 7)) {
2045 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate29721da2014-07-14 16:45:13 -07002046 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002047 success = 0;
2048 goto finalize_session;
2049 }
2050 }
2051
2052finalize_session:
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002053 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002054 if (success) {
2055 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2056 } else {
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002057 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002058 }
2059
2060 fd = adb_connect(buf);
2061 if (fd < 0) {
2062 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2063 return -1;
2064 }
2065 read_status_line(fd, buf, sizeof(buf));
2066 adb_close(fd);
2067
2068 if (!strncmp("Success", buf, 7)) {
Christopher Tate29721da2014-07-14 16:45:13 -07002069 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002070 return 0;
2071 } else {
2072 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002073 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002074 return -1;
2075 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08002076}