blob: 770487804b9d3373758b83e550785a9e0a0adf78 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
Andrew Hsiehb75d6f12014-05-07 20:21:11 +080018#include <stdint.h>
The Android Open Source Projectdd7bc332009-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"
Nick Kralevich86c9e5f2014-11-13 15:17:29 -080039#include "adb_auth.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040#include "file_sync_service.h"
41
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
43
Alexey Tarasov31664102009-10-22 02:55:00 +110044void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -070046 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey960df972014-06-09 17:30:57 -070048int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
50
51static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080052extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080053
54static char *product_file(const char *extra)
55{
56 int n;
57 char *x;
58
59 if (gProductOutPath == NULL) {
60 fprintf(stderr, "adb: Product directory not specified; "
61 "use -p or define ANDROID_PRODUCT_OUT\n");
62 exit(1);
63 }
64
65 n = strlen(gProductOutPath) + strlen(extra) + 2;
66 x = malloc(n);
67 if (x == 0) {
68 fprintf(stderr, "adb: Out of memory (product_file())\n");
69 exit(1);
70 }
71
72 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
73 return x;
74}
75
76void version(FILE * out) {
77 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
78 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
79}
80
81void help()
82{
83 version(stderr);
84
85 fprintf(stderr,
86 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080087 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080088 " -d - directs command to the only connected USB device\n"
89 " returns an error if more than one USB device is present.\n"
90 " -e - directs command to the only running emulator.\n"
91 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070092 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070093 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070094 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 " -p <product name or path> - simple product name like 'sooner', or\n"
96 " a relative/absolute path to a product\n"
97 " out directory like 'out/target/product/sooner'.\n"
98 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
99 " environment variable is used, which must\n"
100 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800101 " -H - Name of adb server host (default: localhost)\n"
102 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700103 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700104 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400105 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
106 " Port 5555 is used by default if no port number is specified.\n"
107 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
108 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200109 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400110 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 "\n"
112 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700113 " adb push [-p] <local> <remote>\n"
114 " - copy file/dir to device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700116 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700117 " - copy file/dir from device\n"
118 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700119 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600121 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800122 " (see 'adb help all')\n"
123 " adb shell - run remote shell interactively\n"
124 " adb shell <command> - run remote shell command\n"
125 " adb emu <command> - run emulator console command\n"
126 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100127 " adb forward --list - list all forward socket connections.\n"
128 " the format is a list of lines with the following format:\n"
129 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800130 " adb forward <local> <remote> - forward socket connections\n"
131 " forward specs are one of: \n"
132 " tcp:<port>\n"
133 " localabstract:<unix domain socket name>\n"
134 " localreserved:<unix domain socket name>\n"
135 " localfilesystem:<unix domain socket name>\n"
136 " dev:<character device name>\n"
137 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100138 " adb forward --no-rebind <local> <remote>\n"
139 " - same as 'adb forward <local> <remote>' but fails\n"
140 " if <local> is already forwarded\n"
141 " adb forward --remove <local> - remove a specific forward socket connection\n"
142 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100143 " adb reverse --list - list all reverse socket connections from device\n"
144 " adb reverse <remote> <local> - reverse socket connections\n"
145 " reverse specs are one of:\n"
146 " tcp:<port>\n"
147 " localabstract:<unix domain socket name>\n"
148 " localreserved:<unix domain socket name>\n"
149 " localfilesystem:<unix domain socket name>\n"
150 " adb reverse --norebind <remote> <local>\n"
151 " - same as 'adb reverse <remote> <local>' but fails\n"
152 " if <remote> is already reversed.\n"
153 " adb reverse --remove <remote>\n"
154 " - remove a specific reversed socket connection\n"
155 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700157 " adb install [-lrtsd] <file>\n"
158 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700160 " (-l: forward lock application)\n"
161 " (-r: replace existing application)\n"
162 " (-t: allow test packages)\n"
163 " (-s: install application on sdcard)\n"
164 " (-d: allow version code downgrade)\n"
165 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166 " adb uninstall [-k] <package> - remove this app package from the device\n"
167 " ('-k' means keep the data and cache directories)\n"
168 " adb bugreport - return all information from the device\n"
169 " that should be included in a bug report.\n"
170 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800171 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700172 " - write an archive of the device's data to <file>.\n"
173 " If no -f option is supplied then the data is written\n"
174 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700175 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700176 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800177 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
178 " (aka .obb) files associated with each application; the default\n"
179 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700180 " (-shared|-noshared enable/disable backup of the device's\n"
181 " shared storage / SD card contents; the default is noshared.)\n"
182 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700183 " (-system|-nosystem toggles whether -all automatically includes\n"
184 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700185 " (<packages...> is the list of applications to be backed up. If\n"
186 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700187 " list is optional. Applications explicitly given on the\n"
188 " command line will be included even if -nosystem would\n"
189 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700190 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700191 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700192 "\n"
Paul Lawrencebbb36312014-10-09 14:22:49 +0000193 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
Nick Kralevich86c9e5f2014-11-13 15:17:29 -0800194 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
195 " and the public key is stored in <file>.pub. Any existing files\n"
196 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 " adb help - show this help message\n"
198 " adb version - show version num\n"
199 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 "scripting:\n"
201 " adb wait-for-device - block until device is online\n"
202 " adb start-server - ensure that there is a server running\n"
203 " adb kill-server - kill the server if it is running\n"
204 " adb get-state - prints: offline | bootloader | device\n"
205 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700206 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800207 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700208 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400209 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800210 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700211 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800212 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrencebbb36312014-10-09 14:22:49 +0000213 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800214 "networking:\n"
215 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500216 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800217 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
218 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
219 "\n"
220 "adb sync notes: adb sync [ <directory> ]\n"
221 " <localdir> can be interpreted in several ways:\n"
222 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700223 " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800224 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700225 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000227 "\n"
228 "environmental variables:\n"
229 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
230 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
231 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
232 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233 );
234}
235
236int usage()
237{
238 help();
239 return 1;
240}
241
242#ifdef HAVE_TERMIO_H
243static struct termios tio_save;
244
245static void stdin_raw_init(int fd)
246{
247 struct termios tio;
248
249 if(tcgetattr(fd, &tio)) return;
250 if(tcgetattr(fd, &tio_save)) return;
251
252 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
253
254 /* no timeout but request at least one character per read */
255 tio.c_cc[VTIME] = 0;
256 tio.c_cc[VMIN] = 1;
257
258 tcsetattr(fd, TCSANOW, &tio);
259 tcflush(fd, TCIFLUSH);
260}
261
262static void stdin_raw_restore(int fd)
263{
264 tcsetattr(fd, TCSANOW, &tio_save);
265 tcflush(fd, TCIFLUSH);
266}
267#endif
268
269static void read_and_dump(int fd)
270{
271 char buf[4096];
272 int len;
273
274 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700275 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700277 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278 if(len == 0) {
279 break;
280 }
281
282 if(len < 0) {
283 if(errno == EINTR) continue;
284 break;
285 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400286 fwrite(buf, 1, len, stdout);
287 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 }
289}
290
Jeff Sharkey960df972014-06-09 17:30:57 -0700291static void read_status_line(int fd, char* buf, size_t count)
292{
293 count--;
294 while (count > 0) {
295 int len = adb_read(fd, buf, count);
296 if (len == 0) {
297 break;
298 } else if (len < 0) {
299 if (errno == EINTR) continue;
300 break;
301 }
302
303 buf += len;
304 count -= len;
305 }
306 *buf = '\0';
307}
308
Christopher Tated2f54152011-04-21 12:53:28 -0700309static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700310 const size_t BUFSIZE = 32 * 1024;
311 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700312 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700313 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700314
315 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700316#ifdef HAVE_TERMIO_H
317 if (inFd == STDIN_FILENO) {
318 stdin_raw_init(STDIN_FILENO);
319 }
320#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700321 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700322 if (inFd == STDIN_FILENO) {
323 len = unix_read(inFd, buf, BUFSIZE);
324 } else {
325 len = adb_read(inFd, buf, BUFSIZE);
326 }
Christopher Tated2f54152011-04-21 12:53:28 -0700327 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700328 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700329 break;
330 }
331 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700332 if (errno == EINTR) {
333 D("copy_to_file() : EINTR, retrying\n");
334 continue;
335 }
Christopher Tated2f54152011-04-21 12:53:28 -0700336 D("copy_to_file() : error %d\n", errno);
337 break;
338 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700339 if (outFd == STDOUT_FILENO) {
340 fwrite(buf, 1, len, stdout);
341 fflush(stdout);
342 } else {
343 adb_write(outFd, buf, len);
344 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700345 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700346 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700347#ifdef HAVE_TERMIO_H
348 if (inFd == STDIN_FILENO) {
349 stdin_raw_restore(STDIN_FILENO);
350 }
351#endif
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700352 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700353 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700354}
355
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800356static void *stdin_read_thread(void *x)
357{
358 int fd, fdi;
359 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800360 int r, n;
361 int state = 0;
362
363 int *fds = (int*) x;
364 fd = fds[0];
365 fdi = fds[1];
366 free(fds);
367
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800368 for(;;) {
369 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700370 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700372 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 if(r == 0) break;
374 if(r < 0) {
375 if(errno == EINTR) continue;
376 break;
377 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400378 for(n = 0; n < r; n++){
379 switch(buf[n]) {
380 case '\n':
381 state = 1;
382 break;
383 case '\r':
384 state = 1;
385 break;
386 case '~':
387 if(state == 1) state++;
388 break;
389 case '.':
390 if(state == 2) {
391 fprintf(stderr,"\n* disconnect *\n");
392#ifdef HAVE_TERMIO_H
393 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800394#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400395 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400397 default:
398 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800399 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 r = adb_write(fd, buf, r);
402 if(r <= 0) {
403 break;
404 }
405 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800406 return 0;
407}
408
409int interactive_shell(void)
410{
411 adb_thread_t thr;
412 int fdi, fd;
413 int *fds;
414
415 fd = adb_connect("shell:");
416 if(fd < 0) {
417 fprintf(stderr,"error: %s\n", adb_error());
418 return 1;
419 }
420 fdi = 0; //dup(0);
421
422 fds = malloc(sizeof(int) * 2);
423 fds[0] = fd;
424 fds[1] = fdi;
425
426#ifdef HAVE_TERMIO_H
427 stdin_raw_init(fdi);
428#endif
429 adb_thread_create(&thr, stdin_read_thread, fds);
430 read_and_dump(fd);
431#ifdef HAVE_TERMIO_H
432 stdin_raw_restore(fdi);
433#endif
434 return 0;
435}
436
437
438static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
439{
440 if (serial) {
441 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
442 } else {
443 const char* prefix = "host";
444 if (ttype == kTransportUsb)
445 prefix = "host-usb";
446 else if (ttype == kTransportLocal)
447 prefix = "host-local";
448
449 snprintf(buffer, buflen, "%s:%s", prefix, command);
450 }
451}
452
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100453int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800454 unsigned progress)
455{
456 char buf[4096];
457 unsigned total;
458 int fd;
459 const unsigned char *ptr;
460
461 sprintf(buf,"%s:%d", service, sz);
462 fd = adb_connect(buf);
463 if(fd < 0) {
464 fprintf(stderr,"error: %s\n", adb_error());
465 return -1;
466 }
467
468 int opt = CHUNK_SIZE;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700469 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800470
471 total = sz;
472 ptr = data;
473
474 if(progress) {
475 char *x = strrchr(service, ':');
476 if(x) service = x + 1;
477 }
478
479 while(sz > 0) {
480 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
481 if(writex(fd, ptr, xfer)) {
482 adb_status(fd);
483 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
484 return -1;
485 }
486 sz -= xfer;
487 ptr += xfer;
488 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100489 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800490 fflush(stdout);
491 }
492 }
493 if(progress) {
494 printf("\n");
495 }
496
497 if(readx(fd, buf, 4)){
498 fprintf(stderr,"* error reading response *\n");
499 adb_close(fd);
500 return -1;
501 }
502 if(memcmp(buf, "OKAY", 4)) {
503 buf[4] = 0;
504 fprintf(stderr,"* error response '%s' *\n", buf);
505 adb_close(fd);
506 return -1;
507 }
508
509 adb_close(fd);
510 return 0;
511}
512
513
514int adb_download(const char *service, const char *fn, unsigned progress)
515{
516 void *data;
517 unsigned sz;
518
519 data = load_file(fn, &sz);
520 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100521 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800522 return -1;
523 }
524
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100525 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800526 free(data);
527 return status;
528}
529
Doug Zongker71fe5842014-06-26 15:35:36 -0700530#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
531
532/*
533 * The sideload-host protocol serves the data in a file (given on the
534 * command line) to the client, using a simple protocol:
535 *
536 * - The connect message includes the total number of bytes in the
537 * file and a block size chosen by us.
538 *
539 * - The other side sends the desired block number as eight decimal
540 * digits (eg "00000023" for block 23). Blocks are numbered from
541 * zero.
542 *
543 * - We send back the data of the requested block. The last block is
544 * likely to be partial; when the last block is requested we only
545 * send the part of the block that exists, it's not padded up to the
546 * block size.
547 *
548 * - When the other side sends "DONEDONE" instead of a block number,
549 * we hang up.
550 */
551int adb_sideload_host(const char* fn) {
552 uint8_t* data;
553 unsigned sz;
554 size_t xfer = 0;
555 int status;
556
557 printf("loading: '%s'", fn);
558 fflush(stdout);
559 data = load_file(fn, &sz);
560 if (data == 0) {
561 printf("\n");
562 fprintf(stderr, "* cannot read '%s' *\n", fn);
563 return -1;
564 }
565
566 char buf[100];
567 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
568 int fd = adb_connect(buf);
569 if (fd < 0) {
570 // Try falling back to the older sideload method. Maybe this
571 // is an older device that doesn't support sideload-host.
572 printf("\n");
573 status = adb_download_buffer("sideload", fn, data, sz, 1);
574 goto done;
575 }
576
577 int opt = SIDELOAD_HOST_BLOCK_SIZE;
578 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
579
580 int last_percent = -1;
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700581 for (;;) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700582 if (readx(fd, buf, 8)) {
583 fprintf(stderr, "* failed to read command: %s\n", adb_error());
584 status = -1;
585 goto done;
586 }
587
588 if (strncmp("DONEDONE", buf, 8) == 0) {
589 status = 0;
590 break;
591 }
592
593 buf[8] = '\0';
594 int block = strtol(buf, NULL, 10);
595
596 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
597 if (offset >= sz) {
598 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
599 status = -1;
600 goto done;
601 }
602 uint8_t* start = data + offset;
603 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
604 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
605 if (offset_end > sz) {
606 to_write = sz - offset;
607 }
608
609 if(writex(fd, start, to_write)) {
610 adb_status(fd);
611 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
612 status = -1;
613 goto done;
614 }
615 xfer += to_write;
616
617 // For normal OTA packages, we expect to transfer every byte
618 // twice, plus a bit of overhead (one read during
619 // verification, one read of each byte for installation, plus
620 // extra access to things like the zip central directory).
621 // This estimate of the completion becomes 100% when we've
622 // transferred ~2.13 (=100/47) times the package size.
623 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
624 if (percent != last_percent) {
625 printf("\rserving: '%s' (~%d%%) ", fn, percent);
626 fflush(stdout);
627 last_percent = percent;
628 }
629 }
630
Colin Cross6d6a8982014-07-07 14:12:41 -0700631 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700632
633 done:
634 if (fd >= 0) adb_close(fd);
635 free(data);
636 return status;
637}
638
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800639static void status_window(transport_type ttype, const char* serial)
640{
641 char command[4096];
642 char *state = 0;
643 char *laststate = 0;
644
645 /* silence stderr */
646#ifdef _WIN32
647 /* XXX: TODO */
648#else
649 int fd;
650 fd = unix_open("/dev/null", O_WRONLY);
651 dup2(fd, 2);
652 adb_close(fd);
653#endif
654
655 format_host_command(command, sizeof command, "get-state", ttype, serial);
656
657 for(;;) {
658 adb_sleep_ms(250);
659
660 if(state) {
661 free(state);
662 state = 0;
663 }
664
665 state = adb_query(command);
666
667 if(state) {
668 if(laststate && !strcmp(state,laststate)){
669 continue;
670 } else {
671 if(laststate) free(laststate);
672 laststate = strdup(state);
673 }
674 }
675
676 printf("%c[2J%c[2H", 27, 27);
677 printf("Android Debug Bridge\n");
678 printf("State: %s\n", state ? state : "offline");
679 fflush(stdout);
680 }
681}
682
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700683static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700684{
685 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
686}
687
688/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700689static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800690{
691 const char *ts;
692 size_t alloc_len;
693 char *ret;
694 char *dest;
695
Jeff Sharkey7c460352014-06-10 16:22:17 -0700696 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700697 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800698 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700699 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800700 alloc_len++;
701 }
702 }
703
Jeff Sharkey7c460352014-06-10 16:22:17 -0700704 if (alloc_len == 0) {
705 // Preserve empty arguments
706 ret = (char *) malloc(3);
707 ret[0] = '\"';
708 ret[1] = '\"';
709 ret[2] = '\0';
710 return ret;
711 }
712
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700713 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800714 dest = ret;
715
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700716 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700717 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800718 *dest++ = '\\';
719 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800720 *dest++ = *ts;
721 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800722 *dest++ = '\0';
723
724 return ret;
725}
726
727/**
728 * Run ppp in "notty" mode against a resource listed as the first parameter
729 * eg:
730 *
731 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
732 *
733 */
734int ppp(int argc, char **argv)
735{
736#ifdef HAVE_WIN32_PROC
737 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
738 return -1;
739#else
740 char *adb_service_name;
741 pid_t pid;
742 int fd;
743
744 if (argc < 2) {
745 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
746 argv[0]);
747
748 return 1;
749 }
750
751 adb_service_name = argv[1];
752
753 fd = adb_connect(adb_service_name);
754
755 if(fd < 0) {
756 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
757 adb_service_name, adb_error());
758 return 1;
759 }
760
761 pid = fork();
762
763 if (pid < 0) {
764 perror("from fork()");
765 return 1;
766 } else if (pid == 0) {
767 int err;
768 int i;
769 const char **ppp_args;
770
771 // copy args
772 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
773 ppp_args[0] = "pppd";
774 for (i = 2 ; i < argc ; i++) {
775 //argv[2] and beyond become ppp_args[1] and beyond
776 ppp_args[i - 1] = argv[i];
777 }
778 ppp_args[i-1] = NULL;
779
780 // child side
781
782 dup2(fd, STDIN_FILENO);
783 dup2(fd, STDOUT_FILENO);
784 adb_close(STDERR_FILENO);
785 adb_close(fd);
786
787 err = execvp("pppd", (char * const *)ppp_args);
788
789 if (err < 0) {
790 perror("execing pppd");
791 }
792 exit(-1);
793 } else {
794 // parent side
795
796 adb_close(fd);
797 return 0;
798 }
799#endif /* !HAVE_WIN32_PROC */
800}
801
802static int send_shellcommand(transport_type transport, char* serial, char* buf)
803{
804 int fd, ret;
805
806 for(;;) {
807 fd = adb_connect(buf);
808 if(fd >= 0)
809 break;
810 fprintf(stderr,"- waiting for device -\n");
811 adb_sleep_ms(1000);
812 do_cmd(transport, serial, "wait-for-device", 0);
813 }
814
815 read_and_dump(fd);
816 ret = adb_close(fd);
817 if (ret)
818 perror("close");
819
820 return ret;
821}
822
823static int logcat(transport_type transport, char* serial, int argc, char **argv)
824{
825 char buf[4096];
826
827 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700828 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800829
830 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700831 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800832 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700833 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700834 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700836 if (!strcmp(argv[0], "longcat")) {
837 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800838 }
839
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800840 argc -= 1;
841 argv += 1;
842 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700843 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700844 strncat(buf, " ", sizeof(buf) - 1);
845 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 free(quoted);
847 }
848
849 send_shellcommand(transport, serial, buf);
850 return 0;
851}
852
Mark Salyzyn60299df2014-04-30 09:10:31 -0700853static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800854{
855 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700856 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800857
858 for(;;) {
859 x = adb_dirstart(x);
860 if(x == 0) return 0;
861 *x = 0;
862 ret = adb_mkdir(path, 0775);
863 *x = OS_PATH_SEPARATOR;
864 if((ret < 0) && (errno != EEXIST)) {
865 return ret;
866 }
867 x++;
868 }
869 return 0;
870}
871
Christopher Tated2f54152011-04-21 12:53:28 -0700872static int backup(int argc, char** argv) {
873 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800874 char default_name[32];
875 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700876 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700877 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700878
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700879 /* find, extract, and use any -f argument */
880 for (i = 1; i < argc; i++) {
881 if (!strcmp("-f", argv[i])) {
882 if (i == argc-1) {
883 fprintf(stderr, "adb: -f passed with no filename\n");
884 return usage();
885 }
886 filename = argv[i+1];
887 for (j = i+2; j <= argc; ) {
888 argv[i++] = argv[j++];
889 }
890 argc -= 2;
891 argv[argc] = NULL;
892 }
Christopher Tated2f54152011-04-21 12:53:28 -0700893 }
894
Christopher Tatebb86bc52011-08-22 17:12:08 -0700895 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
896 if (argc < 2) return usage();
897
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800898 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700899 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800900 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700901 if (outFd < 0) {
902 fprintf(stderr, "adb: unable to open file %s\n", filename);
903 return -1;
904 }
905
906 snprintf(buf, sizeof(buf), "backup");
907 for (argc--, argv++; argc; argc--, argv++) {
908 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
909 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
910 }
911
912 D("backup. filename=%s buf=%s\n", filename, buf);
913 fd = adb_connect(buf);
914 if (fd < 0) {
915 fprintf(stderr, "adb: unable to connect for backup\n");
916 adb_close(outFd);
917 return -1;
918 }
919
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800920 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700921 copy_to_file(fd, outFd);
922
923 adb_close(fd);
924 adb_close(outFd);
925 return 0;
926}
927
Christopher Tate702967a2011-05-17 15:52:54 -0700928static int restore(int argc, char** argv) {
929 const char* filename;
930 int fd, tarFd;
931
932 if (argc != 2) return usage();
933
934 filename = argv[1];
935 tarFd = adb_open(filename, O_RDONLY);
936 if (tarFd < 0) {
937 fprintf(stderr, "adb: unable to open file %s\n", filename);
938 return -1;
939 }
940
941 fd = adb_connect("restore:");
942 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700943 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700944 adb_close(tarFd);
945 return -1;
946 }
947
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800948 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700949 copy_to_file(tarFd, fd);
950
951 adb_close(fd);
952 adb_close(tarFd);
953 return 0;
954}
955
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800956#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
957static int top_works(const char *top)
958{
959 if (top != NULL && adb_is_absolute_host_path(top)) {
960 char path_buf[PATH_MAX];
961 snprintf(path_buf, sizeof(path_buf),
962 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
963 return access(path_buf, F_OK) == 0;
964 }
965 return 0;
966}
967
968static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
969{
970 strcpy(path_buf, indir);
971 while (1) {
972 if (top_works(path_buf)) {
973 return path_buf;
974 }
975 char *s = adb_dirstop(path_buf);
976 if (s != NULL) {
977 *s = '\0';
978 } else {
979 path_buf[0] = '\0';
980 return NULL;
981 }
982 }
983}
984
985static char *find_top(char path_buf[PATH_MAX])
986{
987 char *top = getenv("ANDROID_BUILD_TOP");
988 if (top != NULL && top[0] != '\0') {
989 if (!top_works(top)) {
990 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
991 return NULL;
992 }
993 } else {
994 top = getenv("TOP");
995 if (top != NULL && top[0] != '\0') {
996 if (!top_works(top)) {
997 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
998 return NULL;
999 }
1000 } else {
1001 top = NULL;
1002 }
1003 }
1004
1005 if (top != NULL) {
1006 /* The environment pointed to a top directory that works.
1007 */
1008 strcpy(path_buf, top);
1009 return path_buf;
1010 }
1011
1012 /* The environment didn't help. Walk up the tree from the CWD
1013 * to see if we can find the top.
1014 */
1015 char dir[PATH_MAX];
1016 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1017 if (top == NULL) {
1018 /* If the CWD isn't under a good-looking top, see if the
1019 * executable is.
1020 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001021 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001022 top = find_top_from(dir, path_buf);
1023 }
1024 return top;
1025}
1026
1027/* <hint> may be:
1028 * - A simple product name
1029 * e.g., "sooner"
1030TODO: debug? sooner-debug, sooner:debug?
1031 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1032 * e.g., "out/target/product/sooner"
1033 * - An absolute path to the PRODUCT_OUT dir
1034 * e.g., "/src/device/out/target/product/sooner"
1035 *
1036 * Given <hint>, try to construct an absolute path to the
1037 * ANDROID_PRODUCT_OUT dir.
1038 */
1039static const char *find_product_out_path(const char *hint)
1040{
1041 static char path_buf[PATH_MAX];
1042
1043 if (hint == NULL || hint[0] == '\0') {
1044 return NULL;
1045 }
1046
1047 /* If it's already absolute, don't bother doing any work.
1048 */
1049 if (adb_is_absolute_host_path(hint)) {
1050 strcpy(path_buf, hint);
1051 return path_buf;
1052 }
1053
1054 /* If there are any slashes in it, assume it's a relative path;
1055 * make it absolute.
1056 */
1057 if (adb_dirstart(hint) != NULL) {
1058 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1059 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1060 return NULL;
1061 }
1062 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1063 fprintf(stderr, "adb: Couldn't assemble path\n");
1064 return NULL;
1065 }
1066 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1067 strcat(path_buf, hint);
1068 return path_buf;
1069 }
1070
1071 /* It's a string without any slashes. Try to do something with it.
1072 *
1073 * Try to find the root of the build tree, and build a PRODUCT_OUT
1074 * path from there.
1075 */
1076 char top_buf[PATH_MAX];
1077 const char *top = find_top(top_buf);
1078 if (top == NULL) {
1079 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1080 return NULL;
1081 }
1082//TODO: if we have a way to indicate debug, look in out/debug/target/...
1083 snprintf(path_buf, sizeof(path_buf),
1084 "%s" OS_PATH_SEPARATOR_STR
1085 "out" OS_PATH_SEPARATOR_STR
1086 "target" OS_PATH_SEPARATOR_STR
1087 "product" OS_PATH_SEPARATOR_STR
1088 "%s", top_buf, hint);
1089 if (access(path_buf, F_OK) < 0) {
1090 fprintf(stderr, "adb: Couldn't find a product dir "
1091 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1092 return NULL;
1093 }
1094 return path_buf;
1095}
1096
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001097static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1098 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001099 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001100 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001101
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001102 while (narg > 0) {
1103 if (!strcmp(*arg, "-p")) {
1104 *show_progress = 1;
1105 } else if (!strcmp(*arg, "-a")) {
1106 *copy_attrs = 1;
1107 } else {
1108 break;
1109 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001110 ++arg;
1111 --narg;
1112 }
1113
1114 if (narg > 0) {
1115 *path1 = *arg;
1116 ++arg;
1117 --narg;
1118 }
1119
1120 if (narg > 0) {
1121 *path2 = *arg;
1122 }
1123}
1124
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001125int adb_commandline(int argc, char **argv)
1126{
1127 char buf[4096];
1128 int no_daemon = 0;
1129 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001130 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001131 int persist = 0;
1132 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133 transport_type ttype = kTransportAny;
1134 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001135 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001136
1137 /* If defined, this should be an absolute path to
1138 * the directory containing all of the various system images
1139 * for a particular product. If not defined, and the adb
1140 * command requires this information, then the user must
1141 * specify the path using "-p".
1142 */
1143 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1144 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1145 gProductOutPath = NULL;
1146 }
1147 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1148
Nick Pellydb449262009-05-07 12:48:03 -07001149 serial = getenv("ANDROID_SERIAL");
1150
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001151 /* Validate and assign the server port */
1152 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1153 int server_port = DEFAULT_ADB_PORT;
1154 if (server_port_str && strlen(server_port_str) > 0) {
1155 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001156 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001157 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001158 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001159 server_port_str);
1160 return usage();
1161 }
1162 }
1163
1164 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001165 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001166 if(!strcmp(argv[0],"server")) {
1167 is_server = 1;
1168 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001169 no_daemon = 1;
1170 } else if (!strcmp(argv[0], "fork-server")) {
1171 /* this is a special flag used only when the ADB client launches the ADB Server */
1172 is_daemon = 1;
1173 } else if(!strcmp(argv[0],"persist")) {
1174 persist = 1;
1175 } else if(!strncmp(argv[0], "-p", 2)) {
1176 const char *product = NULL;
1177 if (argv[0][2] == '\0') {
1178 if (argc < 2) return usage();
1179 product = argv[1];
1180 argc--;
1181 argv++;
1182 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001183 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001184 }
1185 gProductOutPath = find_product_out_path(product);
1186 if (gProductOutPath == NULL) {
1187 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1188 product);
1189 return usage();
1190 }
1191 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1192 if (isdigit(argv[0][2])) {
1193 serial = argv[0] + 2;
1194 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001195 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001196 serial = argv[1];
1197 argc--;
1198 argv++;
1199 }
1200 } else if (!strcmp(argv[0],"-d")) {
1201 ttype = kTransportUsb;
1202 } else if (!strcmp(argv[0],"-e")) {
1203 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001204 } else if (!strcmp(argv[0],"-a")) {
1205 gListenAll = 1;
1206 } else if(!strncmp(argv[0], "-H", 2)) {
1207 const char *hostname = NULL;
1208 if (argv[0][2] == '\0') {
1209 if (argc < 2) return usage();
1210 hostname = argv[1];
1211 argc--;
1212 argv++;
1213 } else {
1214 hostname = argv[0] + 2;
1215 }
1216 adb_set_tcp_name(hostname);
1217
1218 } else if(!strncmp(argv[0], "-P", 2)) {
1219 if (argv[0][2] == '\0') {
1220 if (argc < 2) return usage();
1221 server_port_str = argv[1];
1222 argc--;
1223 argv++;
1224 } else {
1225 server_port_str = argv[0] + 2;
1226 }
1227 if (strlen(server_port_str) > 0) {
1228 server_port = (int) strtol(server_port_str, NULL, 0);
1229 if (server_port <= 0 || server_port > 65535) {
1230 fprintf(stderr,
1231 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1232 server_port_str);
1233 return usage();
1234 }
1235 } else {
1236 fprintf(stderr,
1237 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1238 return usage();
1239 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001240 } else {
1241 /* out of recognized modifiers and flags */
1242 break;
1243 }
1244 argc--;
1245 argv++;
1246 }
1247
1248 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001249 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001250
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001251 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001252 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001253 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001254 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001255 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001256 }
1257 if(r) {
1258 fprintf(stderr,"* could not start server *\n");
1259 }
1260 return r;
1261 }
1262
1263top:
1264 if(argc == 0) {
1265 return usage();
1266 }
1267
1268 /* adb_connect() commands */
1269
1270 if(!strcmp(argv[0], "devices")) {
1271 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001272 char *listopt;
1273 if (argc < 2)
1274 listopt = "";
1275 else if (argc == 2 && !strcmp(argv[1], "-l"))
1276 listopt = argv[1];
1277 else {
1278 fprintf(stderr, "Usage: adb devices [-l]\n");
1279 return 1;
1280 }
1281 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001282 tmp = adb_query(buf);
1283 if(tmp) {
1284 printf("List of devices attached \n");
1285 printf("%s\n", tmp);
1286 return 0;
1287 } else {
1288 return 1;
1289 }
1290 }
1291
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001292 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001293 char *tmp;
1294 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001295 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001296 return 1;
1297 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001298 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1299 tmp = adb_query(buf);
1300 if(tmp) {
1301 printf("%s\n", tmp);
1302 return 0;
1303 } else {
1304 return 1;
1305 }
1306 }
1307
1308 if(!strcmp(argv[0], "disconnect")) {
1309 char *tmp;
1310 if (argc > 2) {
1311 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1312 return 1;
1313 }
1314 if (argc == 2) {
1315 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1316 } else {
1317 snprintf(buf, sizeof buf, "host:disconnect:");
1318 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001319 tmp = adb_query(buf);
1320 if(tmp) {
1321 printf("%s\n", tmp);
1322 return 0;
1323 } else {
1324 return 1;
1325 }
1326 }
1327
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001328 if (!strcmp(argv[0], "emu")) {
1329 return adb_send_emulator_command(argc, argv);
1330 }
1331
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001332 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001333 int r;
1334 int fd;
1335
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001336 char h = (argv[0][0] == 'h');
1337
1338 if (h) {
1339 printf("\x1b[41;33m");
1340 fflush(stdout);
1341 }
1342
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001343 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001344 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001345 r = interactive_shell();
1346 if (h) {
1347 printf("\x1b[0m");
1348 fflush(stdout);
1349 }
1350 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001351 }
1352
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001353 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001354 argc -= 2;
1355 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001356 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001357 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001358 strncat(buf, " ", sizeof(buf) - 1);
1359 strncat(buf, quoted, sizeof(buf) - 1);
1360 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001361 }
1362
1363 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001364 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001365 fd = adb_connect(buf);
1366 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001367 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001368 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001369 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001370 adb_close(fd);
1371 r = 0;
1372 } else {
1373 fprintf(stderr,"error: %s\n", adb_error());
1374 r = -1;
1375 }
1376
1377 if(persist) {
1378 fprintf(stderr,"\n- waiting for device -\n");
1379 adb_sleep_ms(1000);
1380 do_cmd(ttype, serial, "wait-for-device", 0);
1381 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001382 if (h) {
1383 printf("\x1b[0m");
1384 fflush(stdout);
1385 }
JP Abgrall408fa572011-03-16 15:57:42 -07001386 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001387 return r;
1388 }
1389 }
1390 }
1391
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001392 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1393 int exec_in = !strcmp(argv[0], "exec-in");
1394 int fd;
1395
1396 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1397 argc -= 2;
1398 argv += 2;
1399 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001400 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001401 strncat(buf, " ", sizeof(buf) - 1);
1402 strncat(buf, quoted, sizeof(buf) - 1);
1403 free(quoted);
1404 }
1405
1406 fd = adb_connect(buf);
1407 if (fd < 0) {
1408 fprintf(stderr, "error: %s\n", adb_error());
1409 return -1;
1410 }
1411
1412 if (exec_in) {
1413 copy_to_file(STDIN_FILENO, fd);
1414 } else {
1415 copy_to_file(fd, STDOUT_FILENO);
1416 }
1417
1418 adb_close(fd);
1419 return 0;
1420 }
1421
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001422 if(!strcmp(argv[0], "kill-server")) {
1423 int fd;
1424 fd = _adb_connect("host:kill");
1425 if(fd == -1) {
1426 fprintf(stderr,"* server not running *\n");
1427 return 1;
1428 }
1429 return 0;
1430 }
1431
Doug Zongker447f0612012-01-09 14:54:53 -08001432 if(!strcmp(argv[0], "sideload")) {
1433 if(argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001434 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001435 return 1;
1436 } else {
1437 return 0;
1438 }
1439 }
1440
Mike Lockwoodff196702009-08-24 15:58:40 -07001441 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001442 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001443 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Paul Lawrencebbb36312014-10-09 14:22:49 +00001444 || !strcmp(argv[0], "root") || !strcmp(argv[0], "disable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001445 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001446 if (!strcmp(argv[0], "reboot-bootloader"))
1447 snprintf(command, sizeof(command), "reboot:bootloader");
1448 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001449 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001450 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001451 snprintf(command, sizeof(command), "%s:", argv[0]);
1452 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001453 if(fd >= 0) {
1454 read_and_dump(fd);
1455 adb_close(fd);
1456 return 0;
1457 }
1458 fprintf(stderr,"error: %s\n", adb_error());
1459 return 1;
1460 }
1461
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001462 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001463 if (argc != 1) return usage();
1464 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001465 return 0;
1466 }
1467
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001468 /* adb_command() wrapper commands */
1469
1470 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1471 char* service = argv[0];
1472 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1473 if (ttype == kTransportUsb) {
1474 service = "wait-for-usb";
1475 } else if (ttype == kTransportLocal) {
1476 service = "wait-for-local";
1477 } else {
1478 service = "wait-for-any";
1479 }
1480 }
1481
1482 format_host_command(buf, sizeof buf, service, ttype, serial);
1483
1484 if (adb_command(buf)) {
1485 D("failure: %s *\n",adb_error());
1486 fprintf(stderr,"error: %s\n", adb_error());
1487 return 1;
1488 }
1489
1490 /* Allow a command to be run after wait-for-device,
1491 * e.g. 'adb wait-for-device shell'.
1492 */
1493 if(argc > 1) {
1494 argc--;
1495 argv++;
1496 goto top;
1497 }
1498 return 0;
1499 }
1500
David 'Digit' Turner25258692013-03-21 21:07:42 +01001501 if(!strcmp(argv[0], "forward") ||
1502 !strcmp(argv[0], "reverse"))
1503 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001504 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001505 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001506 char remove = 0;
1507 char remove_all = 0;
1508 char list = 0;
1509 char no_rebind = 0;
1510
1511 // Parse options here.
1512 while (argc > 1 && argv[1][0] == '-') {
1513 if (!strcmp(argv[1], "--list"))
1514 list = 1;
1515 else if (!strcmp(argv[1], "--remove"))
1516 remove = 1;
1517 else if (!strcmp(argv[1], "--remove-all"))
1518 remove_all = 1;
1519 else if (!strcmp(argv[1], "--no-rebind"))
1520 no_rebind = 1;
1521 else {
1522 return usage();
1523 }
1524 argc--;
1525 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001526 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001527
1528 // Ensure we can only use one option at a time.
1529 if (list + remove + remove_all + no_rebind > 1) {
1530 return usage();
1531 }
1532
1533 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001534 if (reverse) {
1535 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001536 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001537 if (serial) {
1538 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1539 serial);
1540 } else if (ttype == kTransportUsb) {
1541 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1542 } else if (ttype == kTransportLocal) {
1543 snprintf(host_prefix, sizeof host_prefix, "host-local");
1544 } else {
1545 snprintf(host_prefix, sizeof host_prefix, "host");
1546 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001547 }
1548
1549 // Implement forward --list
1550 if (list) {
1551 if (argc != 1)
1552 return usage();
1553 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1554 char* forwards = adb_query(buf);
1555 if (forwards == NULL) {
1556 fprintf(stderr, "error: %s\n", adb_error());
1557 return 1;
1558 }
1559 printf("%s", forwards);
1560 free(forwards);
1561 return 0;
1562 }
1563
1564 // Implement forward --remove-all
1565 else if (remove_all) {
1566 if (argc != 1)
1567 return usage();
1568 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1569 }
1570
1571 // Implement forward --remove <local>
1572 else if (remove) {
1573 if (argc != 2)
1574 return usage();
1575 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1576 }
1577 // Or implement one of:
1578 // forward <local> <remote>
1579 // forward --no-rebind <local> <remote>
1580 else
1581 {
1582 if (argc != 3)
1583 return usage();
1584 const char* command = no_rebind ? "forward:norebind:" : "forward";
1585 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1586 }
1587
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001588 if(adb_command(buf)) {
1589 fprintf(stderr,"error: %s\n", adb_error());
1590 return 1;
1591 }
1592 return 0;
1593 }
1594
1595 /* do_sync_*() commands */
1596
1597 if(!strcmp(argv[0], "ls")) {
1598 if(argc != 2) return usage();
1599 return do_sync_ls(argv[1]);
1600 }
1601
1602 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001603 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001604 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001605 const char* lpath = NULL, *rpath = NULL;
1606
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001607 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001608
1609 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001610 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001611 }
1612
1613 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001614 }
1615
1616 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001617 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001618 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001619 const char* rpath = NULL, *lpath = ".";
1620
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001621 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001622
1623 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001624 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001625 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001626
1627 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001628 }
1629
Jeff Sharkey960df972014-06-09 17:30:57 -07001630 if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001631 if (argc < 2) return usage();
1632 return install_app(ttype, serial, argc, argv);
1633 }
1634
Jeff Sharkey960df972014-06-09 17:30:57 -07001635 if (!strcmp(argv[0], "install-multiple")) {
1636 if (argc < 2) return usage();
1637 return install_multiple_app(ttype, serial, argc, argv);
1638 }
1639
1640 if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001641 if (argc < 2) return usage();
1642 return uninstall_app(ttype, serial, argc, argv);
1643 }
1644
1645 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001646 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001647 int listonly = 0;
1648
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001649 int ret;
1650 if(argc < 2) {
1651 /* No local path was specified. */
1652 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001653 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1654 listonly = 1;
1655 if (argc == 3) {
1656 srcarg = argv[2];
1657 } else {
1658 srcarg = NULL;
1659 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001660 } else if(argc == 2) {
1661 /* A local path or "android"/"data" arg was specified. */
1662 srcarg = argv[1];
1663 } else {
1664 return usage();
1665 }
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001666 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001667 if(ret != 0) return usage();
1668
1669 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001670 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001671 if(ret == 0 && vendor_srcpath != NULL)
1672 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001673 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001674 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001675
1676 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001677 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001678 free(data_srcpath);
1679 return ret;
1680 }
1681
1682 /* passthrough commands */
1683
1684 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001685 !strcmp(argv[0],"get-serialno") ||
1686 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 {
1688 char *tmp;
1689
1690 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1691 tmp = adb_query(buf);
1692 if(tmp) {
1693 printf("%s\n", tmp);
1694 return 0;
1695 } else {
1696 return 1;
1697 }
1698 }
1699
1700 /* other commands */
1701
1702 if(!strcmp(argv[0],"status-window")) {
1703 status_window(ttype, serial);
1704 return 0;
1705 }
1706
Christopher Tatedb0a8802011-11-30 13:00:33 -08001707 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001708 return logcat(ttype, serial, argc, argv);
1709 }
1710
1711 if(!strcmp(argv[0],"ppp")) {
1712 return ppp(argc, argv);
1713 }
1714
1715 if (!strcmp(argv[0], "start-server")) {
1716 return adb_connect("host:start-server");
1717 }
1718
Christopher Tated2f54152011-04-21 12:53:28 -07001719 if (!strcmp(argv[0], "backup")) {
1720 return backup(argc, argv);
1721 }
1722
Christopher Tate702967a2011-05-17 15:52:54 -07001723 if (!strcmp(argv[0], "restore")) {
1724 return restore(argc, argv);
1725 }
1726
Nick Kralevich86c9e5f2014-11-13 15:17:29 -08001727 if (!strcmp(argv[0], "keygen")) {
1728 if (argc < 2) return usage();
1729 return adb_auth_keygen(argv[1]);
1730 }
1731
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001732 if (!strcmp(argv[0], "jdwp")) {
1733 int fd = adb_connect("jdwp");
1734 if (fd >= 0) {
1735 read_and_dump(fd);
1736 adb_close(fd);
1737 return 0;
1738 } else {
1739 fprintf(stderr, "error: %s\n", adb_error());
1740 return -1;
1741 }
1742 }
1743
1744 /* "adb /?" is a common idiom under Windows */
1745 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1746 help();
1747 return 0;
1748 }
1749
1750 if(!strcmp(argv[0], "version")) {
1751 version(stdout);
1752 return 0;
1753 }
1754
1755 usage();
1756 return 1;
1757}
1758
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001759#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001760static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1761{
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001762 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001763 int argc;
1764 va_list ap;
1765
1766 va_start(ap, cmd);
1767 argc = 0;
1768
1769 if (serial) {
1770 argv[argc++] = "-s";
1771 argv[argc++] = serial;
1772 } else if (ttype == kTransportUsb) {
1773 argv[argc++] = "-d";
1774 } else if (ttype == kTransportLocal) {
1775 argv[argc++] = "-e";
1776 }
1777
1778 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001779 while(argc < MAX_ARGV_LENGTH &&
1780 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1781 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001782 va_end(ap);
1783
1784#if 0
1785 int n;
1786 fprintf(stderr,"argc = %d\n",argc);
1787 for(n = 0; n < argc; n++) {
1788 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1789 }
1790#endif
1791
1792 return adb_commandline(argc, argv);
1793}
1794
1795int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001796 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001797{
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001798 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1799 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001800
1801 if(srcarg == NULL) {
1802 android_srcdir = product_file("system");
1803 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001804 vendor_srcdir = product_file("vendor");
1805 /* Check if vendor partition exists */
1806 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1807 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001808 } else {
1809 /* srcarg may be "data", "system" or NULL.
1810 * if srcarg is NULL, then both data and system are synced
1811 */
1812 if(strcmp(srcarg, "system") == 0) {
1813 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001814 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001816 } else if(strcmp(srcarg, "vendor") == 0) {
1817 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001818 } else {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001819 /* It's not "system", "vendor", or "data".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001820 */
1821 return 1;
1822 }
1823 }
1824
1825 if(android_srcdir_out != NULL)
1826 *android_srcdir_out = android_srcdir;
1827 else
1828 free(android_srcdir);
1829
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001830 if(vendor_srcdir_out != NULL)
1831 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001832 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001833 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001834
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001835 if(data_srcdir_out != NULL)
1836 *data_srcdir_out = data_srcdir;
1837 else
1838 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001839 return 0;
1840}
1841
1842static int pm_command(transport_type transport, char* serial,
1843 int argc, char** argv)
1844{
1845 char buf[4096];
1846
1847 snprintf(buf, sizeof(buf), "shell:pm");
1848
1849 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001850 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001851 strncat(buf, " ", sizeof(buf) - 1);
1852 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001853 free(quoted);
1854 }
1855
1856 send_shellcommand(transport, serial, buf);
1857 return 0;
1858}
1859
1860int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1861{
1862 /* if the user choose the -k option, we refuse to do it until devices are
1863 out with the option to uninstall the remaining data somehow (adb/ui) */
1864 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1865 {
1866 printf(
1867 "The -k option uninstalls the application while retaining the data/cache.\n"
1868 "At the moment, there is no way to remove the remaining data.\n"
1869 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1870 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1871 return -1;
1872 }
1873
1874 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1875 return pm_command(transport, serial, argc, argv);
1876}
1877
1878static int delete_file(transport_type transport, char* serial, char* filename)
1879{
1880 char buf[4096];
1881 char* quoted;
1882
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001883 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001884 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001885 strncat(buf, quoted, sizeof(buf)-1);
1886 free(quoted);
1887
1888 send_shellcommand(transport, serial, buf);
1889 return 0;
1890}
1891
Kenny Root597ea5b2011-08-05 11:19:45 -07001892static const char* get_basename(const char* filename)
1893{
1894 const char* basename = adb_dirstop(filename);
1895 if (basename) {
1896 basename++;
1897 return basename;
1898 } else {
1899 return filename;
1900 }
1901}
1902
Kenny Root597ea5b2011-08-05 11:19:45 -07001903int install_app(transport_type transport, char* serial, int argc, char** argv)
1904{
1905 static const char *const DATA_DEST = "/data/local/tmp/%s";
1906 static const char *const SD_DEST = "/sdcard/tmp/%s";
1907 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001908 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001909 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001910
1911 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001912 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001913 where = SD_DEST;
1914 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001915 }
1916
Jeff Sharkey960df972014-06-09 17:30:57 -07001917 // Find last APK argument.
1918 // All other arguments passed through verbatim.
1919 int last_apk = -1;
1920 for (i = argc - 1; i >= 0; i--) {
1921 char* file = argv[i];
1922 char* dot = strrchr(file, '.');
1923 if (dot && !strcasecmp(dot, ".apk")) {
1924 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1925 fprintf(stderr, "Invalid APK file: %s\n", file);
1926 return -1;
1927 }
1928
1929 last_apk = i;
1930 break;
1931 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001932 }
1933
Jeff Sharkey960df972014-06-09 17:30:57 -07001934 if (last_apk == -1) {
1935 fprintf(stderr, "Missing APK file\n");
1936 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001937 }
1938
Jeff Sharkey960df972014-06-09 17:30:57 -07001939 char* apk_file = argv[last_apk];
1940 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001941 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001942 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001943 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001944 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001945 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001946 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001947 }
1948
1949 pm_command(transport, serial, argc, argv);
1950
Kenny Root60733e92012-03-26 16:14:02 -07001951cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001952 delete_file(transport, serial, apk_dest);
1953 return err;
1954}
1955
1956int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1957{
1958 char buf[1024];
1959 int i;
1960 struct stat sb;
1961 unsigned long long total_size = 0;
1962
1963 // Find all APK arguments starting at end.
1964 // All other arguments passed through verbatim.
1965 int first_apk = -1;
1966 for (i = argc - 1; i >= 0; i--) {
1967 char* file = argv[i];
1968 char* dot = strrchr(file, '.');
1969 if (dot && !strcasecmp(dot, ".apk")) {
1970 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1971 fprintf(stderr, "Invalid APK file: %s\n", file);
1972 return -1;
1973 }
1974
1975 total_size += sb.st_size;
1976 first_apk = i;
1977 } else {
1978 break;
1979 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001980 }
1981
Jeff Sharkey960df972014-06-09 17:30:57 -07001982 if (first_apk == -1) {
1983 fprintf(stderr, "Missing APK file\n");
1984 return 1;
1985 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001986
Jeff Sharkey960df972014-06-09 17:30:57 -07001987 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1988 for (i = 1; i < first_apk; i++) {
1989 char *quoted = escape_arg(argv[i]);
1990 strncat(buf, " ", sizeof(buf) - 1);
1991 strncat(buf, quoted, sizeof(buf) - 1);
1992 free(quoted);
1993 }
1994
1995 // Create install session
1996 int fd = adb_connect(buf);
1997 if (fd < 0) {
1998 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1999 return -1;
2000 }
2001 read_status_line(fd, buf, sizeof(buf));
2002 adb_close(fd);
2003
2004 int session_id = -1;
2005 if (!strncmp("Success", buf, 7)) {
2006 char* start = strrchr(buf, '[');
2007 char* end = strrchr(buf, ']');
2008 if (start && end) {
2009 *end = '\0';
2010 session_id = strtol(start + 1, NULL, 10);
2011 }
2012 }
2013 if (session_id < 0) {
2014 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002015 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002016 return -1;
2017 }
2018
2019 // Valid session, now stream the APKs
2020 int success = 1;
2021 for (i = first_apk; i < argc; i++) {
2022 char* file = argv[i];
2023 if (stat(file, &sb) == -1) {
2024 fprintf(stderr, "Failed to stat %s\n", file);
2025 success = 0;
2026 goto finalize_session;
2027 }
2028
2029 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002030 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002031
2032 int localFd = adb_open(file, O_RDONLY);
2033 if (localFd < 0) {
2034 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2035 success = 0;
2036 goto finalize_session;
2037 }
2038
2039 int remoteFd = adb_connect(buf);
2040 if (remoteFd < 0) {
2041 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2042 adb_close(localFd);
2043 success = 0;
2044 goto finalize_session;
2045 }
2046
2047 copy_to_file(localFd, remoteFd);
2048 read_status_line(remoteFd, buf, sizeof(buf));
2049
2050 adb_close(localFd);
2051 adb_close(remoteFd);
2052
2053 if (strncmp("Success", buf, 7)) {
2054 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002055 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002056 success = 0;
2057 goto finalize_session;
2058 }
2059 }
2060
2061finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002062 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002063 if (success) {
2064 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2065 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002066 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002067 }
2068
2069 fd = adb_connect(buf);
2070 if (fd < 0) {
2071 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2072 return -1;
2073 }
2074 read_status_line(fd, buf, sizeof(buf));
2075 adb_close(fd);
2076
2077 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002078 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002079 return 0;
2080 } else {
2081 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002082 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002083 return -1;
2084 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002085}