blob: 23e9ea4f5a00c2e3ed8609a3f49f462a31b7e260 [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
Yabin Cui6704a3c2014-11-17 14:48:25 -080032#if !defined(_WIN32)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080033#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
Yabin Cui6704a3c2014-11-17 14:48:25 -0800238#if defined(_WIN32)
239
240// Windows does not have <termio.h>.
241static void stdin_raw_init(int fd) {
242
243}
244
245static void stdin_raw_restore(int fd) {
246
247}
248
249#else
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800250static struct termios tio_save;
251
252static void stdin_raw_init(int fd)
253{
254 struct termios tio;
255
256 if(tcgetattr(fd, &tio)) return;
257 if(tcgetattr(fd, &tio_save)) return;
258
259 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
260
261 /* no timeout but request at least one character per read */
262 tio.c_cc[VTIME] = 0;
263 tio.c_cc[VMIN] = 1;
264
265 tcsetattr(fd, TCSANOW, &tio);
266 tcflush(fd, TCIFLUSH);
267}
268
269static void stdin_raw_restore(int fd)
270{
271 tcsetattr(fd, TCSANOW, &tio_save);
272 tcflush(fd, TCIFLUSH);
273}
274#endif
275
276static void read_and_dump(int fd)
277{
278 char buf[4096];
279 int len;
280
281 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700282 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800283 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700284 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800285 if(len == 0) {
286 break;
287 }
288
289 if(len < 0) {
290 if(errno == EINTR) continue;
291 break;
292 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400293 fwrite(buf, 1, len, stdout);
294 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800295 }
296}
297
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700298static void read_status_line(int fd, char* buf, size_t count)
299{
300 count--;
301 while (count > 0) {
302 int len = adb_read(fd, buf, count);
303 if (len == 0) {
304 break;
305 } else if (len < 0) {
306 if (errno == EINTR) continue;
307 break;
308 }
309
310 buf += len;
311 count -= len;
312 }
313 *buf = '\0';
314}
315
Christopher Tate73779122011-04-21 12:53:28 -0700316static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700317 const size_t BUFSIZE = 32 * 1024;
318 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700319 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700320 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700321
322 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cui6704a3c2014-11-17 14:48:25 -0800323
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700324 if (inFd == STDIN_FILENO) {
325 stdin_raw_init(STDIN_FILENO);
326 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800327
Christopher Tate73779122011-04-21 12:53:28 -0700328 for (;;) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700329 if (inFd == STDIN_FILENO) {
330 len = unix_read(inFd, buf, BUFSIZE);
331 } else {
332 len = adb_read(inFd, buf, BUFSIZE);
333 }
Christopher Tate73779122011-04-21 12:53:28 -0700334 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700335 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700336 break;
337 }
338 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700339 if (errno == EINTR) {
340 D("copy_to_file() : EINTR, retrying\n");
341 continue;
342 }
Christopher Tate73779122011-04-21 12:53:28 -0700343 D("copy_to_file() : error %d\n", errno);
344 break;
345 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700346 if (outFd == STDOUT_FILENO) {
347 fwrite(buf, 1, len, stdout);
348 fflush(stdout);
349 } else {
350 adb_write(outFd, buf, len);
351 }
Christopher Tatefba22972011-06-01 17:56:23 -0700352 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700353 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800354
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700355 if (inFd == STDIN_FILENO) {
356 stdin_raw_restore(STDIN_FILENO);
357 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800358
Christopher Tatefba22972011-06-01 17:56:23 -0700359 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700360 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700361}
362
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800363static void *stdin_read_thread(void *x)
364{
365 int fd, fdi;
366 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800367 int r, n;
368 int state = 0;
369
370 int *fds = (int*) x;
371 fd = fds[0];
372 fdi = fds[1];
373 free(fds);
374
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800375 for(;;) {
376 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700377 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800378 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700379 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800380 if(r == 0) break;
381 if(r < 0) {
382 if(errno == EINTR) continue;
383 break;
384 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400385 for(n = 0; n < r; n++){
386 switch(buf[n]) {
387 case '\n':
388 state = 1;
389 break;
390 case '\r':
391 state = 1;
392 break;
393 case '~':
394 if(state == 1) state++;
395 break;
396 case '.':
397 if(state == 2) {
398 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400399 stdin_raw_restore(fdi);
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400400 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800401 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400402 default:
403 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800404 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800405 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800406 r = adb_write(fd, buf, r);
407 if(r <= 0) {
408 break;
409 }
410 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800411 return 0;
412}
413
414int interactive_shell(void)
415{
416 adb_thread_t thr;
417 int fdi, fd;
418 int *fds;
419
420 fd = adb_connect("shell:");
421 if(fd < 0) {
422 fprintf(stderr,"error: %s\n", adb_error());
423 return 1;
424 }
425 fdi = 0; //dup(0);
426
427 fds = malloc(sizeof(int) * 2);
428 fds[0] = fd;
429 fds[1] = fdi;
430
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800431 stdin_raw_init(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800432 adb_thread_create(&thr, stdin_read_thread, fds);
433 read_and_dump(fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800434 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800435 return 0;
436}
437
438
439static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
440{
441 if (serial) {
442 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
443 } else {
444 const char* prefix = "host";
445 if (ttype == kTransportUsb)
446 prefix = "host-usb";
447 else if (ttype == kTransportLocal)
448 prefix = "host-local";
449
450 snprintf(buffer, buflen, "%s:%s", prefix, command);
451 }
452}
453
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100454int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800455 unsigned progress)
456{
457 char buf[4096];
458 unsigned total;
459 int fd;
460 const unsigned char *ptr;
461
462 sprintf(buf,"%s:%d", service, sz);
463 fd = adb_connect(buf);
464 if(fd < 0) {
465 fprintf(stderr,"error: %s\n", adb_error());
466 return -1;
467 }
468
469 int opt = CHUNK_SIZE;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700470 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800471
472 total = sz;
473 ptr = data;
474
475 if(progress) {
476 char *x = strrchr(service, ':');
477 if(x) service = x + 1;
478 }
479
480 while(sz > 0) {
481 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
482 if(writex(fd, ptr, xfer)) {
483 adb_status(fd);
484 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
485 return -1;
486 }
487 sz -= xfer;
488 ptr += xfer;
489 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100490 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800491 fflush(stdout);
492 }
493 }
494 if(progress) {
495 printf("\n");
496 }
497
498 if(readx(fd, buf, 4)){
499 fprintf(stderr,"* error reading response *\n");
500 adb_close(fd);
501 return -1;
502 }
503 if(memcmp(buf, "OKAY", 4)) {
504 buf[4] = 0;
505 fprintf(stderr,"* error response '%s' *\n", buf);
506 adb_close(fd);
507 return -1;
508 }
509
510 adb_close(fd);
511 return 0;
512}
513
514
515int adb_download(const char *service, const char *fn, unsigned progress)
516{
517 void *data;
518 unsigned sz;
519
520 data = load_file(fn, &sz);
521 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100522 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800523 return -1;
524 }
525
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100526 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800527 free(data);
528 return status;
529}
530
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700531#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
532
533/*
534 * The sideload-host protocol serves the data in a file (given on the
535 * command line) to the client, using a simple protocol:
536 *
537 * - The connect message includes the total number of bytes in the
538 * file and a block size chosen by us.
539 *
540 * - The other side sends the desired block number as eight decimal
541 * digits (eg "00000023" for block 23). Blocks are numbered from
542 * zero.
543 *
544 * - We send back the data of the requested block. The last block is
545 * likely to be partial; when the last block is requested we only
546 * send the part of the block that exists, it's not padded up to the
547 * block size.
548 *
549 * - When the other side sends "DONEDONE" instead of a block number,
550 * we hang up.
551 */
552int adb_sideload_host(const char* fn) {
553 uint8_t* data;
554 unsigned sz;
555 size_t xfer = 0;
556 int status;
557
558 printf("loading: '%s'", fn);
559 fflush(stdout);
560 data = load_file(fn, &sz);
561 if (data == 0) {
562 printf("\n");
563 fprintf(stderr, "* cannot read '%s' *\n", fn);
564 return -1;
565 }
566
567 char buf[100];
568 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
569 int fd = adb_connect(buf);
570 if (fd < 0) {
571 // Try falling back to the older sideload method. Maybe this
572 // is an older device that doesn't support sideload-host.
573 printf("\n");
574 status = adb_download_buffer("sideload", fn, data, sz, 1);
575 goto done;
576 }
577
578 int opt = SIDELOAD_HOST_BLOCK_SIZE;
579 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
580
581 int last_percent = -1;
Doug Zongkera27ee6c2014-07-07 15:28:43 -0700582 for (;;) {
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700583 if (readx(fd, buf, 8)) {
584 fprintf(stderr, "* failed to read command: %s\n", adb_error());
585 status = -1;
586 goto done;
587 }
588
589 if (strncmp("DONEDONE", buf, 8) == 0) {
590 status = 0;
591 break;
592 }
593
594 buf[8] = '\0';
595 int block = strtol(buf, NULL, 10);
596
597 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
598 if (offset >= sz) {
599 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
600 status = -1;
601 goto done;
602 }
603 uint8_t* start = data + offset;
604 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
605 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
606 if (offset_end > sz) {
607 to_write = sz - offset;
608 }
609
610 if(writex(fd, start, to_write)) {
611 adb_status(fd);
612 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
613 status = -1;
614 goto done;
615 }
616 xfer += to_write;
617
618 // For normal OTA packages, we expect to transfer every byte
619 // twice, plus a bit of overhead (one read during
620 // verification, one read of each byte for installation, plus
621 // extra access to things like the zip central directory).
622 // This estimate of the completion becomes 100% when we've
623 // transferred ~2.13 (=100/47) times the package size.
624 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
625 if (percent != last_percent) {
626 printf("\rserving: '%s' (~%d%%) ", fn, percent);
627 fflush(stdout);
628 last_percent = percent;
629 }
630 }
631
Colin Cross2328bea2014-07-07 14:12:41 -0700632 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700633
634 done:
635 if (fd >= 0) adb_close(fd);
636 free(data);
637 return status;
638}
639
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800640static void status_window(transport_type ttype, const char* serial)
641{
642 char command[4096];
643 char *state = 0;
644 char *laststate = 0;
645
646 /* silence stderr */
647#ifdef _WIN32
648 /* XXX: TODO */
649#else
650 int fd;
651 fd = unix_open("/dev/null", O_WRONLY);
652 dup2(fd, 2);
653 adb_close(fd);
654#endif
655
656 format_host_command(command, sizeof command, "get-state", ttype, serial);
657
658 for(;;) {
659 adb_sleep_ms(250);
660
661 if(state) {
662 free(state);
663 state = 0;
664 }
665
666 state = adb_query(command);
667
668 if(state) {
669 if(laststate && !strcmp(state,laststate)){
670 continue;
671 } else {
672 if(laststate) free(laststate);
673 laststate = strdup(state);
674 }
675 }
676
677 printf("%c[2J%c[2H", 27, 27);
678 printf("Android Debug Bridge\n");
679 printf("State: %s\n", state ? state : "offline");
680 fflush(stdout);
681 }
682}
683
Brian Carlstrom529fca82014-08-05 22:51:18 -0700684static int should_escape(const char c)
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700685{
686 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
687}
688
689/* Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700690static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800691{
692 const char *ts;
693 size_t alloc_len;
694 char *ret;
695 char *dest;
696
Jeff Sharkey026d9622014-06-10 16:22:17 -0700697 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700698 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800699 alloc_len++;
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700700 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800701 alloc_len++;
702 }
703 }
704
Jeff Sharkey026d9622014-06-10 16:22:17 -0700705 if (alloc_len == 0) {
706 // Preserve empty arguments
707 ret = (char *) malloc(3);
708 ret[0] = '\"';
709 ret[1] = '\"';
710 ret[2] = '\0';
711 return ret;
712 }
713
Jeff Sharkey824d1062014-06-10 11:31:24 -0700714 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800715 dest = ret;
716
Jeff Sharkey824d1062014-06-10 11:31:24 -0700717 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyde7cad82014-08-05 16:53:08 -0700718 if (should_escape(*ts)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800719 *dest++ = '\\';
720 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800721 *dest++ = *ts;
722 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800723 *dest++ = '\0';
724
725 return ret;
726}
727
728/**
729 * Run ppp in "notty" mode against a resource listed as the first parameter
730 * eg:
731 *
732 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
733 *
734 */
735int ppp(int argc, char **argv)
736{
Yabin Cui2fa43212014-11-11 09:24:11 -0800737#if defined(_WIN32)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800738 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
739 return -1;
740#else
741 char *adb_service_name;
742 pid_t pid;
743 int fd;
744
745 if (argc < 2) {
746 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
747 argv[0]);
748
749 return 1;
750 }
751
752 adb_service_name = argv[1];
753
754 fd = adb_connect(adb_service_name);
755
756 if(fd < 0) {
757 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
758 adb_service_name, adb_error());
759 return 1;
760 }
761
762 pid = fork();
763
764 if (pid < 0) {
765 perror("from fork()");
766 return 1;
767 } else if (pid == 0) {
768 int err;
769 int i;
770 const char **ppp_args;
771
772 // copy args
773 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
774 ppp_args[0] = "pppd";
775 for (i = 2 ; i < argc ; i++) {
776 //argv[2] and beyond become ppp_args[1] and beyond
777 ppp_args[i - 1] = argv[i];
778 }
779 ppp_args[i-1] = NULL;
780
781 // child side
782
783 dup2(fd, STDIN_FILENO);
784 dup2(fd, STDOUT_FILENO);
785 adb_close(STDERR_FILENO);
786 adb_close(fd);
787
788 err = execvp("pppd", (char * const *)ppp_args);
789
790 if (err < 0) {
791 perror("execing pppd");
792 }
793 exit(-1);
794 } else {
795 // parent side
796
797 adb_close(fd);
798 return 0;
799 }
Yabin Cui2fa43212014-11-11 09:24:11 -0800800#endif /* !defined(_WIN32) */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800801}
802
803static int send_shellcommand(transport_type transport, char* serial, char* buf)
804{
805 int fd, ret;
806
807 for(;;) {
808 fd = adb_connect(buf);
809 if(fd >= 0)
810 break;
811 fprintf(stderr,"- waiting for device -\n");
812 adb_sleep_ms(1000);
813 do_cmd(transport, serial, "wait-for-device", 0);
814 }
815
816 read_and_dump(fd);
817 ret = adb_close(fd);
818 if (ret)
819 perror("close");
820
821 return ret;
822}
823
824static int logcat(transport_type transport, char* serial, int argc, char **argv)
825{
826 char buf[4096];
827
828 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700829 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800830
831 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700832 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800833 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700834 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700835 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800836
Jeff Sharkey824d1062014-06-10 11:31:24 -0700837 if (!strcmp(argv[0], "longcat")) {
838 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800839 }
840
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800841 argc -= 1;
842 argv += 1;
843 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700844 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700845 strncat(buf, " ", sizeof(buf) - 1);
846 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800847 free(quoted);
848 }
849
850 send_shellcommand(transport, serial, buf);
851 return 0;
852}
853
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700854static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800855{
856 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700857 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800858
859 for(;;) {
860 x = adb_dirstart(x);
861 if(x == 0) return 0;
862 *x = 0;
863 ret = adb_mkdir(path, 0775);
864 *x = OS_PATH_SEPARATOR;
865 if((ret < 0) && (errno != EEXIST)) {
866 return ret;
867 }
868 x++;
869 }
870 return 0;
871}
872
Christopher Tate73779122011-04-21 12:53:28 -0700873static int backup(int argc, char** argv) {
874 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800875 char default_name[32];
876 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700877 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700878 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700879
Christopher Tatefba22972011-06-01 17:56:23 -0700880 /* find, extract, and use any -f argument */
881 for (i = 1; i < argc; i++) {
882 if (!strcmp("-f", argv[i])) {
883 if (i == argc-1) {
884 fprintf(stderr, "adb: -f passed with no filename\n");
885 return usage();
886 }
887 filename = argv[i+1];
888 for (j = i+2; j <= argc; ) {
889 argv[i++] = argv[j++];
890 }
891 argc -= 2;
892 argv[argc] = NULL;
893 }
Christopher Tate73779122011-04-21 12:53:28 -0700894 }
895
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700896 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
897 if (argc < 2) return usage();
898
Christopher Tate1e9f2392011-12-08 19:04:34 -0800899 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700900 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800901 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700902 if (outFd < 0) {
903 fprintf(stderr, "adb: unable to open file %s\n", filename);
904 return -1;
905 }
906
907 snprintf(buf, sizeof(buf), "backup");
908 for (argc--, argv++; argc; argc--, argv++) {
909 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
910 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
911 }
912
913 D("backup. filename=%s buf=%s\n", filename, buf);
914 fd = adb_connect(buf);
915 if (fd < 0) {
916 fprintf(stderr, "adb: unable to connect for backup\n");
917 adb_close(outFd);
918 return -1;
919 }
920
Christopher Tate9c829102012-01-06 15:43:03 -0800921 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700922 copy_to_file(fd, outFd);
923
924 adb_close(fd);
925 adb_close(outFd);
926 return 0;
927}
928
Christopher Tatecf5379b2011-05-17 15:52:54 -0700929static int restore(int argc, char** argv) {
930 const char* filename;
931 int fd, tarFd;
932
933 if (argc != 2) return usage();
934
935 filename = argv[1];
936 tarFd = adb_open(filename, O_RDONLY);
937 if (tarFd < 0) {
938 fprintf(stderr, "adb: unable to open file %s\n", filename);
939 return -1;
940 }
941
942 fd = adb_connect("restore:");
943 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700944 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700945 adb_close(tarFd);
946 return -1;
947 }
948
Christopher Tate9c829102012-01-06 15:43:03 -0800949 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700950 copy_to_file(tarFd, fd);
951
952 adb_close(fd);
953 adb_close(tarFd);
954 return 0;
955}
956
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800957#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
958static int top_works(const char *top)
959{
960 if (top != NULL && adb_is_absolute_host_path(top)) {
961 char path_buf[PATH_MAX];
962 snprintf(path_buf, sizeof(path_buf),
963 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
964 return access(path_buf, F_OK) == 0;
965 }
966 return 0;
967}
968
969static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
970{
971 strcpy(path_buf, indir);
972 while (1) {
973 if (top_works(path_buf)) {
974 return path_buf;
975 }
976 char *s = adb_dirstop(path_buf);
977 if (s != NULL) {
978 *s = '\0';
979 } else {
980 path_buf[0] = '\0';
981 return NULL;
982 }
983 }
984}
985
986static char *find_top(char path_buf[PATH_MAX])
987{
988 char *top = getenv("ANDROID_BUILD_TOP");
989 if (top != NULL && top[0] != '\0') {
990 if (!top_works(top)) {
991 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
992 return NULL;
993 }
994 } else {
995 top = getenv("TOP");
996 if (top != NULL && top[0] != '\0') {
997 if (!top_works(top)) {
998 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
999 return NULL;
1000 }
1001 } else {
1002 top = NULL;
1003 }
1004 }
1005
1006 if (top != NULL) {
1007 /* The environment pointed to a top directory that works.
1008 */
1009 strcpy(path_buf, top);
1010 return path_buf;
1011 }
1012
1013 /* The environment didn't help. Walk up the tree from the CWD
1014 * to see if we can find the top.
1015 */
1016 char dir[PATH_MAX];
1017 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1018 if (top == NULL) {
1019 /* If the CWD isn't under a good-looking top, see if the
1020 * executable is.
1021 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +11001022 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001023 top = find_top_from(dir, path_buf);
1024 }
1025 return top;
1026}
1027
1028/* <hint> may be:
1029 * - A simple product name
1030 * e.g., "sooner"
1031TODO: debug? sooner-debug, sooner:debug?
1032 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1033 * e.g., "out/target/product/sooner"
1034 * - An absolute path to the PRODUCT_OUT dir
1035 * e.g., "/src/device/out/target/product/sooner"
1036 *
1037 * Given <hint>, try to construct an absolute path to the
1038 * ANDROID_PRODUCT_OUT dir.
1039 */
1040static const char *find_product_out_path(const char *hint)
1041{
1042 static char path_buf[PATH_MAX];
1043
1044 if (hint == NULL || hint[0] == '\0') {
1045 return NULL;
1046 }
1047
1048 /* If it's already absolute, don't bother doing any work.
1049 */
1050 if (adb_is_absolute_host_path(hint)) {
1051 strcpy(path_buf, hint);
1052 return path_buf;
1053 }
1054
1055 /* If there are any slashes in it, assume it's a relative path;
1056 * make it absolute.
1057 */
1058 if (adb_dirstart(hint) != NULL) {
1059 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1060 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1061 return NULL;
1062 }
1063 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1064 fprintf(stderr, "adb: Couldn't assemble path\n");
1065 return NULL;
1066 }
1067 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1068 strcat(path_buf, hint);
1069 return path_buf;
1070 }
1071
1072 /* It's a string without any slashes. Try to do something with it.
1073 *
1074 * Try to find the root of the build tree, and build a PRODUCT_OUT
1075 * path from there.
1076 */
1077 char top_buf[PATH_MAX];
1078 const char *top = find_top(top_buf);
1079 if (top == NULL) {
1080 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1081 return NULL;
1082 }
1083//TODO: if we have a way to indicate debug, look in out/debug/target/...
1084 snprintf(path_buf, sizeof(path_buf),
1085 "%s" OS_PATH_SEPARATOR_STR
1086 "out" OS_PATH_SEPARATOR_STR
1087 "target" OS_PATH_SEPARATOR_STR
1088 "product" OS_PATH_SEPARATOR_STR
1089 "%s", top_buf, hint);
1090 if (access(path_buf, F_OK) < 0) {
1091 fprintf(stderr, "adb: Couldn't find a product dir "
1092 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1093 return NULL;
1094 }
1095 return path_buf;
1096}
1097
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001098static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1099 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001100 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001101 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001102
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001103 while (narg > 0) {
1104 if (!strcmp(*arg, "-p")) {
1105 *show_progress = 1;
1106 } else if (!strcmp(*arg, "-a")) {
1107 *copy_attrs = 1;
1108 } else {
1109 break;
1110 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001111 ++arg;
1112 --narg;
1113 }
1114
1115 if (narg > 0) {
1116 *path1 = *arg;
1117 ++arg;
1118 --narg;
1119 }
1120
1121 if (narg > 0) {
1122 *path2 = *arg;
1123 }
1124}
1125
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001126int adb_commandline(int argc, char **argv)
1127{
1128 char buf[4096];
1129 int no_daemon = 0;
1130 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001131 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001132 int persist = 0;
1133 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001134 transport_type ttype = kTransportAny;
1135 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001136 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001137
1138 /* If defined, this should be an absolute path to
1139 * the directory containing all of the various system images
1140 * for a particular product. If not defined, and the adb
1141 * command requires this information, then the user must
1142 * specify the path using "-p".
1143 */
1144 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1145 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1146 gProductOutPath = NULL;
1147 }
1148 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1149
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001150 serial = getenv("ANDROID_SERIAL");
1151
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001152 /* Validate and assign the server port */
1153 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1154 int server_port = DEFAULT_ADB_PORT;
1155 if (server_port_str && strlen(server_port_str) > 0) {
1156 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001157 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001158 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001159 "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 +01001160 server_port_str);
1161 return usage();
1162 }
1163 }
1164
1165 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001166 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001167 if(!strcmp(argv[0],"server")) {
1168 is_server = 1;
1169 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001170 no_daemon = 1;
1171 } else if (!strcmp(argv[0], "fork-server")) {
1172 /* this is a special flag used only when the ADB client launches the ADB Server */
1173 is_daemon = 1;
1174 } else if(!strcmp(argv[0],"persist")) {
1175 persist = 1;
1176 } else if(!strncmp(argv[0], "-p", 2)) {
1177 const char *product = NULL;
1178 if (argv[0][2] == '\0') {
1179 if (argc < 2) return usage();
1180 product = argv[1];
1181 argc--;
1182 argv++;
1183 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001184 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001185 }
1186 gProductOutPath = find_product_out_path(product);
1187 if (gProductOutPath == NULL) {
1188 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1189 product);
1190 return usage();
1191 }
1192 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1193 if (isdigit(argv[0][2])) {
1194 serial = argv[0] + 2;
1195 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001196 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001197 serial = argv[1];
1198 argc--;
1199 argv++;
1200 }
1201 } else if (!strcmp(argv[0],"-d")) {
1202 ttype = kTransportUsb;
1203 } else if (!strcmp(argv[0],"-e")) {
1204 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001205 } else if (!strcmp(argv[0],"-a")) {
1206 gListenAll = 1;
1207 } else if(!strncmp(argv[0], "-H", 2)) {
1208 const char *hostname = NULL;
1209 if (argv[0][2] == '\0') {
1210 if (argc < 2) return usage();
1211 hostname = argv[1];
1212 argc--;
1213 argv++;
1214 } else {
1215 hostname = argv[0] + 2;
1216 }
1217 adb_set_tcp_name(hostname);
1218
1219 } else if(!strncmp(argv[0], "-P", 2)) {
1220 if (argv[0][2] == '\0') {
1221 if (argc < 2) return usage();
1222 server_port_str = argv[1];
1223 argc--;
1224 argv++;
1225 } else {
1226 server_port_str = argv[0] + 2;
1227 }
1228 if (strlen(server_port_str) > 0) {
1229 server_port = (int) strtol(server_port_str, NULL, 0);
1230 if (server_port <= 0 || server_port > 65535) {
1231 fprintf(stderr,
1232 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1233 server_port_str);
1234 return usage();
1235 }
1236 } else {
1237 fprintf(stderr,
1238 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1239 return usage();
1240 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001241 } else {
1242 /* out of recognized modifiers and flags */
1243 break;
1244 }
1245 argc--;
1246 argv++;
1247 }
1248
1249 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001250 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001251
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001252 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001253 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001254 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001255 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001256 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001257 }
1258 if(r) {
1259 fprintf(stderr,"* could not start server *\n");
1260 }
1261 return r;
1262 }
1263
1264top:
1265 if(argc == 0) {
1266 return usage();
1267 }
1268
1269 /* adb_connect() commands */
1270
1271 if(!strcmp(argv[0], "devices")) {
1272 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001273 char *listopt;
1274 if (argc < 2)
1275 listopt = "";
1276 else if (argc == 2 && !strcmp(argv[1], "-l"))
1277 listopt = argv[1];
1278 else {
1279 fprintf(stderr, "Usage: adb devices [-l]\n");
1280 return 1;
1281 }
1282 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001283 tmp = adb_query(buf);
1284 if(tmp) {
1285 printf("List of devices attached \n");
1286 printf("%s\n", tmp);
1287 return 0;
1288 } else {
1289 return 1;
1290 }
1291 }
1292
Mike Lockwood01c2c302010-05-24 10:44:35 -04001293 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001294 char *tmp;
1295 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001296 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001297 return 1;
1298 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001299 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1300 tmp = adb_query(buf);
1301 if(tmp) {
1302 printf("%s\n", tmp);
1303 return 0;
1304 } else {
1305 return 1;
1306 }
1307 }
1308
1309 if(!strcmp(argv[0], "disconnect")) {
1310 char *tmp;
1311 if (argc > 2) {
1312 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1313 return 1;
1314 }
1315 if (argc == 2) {
1316 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1317 } else {
1318 snprintf(buf, sizeof buf, "host:disconnect:");
1319 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001320 tmp = adb_query(buf);
1321 if(tmp) {
1322 printf("%s\n", tmp);
1323 return 0;
1324 } else {
1325 return 1;
1326 }
1327 }
1328
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001329 if (!strcmp(argv[0], "emu")) {
1330 return adb_send_emulator_command(argc, argv);
1331 }
1332
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001333 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001334 int r;
1335 int fd;
1336
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001337 char h = (argv[0][0] == 'h');
1338
1339 if (h) {
1340 printf("\x1b[41;33m");
1341 fflush(stdout);
1342 }
1343
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001344 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001345 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001346 r = interactive_shell();
1347 if (h) {
1348 printf("\x1b[0m");
1349 fflush(stdout);
1350 }
1351 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001352 }
1353
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001354 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001355 argc -= 2;
1356 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001357 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001358 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001359 strncat(buf, " ", sizeof(buf) - 1);
1360 strncat(buf, quoted, sizeof(buf) - 1);
1361 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001362 }
1363
1364 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001365 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001366 fd = adb_connect(buf);
1367 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001368 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001369 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001370 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001371 adb_close(fd);
1372 r = 0;
1373 } else {
1374 fprintf(stderr,"error: %s\n", adb_error());
1375 r = -1;
1376 }
1377
1378 if(persist) {
1379 fprintf(stderr,"\n- waiting for device -\n");
1380 adb_sleep_ms(1000);
1381 do_cmd(ttype, serial, "wait-for-device", 0);
1382 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001383 if (h) {
1384 printf("\x1b[0m");
1385 fflush(stdout);
1386 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001387 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001388 return r;
1389 }
1390 }
1391 }
1392
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001393 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1394 int exec_in = !strcmp(argv[0], "exec-in");
1395 int fd;
1396
1397 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1398 argc -= 2;
1399 argv += 2;
1400 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001401 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001402 strncat(buf, " ", sizeof(buf) - 1);
1403 strncat(buf, quoted, sizeof(buf) - 1);
1404 free(quoted);
1405 }
1406
1407 fd = adb_connect(buf);
1408 if (fd < 0) {
1409 fprintf(stderr, "error: %s\n", adb_error());
1410 return -1;
1411 }
1412
1413 if (exec_in) {
1414 copy_to_file(STDIN_FILENO, fd);
1415 } else {
1416 copy_to_file(fd, STDOUT_FILENO);
1417 }
1418
1419 adb_close(fd);
1420 return 0;
1421 }
1422
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001423 if(!strcmp(argv[0], "kill-server")) {
1424 int fd;
1425 fd = _adb_connect("host:kill");
1426 if(fd == -1) {
1427 fprintf(stderr,"* server not running *\n");
1428 return 1;
1429 }
1430 return 0;
1431 }
1432
Doug Zongker6b217ed2012-01-09 14:54:53 -08001433 if(!strcmp(argv[0], "sideload")) {
1434 if(argc != 2) return usage();
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001435 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001436 return 1;
1437 } else {
1438 return 0;
1439 }
1440 }
1441
Mike Lockwood26b88e32009-08-24 15:58:40 -07001442 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001443 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001444 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001445 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001446 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001447 if (!strcmp(argv[0], "reboot-bootloader"))
1448 snprintf(command, sizeof(command), "reboot:bootloader");
1449 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001450 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001451 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001452 snprintf(command, sizeof(command), "%s:", argv[0]);
1453 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001454 if(fd >= 0) {
1455 read_and_dump(fd);
1456 adb_close(fd);
1457 return 0;
1458 }
1459 fprintf(stderr,"error: %s\n", adb_error());
1460 return 1;
1461 }
1462
Mike Lockwood78589f32009-09-03 14:54:58 -04001463 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001464 if (argc != 1) return usage();
1465 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001466 return 0;
1467 }
1468
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001469 /* adb_command() wrapper commands */
1470
1471 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1472 char* service = argv[0];
1473 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1474 if (ttype == kTransportUsb) {
1475 service = "wait-for-usb";
1476 } else if (ttype == kTransportLocal) {
1477 service = "wait-for-local";
1478 } else {
1479 service = "wait-for-any";
1480 }
1481 }
1482
1483 format_host_command(buf, sizeof buf, service, ttype, serial);
1484
1485 if (adb_command(buf)) {
1486 D("failure: %s *\n",adb_error());
1487 fprintf(stderr,"error: %s\n", adb_error());
1488 return 1;
1489 }
1490
1491 /* Allow a command to be run after wait-for-device,
1492 * e.g. 'adb wait-for-device shell'.
1493 */
1494 if(argc > 1) {
1495 argc--;
1496 argv++;
1497 goto top;
1498 }
1499 return 0;
1500 }
1501
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001502 if(!strcmp(argv[0], "forward") ||
1503 !strcmp(argv[0], "reverse"))
1504 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001505 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001506 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001507 char remove = 0;
1508 char remove_all = 0;
1509 char list = 0;
1510 char no_rebind = 0;
1511
1512 // Parse options here.
1513 while (argc > 1 && argv[1][0] == '-') {
1514 if (!strcmp(argv[1], "--list"))
1515 list = 1;
1516 else if (!strcmp(argv[1], "--remove"))
1517 remove = 1;
1518 else if (!strcmp(argv[1], "--remove-all"))
1519 remove_all = 1;
1520 else if (!strcmp(argv[1], "--no-rebind"))
1521 no_rebind = 1;
1522 else {
1523 return usage();
1524 }
1525 argc--;
1526 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001527 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001528
1529 // Ensure we can only use one option at a time.
1530 if (list + remove + remove_all + no_rebind > 1) {
1531 return usage();
1532 }
1533
1534 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001535 if (reverse) {
1536 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001537 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001538 if (serial) {
1539 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1540 serial);
1541 } else if (ttype == kTransportUsb) {
1542 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1543 } else if (ttype == kTransportLocal) {
1544 snprintf(host_prefix, sizeof host_prefix, "host-local");
1545 } else {
1546 snprintf(host_prefix, sizeof host_prefix, "host");
1547 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001548 }
1549
1550 // Implement forward --list
1551 if (list) {
1552 if (argc != 1)
1553 return usage();
1554 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1555 char* forwards = adb_query(buf);
1556 if (forwards == NULL) {
1557 fprintf(stderr, "error: %s\n", adb_error());
1558 return 1;
1559 }
1560 printf("%s", forwards);
1561 free(forwards);
1562 return 0;
1563 }
1564
1565 // Implement forward --remove-all
1566 else if (remove_all) {
1567 if (argc != 1)
1568 return usage();
1569 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1570 }
1571
1572 // Implement forward --remove <local>
1573 else if (remove) {
1574 if (argc != 2)
1575 return usage();
1576 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1577 }
1578 // Or implement one of:
1579 // forward <local> <remote>
1580 // forward --no-rebind <local> <remote>
1581 else
1582 {
1583 if (argc != 3)
1584 return usage();
1585 const char* command = no_rebind ? "forward:norebind:" : "forward";
1586 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1587 }
1588
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001589 if(adb_command(buf)) {
1590 fprintf(stderr,"error: %s\n", adb_error());
1591 return 1;
1592 }
1593 return 0;
1594 }
1595
1596 /* do_sync_*() commands */
1597
1598 if(!strcmp(argv[0], "ls")) {
1599 if(argc != 2) return usage();
1600 return do_sync_ls(argv[1]);
1601 }
1602
1603 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001604 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001605 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001606 const char* lpath = NULL, *rpath = NULL;
1607
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001608 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001609
1610 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001611 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001612 }
1613
1614 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001615 }
1616
1617 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001618 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001619 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001620 const char* rpath = NULL, *lpath = ".";
1621
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001622 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001623
1624 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001625 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001626 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001627
1628 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001629 }
1630
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001631 if (!strcmp(argv[0], "install")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001632 if (argc < 2) return usage();
1633 return install_app(ttype, serial, argc, argv);
1634 }
1635
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001636 if (!strcmp(argv[0], "install-multiple")) {
1637 if (argc < 2) return usage();
1638 return install_multiple_app(ttype, serial, argc, argv);
1639 }
1640
1641 if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001642 if (argc < 2) return usage();
1643 return uninstall_app(ttype, serial, argc, argv);
1644 }
1645
1646 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001647 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001648 int listonly = 0;
1649
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001650 int ret;
1651 if(argc < 2) {
1652 /* No local path was specified. */
1653 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001654 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1655 listonly = 1;
1656 if (argc == 3) {
1657 srcarg = argv[2];
1658 } else {
1659 srcarg = NULL;
1660 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001661 } else if(argc == 2) {
1662 /* A local path or "android"/"data" arg was specified. */
1663 srcarg = argv[1];
1664 } else {
1665 return usage();
1666 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001667 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001668 if(ret != 0) return usage();
1669
1670 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001671 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001672 if(ret == 0 && vendor_srcpath != NULL)
1673 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001674 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001675 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001676
1677 free(android_srcpath);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001678 free(vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001679 free(data_srcpath);
1680 return ret;
1681 }
1682
1683 /* passthrough commands */
1684
1685 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001686 !strcmp(argv[0],"get-serialno") ||
1687 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001688 {
1689 char *tmp;
1690
1691 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1692 tmp = adb_query(buf);
1693 if(tmp) {
1694 printf("%s\n", tmp);
1695 return 0;
1696 } else {
1697 return 1;
1698 }
1699 }
1700
1701 /* other commands */
1702
1703 if(!strcmp(argv[0],"status-window")) {
1704 status_window(ttype, serial);
1705 return 0;
1706 }
1707
Christopher Tate7b9b5162011-11-30 13:00:33 -08001708 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001709 return logcat(ttype, serial, argc, argv);
1710 }
1711
1712 if(!strcmp(argv[0],"ppp")) {
1713 return ppp(argc, argv);
1714 }
1715
1716 if (!strcmp(argv[0], "start-server")) {
1717 return adb_connect("host:start-server");
1718 }
1719
Christopher Tate73779122011-04-21 12:53:28 -07001720 if (!strcmp(argv[0], "backup")) {
1721 return backup(argc, argv);
1722 }
1723
Christopher Tatecf5379b2011-05-17 15:52:54 -07001724 if (!strcmp(argv[0], "restore")) {
1725 return restore(argc, argv);
1726 }
1727
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001728 if (!strcmp(argv[0], "jdwp")) {
1729 int fd = adb_connect("jdwp");
1730 if (fd >= 0) {
1731 read_and_dump(fd);
1732 adb_close(fd);
1733 return 0;
1734 } else {
1735 fprintf(stderr, "error: %s\n", adb_error());
1736 return -1;
1737 }
1738 }
1739
1740 /* "adb /?" is a common idiom under Windows */
1741 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1742 help();
1743 return 0;
1744 }
1745
1746 if(!strcmp(argv[0], "version")) {
1747 version(stdout);
1748 return 0;
1749 }
1750
1751 usage();
1752 return 1;
1753}
1754
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001755#define MAX_ARGV_LENGTH 16
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001756static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1757{
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001758 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001759 int argc;
1760 va_list ap;
1761
1762 va_start(ap, cmd);
1763 argc = 0;
1764
1765 if (serial) {
1766 argv[argc++] = "-s";
1767 argv[argc++] = serial;
1768 } else if (ttype == kTransportUsb) {
1769 argv[argc++] = "-d";
1770 } else if (ttype == kTransportLocal) {
1771 argv[argc++] = "-e";
1772 }
1773
1774 argv[argc++] = cmd;
Alexander Ivchenko9bdc70d2014-08-06 14:51:40 +04001775 while(argc < MAX_ARGV_LENGTH &&
1776 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1777 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001778 va_end(ap);
1779
1780#if 0
1781 int n;
1782 fprintf(stderr,"argc = %d\n",argc);
1783 for(n = 0; n < argc; n++) {
1784 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1785 }
1786#endif
1787
1788 return adb_commandline(argc, argv);
1789}
1790
1791int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001792 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001793{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001794 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1795 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001796
1797 if(srcarg == NULL) {
1798 android_srcdir = product_file("system");
1799 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001800 vendor_srcdir = product_file("vendor");
1801 /* Check if vendor partition exists */
1802 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1803 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001804 } else {
1805 /* srcarg may be "data", "system" or NULL.
1806 * if srcarg is NULL, then both data and system are synced
1807 */
1808 if(strcmp(srcarg, "system") == 0) {
1809 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001810 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001811 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001812 } else if(strcmp(srcarg, "vendor") == 0) {
1813 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001814 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001815 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001816 */
1817 return 1;
1818 }
1819 }
1820
1821 if(android_srcdir_out != NULL)
1822 *android_srcdir_out = android_srcdir;
1823 else
1824 free(android_srcdir);
1825
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001826 if(vendor_srcdir_out != NULL)
1827 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001828 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001829 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001830
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001831 if(data_srcdir_out != NULL)
1832 *data_srcdir_out = data_srcdir;
1833 else
1834 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001835 return 0;
1836}
1837
1838static int pm_command(transport_type transport, char* serial,
1839 int argc, char** argv)
1840{
1841 char buf[4096];
1842
1843 snprintf(buf, sizeof(buf), "shell:pm");
1844
1845 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001846 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001847 strncat(buf, " ", sizeof(buf) - 1);
1848 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001849 free(quoted);
1850 }
1851
1852 send_shellcommand(transport, serial, buf);
1853 return 0;
1854}
1855
1856int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1857{
1858 /* if the user choose the -k option, we refuse to do it until devices are
1859 out with the option to uninstall the remaining data somehow (adb/ui) */
1860 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1861 {
1862 printf(
1863 "The -k option uninstalls the application while retaining the data/cache.\n"
1864 "At the moment, there is no way to remove the remaining data.\n"
1865 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1866 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1867 return -1;
1868 }
1869
1870 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1871 return pm_command(transport, serial, argc, argv);
1872}
1873
1874static int delete_file(transport_type transport, char* serial, char* filename)
1875{
1876 char buf[4096];
1877 char* quoted;
1878
Jeff Sharkeyce474652014-09-09 12:38:30 -07001879 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001880 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001881 strncat(buf, quoted, sizeof(buf)-1);
1882 free(quoted);
1883
1884 send_shellcommand(transport, serial, buf);
1885 return 0;
1886}
1887
Kenny Root3802c992011-08-05 11:19:45 -07001888static const char* get_basename(const char* filename)
1889{
1890 const char* basename = adb_dirstop(filename);
1891 if (basename) {
1892 basename++;
1893 return basename;
1894 } else {
1895 return filename;
1896 }
1897}
1898
Kenny Root3802c992011-08-05 11:19:45 -07001899int install_app(transport_type transport, char* serial, int argc, char** argv)
1900{
1901 static const char *const DATA_DEST = "/data/local/tmp/%s";
1902 static const char *const SD_DEST = "/sdcard/tmp/%s";
1903 const char* where = DATA_DEST;
Kenny Root3802c992011-08-05 11:19:45 -07001904 int i;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001905 struct stat sb;
Kenny Root3802c992011-08-05 11:19:45 -07001906
1907 for (i = 1; i < argc; i++) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001908 if (!strcmp(argv[i], "-s")) {
Kenny Root3802c992011-08-05 11:19:45 -07001909 where = SD_DEST;
1910 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001911 }
1912
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001913 // Find last APK argument.
1914 // All other arguments passed through verbatim.
1915 int last_apk = -1;
1916 for (i = argc - 1; i >= 0; i--) {
1917 char* file = argv[i];
1918 char* dot = strrchr(file, '.');
1919 if (dot && !strcasecmp(dot, ".apk")) {
1920 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1921 fprintf(stderr, "Invalid APK file: %s\n", file);
1922 return -1;
1923 }
1924
1925 last_apk = i;
1926 break;
1927 }
Kenny Root3802c992011-08-05 11:19:45 -07001928 }
1929
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001930 if (last_apk == -1) {
1931 fprintf(stderr, "Missing APK file\n");
1932 return -1;
Kenny Root3802c992011-08-05 11:19:45 -07001933 }
1934
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001935 char* apk_file = argv[last_apk];
1936 char apk_dest[PATH_MAX];
Kenny Root3802c992011-08-05 11:19:45 -07001937 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001938 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001939 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001940 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001941 } else {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001942 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root3802c992011-08-05 11:19:45 -07001943 }
1944
1945 pm_command(transport, serial, argc, argv);
1946
Kenny Root58d5f222012-03-26 16:14:02 -07001947cleanup_apk:
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001948 delete_file(transport, serial, apk_dest);
1949 return err;
1950}
1951
1952int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1953{
1954 char buf[1024];
1955 int i;
1956 struct stat sb;
1957 unsigned long long total_size = 0;
1958
1959 // Find all APK arguments starting at end.
1960 // All other arguments passed through verbatim.
1961 int first_apk = -1;
1962 for (i = argc - 1; i >= 0; i--) {
1963 char* file = argv[i];
1964 char* dot = strrchr(file, '.');
1965 if (dot && !strcasecmp(dot, ".apk")) {
1966 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1967 fprintf(stderr, "Invalid APK file: %s\n", file);
1968 return -1;
1969 }
1970
1971 total_size += sb.st_size;
1972 first_apk = i;
1973 } else {
1974 break;
1975 }
Kenny Root3802c992011-08-05 11:19:45 -07001976 }
1977
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001978 if (first_apk == -1) {
1979 fprintf(stderr, "Missing APK file\n");
1980 return 1;
1981 }
Kenny Root3802c992011-08-05 11:19:45 -07001982
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001983 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1984 for (i = 1; i < first_apk; i++) {
1985 char *quoted = escape_arg(argv[i]);
1986 strncat(buf, " ", sizeof(buf) - 1);
1987 strncat(buf, quoted, sizeof(buf) - 1);
1988 free(quoted);
1989 }
1990
1991 // Create install session
1992 int fd = adb_connect(buf);
1993 if (fd < 0) {
1994 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1995 return -1;
1996 }
1997 read_status_line(fd, buf, sizeof(buf));
1998 adb_close(fd);
1999
2000 int session_id = -1;
2001 if (!strncmp("Success", buf, 7)) {
2002 char* start = strrchr(buf, '[');
2003 char* end = strrchr(buf, ']');
2004 if (start && end) {
2005 *end = '\0';
2006 session_id = strtol(start + 1, NULL, 10);
2007 }
2008 }
2009 if (session_id < 0) {
2010 fprintf(stderr, "Failed to create session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002011 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002012 return -1;
2013 }
2014
2015 // Valid session, now stream the APKs
2016 int success = 1;
2017 for (i = first_apk; i < argc; i++) {
2018 char* file = argv[i];
2019 if (stat(file, &sb) == -1) {
2020 fprintf(stderr, "Failed to stat %s\n", file);
2021 success = 0;
2022 goto finalize_session;
2023 }
2024
2025 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkey4a7ddb62014-07-14 13:57:54 -07002026 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002027
2028 int localFd = adb_open(file, O_RDONLY);
2029 if (localFd < 0) {
2030 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2031 success = 0;
2032 goto finalize_session;
2033 }
2034
2035 int remoteFd = adb_connect(buf);
2036 if (remoteFd < 0) {
2037 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2038 adb_close(localFd);
2039 success = 0;
2040 goto finalize_session;
2041 }
2042
2043 copy_to_file(localFd, remoteFd);
2044 read_status_line(remoteFd, buf, sizeof(buf));
2045
2046 adb_close(localFd);
2047 adb_close(remoteFd);
2048
2049 if (strncmp("Success", buf, 7)) {
2050 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate29721da2014-07-14 16:45:13 -07002051 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002052 success = 0;
2053 goto finalize_session;
2054 }
2055 }
2056
2057finalize_session:
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002058 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002059 if (success) {
2060 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2061 } else {
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002062 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002063 }
2064
2065 fd = adb_connect(buf);
2066 if (fd < 0) {
2067 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2068 return -1;
2069 }
2070 read_status_line(fd, buf, sizeof(buf));
2071 adb_close(fd);
2072
2073 if (!strncmp("Success", buf, 7)) {
Christopher Tate29721da2014-07-14 16:45:13 -07002074 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002075 return 0;
2076 } else {
2077 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07002078 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002079 return -1;
2080 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08002081}