blob: 23722b6d38f50eea658d223341371e401b2e66c8 [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>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov857f17a2009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -070044 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080045int install_app(transport_type transport, char* serial, int argc, char** argv);
46int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47
48static const char *gProductOutPath = NULL;
Matt Gumbel411775c2012-11-14 10:16:17 -080049extern int gListenAll;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080050
51static char *product_file(const char *extra)
52{
53 int n;
54 char *x;
55
56 if (gProductOutPath == NULL) {
57 fprintf(stderr, "adb: Product directory not specified; "
58 "use -p or define ANDROID_PRODUCT_OUT\n");
59 exit(1);
60 }
61
62 n = strlen(gProductOutPath) + strlen(extra) + 2;
63 x = malloc(n);
64 if (x == 0) {
65 fprintf(stderr, "adb: Out of memory (product_file())\n");
66 exit(1);
67 }
68
69 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
70 return x;
71}
72
73void version(FILE * out) {
74 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
75 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
76}
77
78void help()
79{
80 version(stderr);
81
82 fprintf(stderr,
83 "\n"
Matt Gumbel411775c2012-11-14 10:16:17 -080084 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080085 " -d - directs command to the only connected USB device\n"
86 " returns an error if more than one USB device is present.\n"
87 " -e - directs command to the only running emulator.\n"
88 " returns an error if more than one emulator is running.\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -070089 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson27042382012-05-30 18:11:27 -070090 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070091 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080092 " -p <product name or path> - simple product name like 'sooner', or\n"
93 " a relative/absolute path to a product\n"
94 " out directory like 'out/target/product/sooner'.\n"
95 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
96 " environment variable is used, which must\n"
97 " be an absolute path.\n"
Matt Gumbel411775c2012-11-14 10:16:17 -080098 " -H - Name of adb server host (default: localhost)\n"
99 " -P - Port of adb server (default: 5037)\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700100 " devices [-l] - list all connected devices\n"
Scott Anderson27042382012-05-30 18:11:27 -0700101 " ('-l' will also list device qualifiers)\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400102 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
103 " Port 5555 is used by default if no port number is specified.\n"
104 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
105 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischerc3e82b82011-04-26 12:46:05 +0200106 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400107 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800108 "\n"
109 "device commands:\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700110 " adb push [-p] <local> <remote>\n"
111 " - copy file/dir to device\n"
112 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700113 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700114 " - copy file/dir from device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700116 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800117 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600118 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800119 " (see 'adb help all')\n"
120 " adb shell - run remote shell interactively\n"
121 " adb shell <command> - run remote shell command\n"
122 " adb emu <command> - run emulator console command\n"
123 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100124 " adb forward --list - list all forward socket connections.\n"
125 " the format is a list of lines with the following format:\n"
126 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800127 " adb forward <local> <remote> - forward socket connections\n"
128 " forward specs are one of: \n"
129 " tcp:<port>\n"
130 " localabstract:<unix domain socket name>\n"
131 " localreserved:<unix domain socket name>\n"
132 " localfilesystem:<unix domain socket name>\n"
133 " dev:<character device name>\n"
134 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100135 " adb forward --no-rebind <local> <remote>\n"
136 " - same as 'adb forward <local> <remote>' but fails\n"
137 " if <local> is already forwarded\n"
138 " adb forward --remove <local> - remove a specific forward socket connection\n"
139 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner963a4492013-03-21 21:07:42 +0100140 " adb reverse --list - list all reverse socket connections from device\n"
141 " adb reverse <remote> <local> - reverse socket connections\n"
142 " reverse specs are one of:\n"
143 " tcp:<port>\n"
144 " localabstract:<unix domain socket name>\n"
145 " localreserved:<unix domain socket name>\n"
146 " localfilesystem:<unix domain socket name>\n"
147 " adb reverse --norebind <remote> <local>\n"
148 " - same as 'adb reverse <remote> <local>' but fails\n"
149 " if <remote> is already reversed.\n"
150 " adb reverse --remove <remote>\n"
151 " - remove a specific reversed socket connection\n"
152 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800153 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700154 " adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700155 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800156 " ('-l' means forward-lock the app)\n"
157 " ('-r' means reinstall the app, keeping its data)\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700158 " ('-d' means allow version code downgrade)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500159 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700160 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800161 " adb uninstall [-k] <package> - remove this app package from the device\n"
162 " ('-k' means keep the data and cache directories)\n"
163 " adb bugreport - return all information from the device\n"
164 " that should be included in a bug report.\n"
165 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800166 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700167 " - write an archive of the device's data to <file>.\n"
168 " If no -f option is supplied then the data is written\n"
169 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700170 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700171 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800172 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
173 " (aka .obb) files associated with each application; the default\n"
174 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700175 " (-shared|-noshared enable/disable backup of the device's\n"
176 " shared storage / SD card contents; the default is noshared.)\n"
177 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700178 " (-system|-nosystem toggles whether -all automatically includes\n"
179 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700180 " (<packages...> is the list of applications to be backed up. If\n"
181 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700182 " list is optional. Applications explicitly given on the\n"
183 " command line will be included even if -nosystem would\n"
184 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700185 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700186 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700187 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800188 " adb help - show this help message\n"
189 " adb version - show version num\n"
190 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800191 "scripting:\n"
192 " adb wait-for-device - block until device is online\n"
193 " adb start-server - ensure that there is a server running\n"
194 " adb kill-server - kill the server if it is running\n"
195 " adb get-state - prints: offline | bootloader | device\n"
196 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700197 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800198 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700199 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400200 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800201 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700202 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800203 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700204 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800205 "\n"
206 "networking:\n"
207 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500208 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800209 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
210 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
211 "\n"
212 "adb sync notes: adb sync [ <directory> ]\n"
213 " <localdir> can be interpreted in several ways:\n"
214 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700215 " - 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 -0800216 "\n"
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700217 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800218 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000219 "\n"
220 "environmental variables:\n"
221 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
222 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
223 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
224 " 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 -0800225 );
226}
227
228int usage()
229{
230 help();
231 return 1;
232}
233
234#ifdef HAVE_TERMIO_H
235static struct termios tio_save;
236
237static void stdin_raw_init(int fd)
238{
239 struct termios tio;
240
241 if(tcgetattr(fd, &tio)) return;
242 if(tcgetattr(fd, &tio_save)) return;
243
244 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
245
246 /* no timeout but request at least one character per read */
247 tio.c_cc[VTIME] = 0;
248 tio.c_cc[VMIN] = 1;
249
250 tcsetattr(fd, TCSANOW, &tio);
251 tcflush(fd, TCIFLUSH);
252}
253
254static void stdin_raw_restore(int fd)
255{
256 tcsetattr(fd, TCSANOW, &tio_save);
257 tcflush(fd, TCIFLUSH);
258}
259#endif
260
261static void read_and_dump(int fd)
262{
263 char buf[4096];
264 int len;
265
266 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700267 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800268 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700269 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800270 if(len == 0) {
271 break;
272 }
273
274 if(len < 0) {
275 if(errno == EINTR) continue;
276 break;
277 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400278 fwrite(buf, 1, len, stdout);
279 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800280 }
281}
282
Christopher Tate73779122011-04-21 12:53:28 -0700283static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700284 const size_t BUFSIZE = 32 * 1024;
285 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700286 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700287 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700288
289 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700290#ifdef HAVE_TERMIO_H
291 if (inFd == STDIN_FILENO) {
292 stdin_raw_init(STDIN_FILENO);
293 }
294#endif
Christopher Tate73779122011-04-21 12:53:28 -0700295 for (;;) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700296 if (inFd == STDIN_FILENO) {
297 len = unix_read(inFd, buf, BUFSIZE);
298 } else {
299 len = adb_read(inFd, buf, BUFSIZE);
300 }
Christopher Tate73779122011-04-21 12:53:28 -0700301 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700302 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700303 break;
304 }
305 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700306 if (errno == EINTR) {
307 D("copy_to_file() : EINTR, retrying\n");
308 continue;
309 }
Christopher Tate73779122011-04-21 12:53:28 -0700310 D("copy_to_file() : error %d\n", errno);
311 break;
312 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700313 if (outFd == STDOUT_FILENO) {
314 fwrite(buf, 1, len, stdout);
315 fflush(stdout);
316 } else {
317 adb_write(outFd, buf, len);
318 }
Christopher Tatefba22972011-06-01 17:56:23 -0700319 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700320 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700321#ifdef HAVE_TERMIO_H
322 if (inFd == STDIN_FILENO) {
323 stdin_raw_restore(STDIN_FILENO);
324 }
325#endif
Christopher Tatefba22972011-06-01 17:56:23 -0700326 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700327 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700328}
329
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800330static void *stdin_read_thread(void *x)
331{
332 int fd, fdi;
333 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800334 int r, n;
335 int state = 0;
336
337 int *fds = (int*) x;
338 fd = fds[0];
339 fdi = fds[1];
340 free(fds);
341
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800342 for(;;) {
343 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700344 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800345 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700346 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800347 if(r == 0) break;
348 if(r < 0) {
349 if(errno == EINTR) continue;
350 break;
351 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400352 for(n = 0; n < r; n++){
353 switch(buf[n]) {
354 case '\n':
355 state = 1;
356 break;
357 case '\r':
358 state = 1;
359 break;
360 case '~':
361 if(state == 1) state++;
362 break;
363 case '.':
364 if(state == 2) {
365 fprintf(stderr,"\n* disconnect *\n");
366#ifdef HAVE_TERMIO_H
367 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800368#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400369 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800370 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400371 default:
372 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800373 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800374 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800375 r = adb_write(fd, buf, r);
376 if(r <= 0) {
377 break;
378 }
379 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800380 return 0;
381}
382
383int interactive_shell(void)
384{
385 adb_thread_t thr;
386 int fdi, fd;
387 int *fds;
388
389 fd = adb_connect("shell:");
390 if(fd < 0) {
391 fprintf(stderr,"error: %s\n", adb_error());
392 return 1;
393 }
394 fdi = 0; //dup(0);
395
396 fds = malloc(sizeof(int) * 2);
397 fds[0] = fd;
398 fds[1] = fdi;
399
400#ifdef HAVE_TERMIO_H
401 stdin_raw_init(fdi);
402#endif
403 adb_thread_create(&thr, stdin_read_thread, fds);
404 read_and_dump(fd);
405#ifdef HAVE_TERMIO_H
406 stdin_raw_restore(fdi);
407#endif
408 return 0;
409}
410
411
412static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
413{
414 if (serial) {
415 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
416 } else {
417 const char* prefix = "host";
418 if (ttype == kTransportUsb)
419 prefix = "host-usb";
420 else if (ttype == kTransportLocal)
421 prefix = "host-local";
422
423 snprintf(buffer, buflen, "%s:%s", prefix, command);
424 }
425}
426
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100427int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800428 unsigned progress)
429{
430 char buf[4096];
431 unsigned total;
432 int fd;
433 const unsigned char *ptr;
434
435 sprintf(buf,"%s:%d", service, sz);
436 fd = adb_connect(buf);
437 if(fd < 0) {
438 fprintf(stderr,"error: %s\n", adb_error());
439 return -1;
440 }
441
442 int opt = CHUNK_SIZE;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700443 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800444
445 total = sz;
446 ptr = data;
447
448 if(progress) {
449 char *x = strrchr(service, ':');
450 if(x) service = x + 1;
451 }
452
453 while(sz > 0) {
454 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
455 if(writex(fd, ptr, xfer)) {
456 adb_status(fd);
457 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
458 return -1;
459 }
460 sz -= xfer;
461 ptr += xfer;
462 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100463 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800464 fflush(stdout);
465 }
466 }
467 if(progress) {
468 printf("\n");
469 }
470
471 if(readx(fd, buf, 4)){
472 fprintf(stderr,"* error reading response *\n");
473 adb_close(fd);
474 return -1;
475 }
476 if(memcmp(buf, "OKAY", 4)) {
477 buf[4] = 0;
478 fprintf(stderr,"* error response '%s' *\n", buf);
479 adb_close(fd);
480 return -1;
481 }
482
483 adb_close(fd);
484 return 0;
485}
486
487
488int adb_download(const char *service, const char *fn, unsigned progress)
489{
490 void *data;
491 unsigned sz;
492
493 data = load_file(fn, &sz);
494 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100495 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800496 return -1;
497 }
498
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100499 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800500 free(data);
501 return status;
502}
503
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700504#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
505
506/*
507 * The sideload-host protocol serves the data in a file (given on the
508 * command line) to the client, using a simple protocol:
509 *
510 * - The connect message includes the total number of bytes in the
511 * file and a block size chosen by us.
512 *
513 * - The other side sends the desired block number as eight decimal
514 * digits (eg "00000023" for block 23). Blocks are numbered from
515 * zero.
516 *
517 * - We send back the data of the requested block. The last block is
518 * likely to be partial; when the last block is requested we only
519 * send the part of the block that exists, it's not padded up to the
520 * block size.
521 *
522 * - When the other side sends "DONEDONE" instead of a block number,
523 * we hang up.
524 */
525int adb_sideload_host(const char* fn) {
526 uint8_t* data;
527 unsigned sz;
528 size_t xfer = 0;
529 int status;
530
531 printf("loading: '%s'", fn);
532 fflush(stdout);
533 data = load_file(fn, &sz);
534 if (data == 0) {
535 printf("\n");
536 fprintf(stderr, "* cannot read '%s' *\n", fn);
537 return -1;
538 }
539
540 char buf[100];
541 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
542 int fd = adb_connect(buf);
543 if (fd < 0) {
544 // Try falling back to the older sideload method. Maybe this
545 // is an older device that doesn't support sideload-host.
546 printf("\n");
547 status = adb_download_buffer("sideload", fn, data, sz, 1);
548 goto done;
549 }
550
551 int opt = SIDELOAD_HOST_BLOCK_SIZE;
552 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
553
554 int last_percent = -1;
Doug Zongkera27ee6c2014-07-07 15:28:43 -0700555 for (;;) {
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700556 if (readx(fd, buf, 8)) {
557 fprintf(stderr, "* failed to read command: %s\n", adb_error());
558 status = -1;
559 goto done;
560 }
561
562 if (strncmp("DONEDONE", buf, 8) == 0) {
563 status = 0;
564 break;
565 }
566
567 buf[8] = '\0';
568 int block = strtol(buf, NULL, 10);
569
570 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
571 if (offset >= sz) {
572 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
573 status = -1;
574 goto done;
575 }
576 uint8_t* start = data + offset;
577 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
578 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
579 if (offset_end > sz) {
580 to_write = sz - offset;
581 }
582
583 if(writex(fd, start, to_write)) {
584 adb_status(fd);
585 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
586 status = -1;
587 goto done;
588 }
589 xfer += to_write;
590
591 // For normal OTA packages, we expect to transfer every byte
592 // twice, plus a bit of overhead (one read during
593 // verification, one read of each byte for installation, plus
594 // extra access to things like the zip central directory).
595 // This estimate of the completion becomes 100% when we've
596 // transferred ~2.13 (=100/47) times the package size.
597 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
598 if (percent != last_percent) {
599 printf("\rserving: '%s' (~%d%%) ", fn, percent);
600 fflush(stdout);
601 last_percent = percent;
602 }
603 }
604
Colin Cross2328bea2014-07-07 14:12:41 -0700605 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700606
607 done:
608 if (fd >= 0) adb_close(fd);
609 free(data);
610 return status;
611}
612
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800613static void status_window(transport_type ttype, const char* serial)
614{
615 char command[4096];
616 char *state = 0;
617 char *laststate = 0;
618
619 /* silence stderr */
620#ifdef _WIN32
621 /* XXX: TODO */
622#else
623 int fd;
624 fd = unix_open("/dev/null", O_WRONLY);
625 dup2(fd, 2);
626 adb_close(fd);
627#endif
628
629 format_host_command(command, sizeof command, "get-state", ttype, serial);
630
631 for(;;) {
632 adb_sleep_ms(250);
633
634 if(state) {
635 free(state);
636 state = 0;
637 }
638
639 state = adb_query(command);
640
641 if(state) {
642 if(laststate && !strcmp(state,laststate)){
643 continue;
644 } else {
645 if(laststate) free(laststate);
646 laststate = strdup(state);
647 }
648 }
649
650 printf("%c[2J%c[2H", 27, 27);
651 printf("Android Debug Bridge\n");
652 printf("State: %s\n", state ? state : "offline");
653 fflush(stdout);
654 }
655}
656
Jeff Sharkey824d1062014-06-10 11:31:24 -0700657/** Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700658static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800659{
660 const char *ts;
661 size_t alloc_len;
662 char *ret;
663 char *dest;
664
Jeff Sharkey026d9622014-06-10 16:22:17 -0700665 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700666 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800667 alloc_len++;
Jeff Sharkey026d9622014-06-10 16:22:17 -0700668 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800669 alloc_len++;
670 }
671 }
672
Jeff Sharkey026d9622014-06-10 16:22:17 -0700673 if (alloc_len == 0) {
674 // Preserve empty arguments
675 ret = (char *) malloc(3);
676 ret[0] = '\"';
677 ret[1] = '\"';
678 ret[2] = '\0';
679 return ret;
680 }
681
Jeff Sharkey824d1062014-06-10 11:31:24 -0700682 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800683 dest = ret;
684
Jeff Sharkey824d1062014-06-10 11:31:24 -0700685 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700686 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800687 *dest++ = '\\';
688 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800689 *dest++ = *ts;
690 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800691 *dest++ = '\0';
692
693 return ret;
694}
695
696/**
697 * Run ppp in "notty" mode against a resource listed as the first parameter
698 * eg:
699 *
700 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
701 *
702 */
703int ppp(int argc, char **argv)
704{
705#ifdef HAVE_WIN32_PROC
706 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
707 return -1;
708#else
709 char *adb_service_name;
710 pid_t pid;
711 int fd;
712
713 if (argc < 2) {
714 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
715 argv[0]);
716
717 return 1;
718 }
719
720 adb_service_name = argv[1];
721
722 fd = adb_connect(adb_service_name);
723
724 if(fd < 0) {
725 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
726 adb_service_name, adb_error());
727 return 1;
728 }
729
730 pid = fork();
731
732 if (pid < 0) {
733 perror("from fork()");
734 return 1;
735 } else if (pid == 0) {
736 int err;
737 int i;
738 const char **ppp_args;
739
740 // copy args
741 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
742 ppp_args[0] = "pppd";
743 for (i = 2 ; i < argc ; i++) {
744 //argv[2] and beyond become ppp_args[1] and beyond
745 ppp_args[i - 1] = argv[i];
746 }
747 ppp_args[i-1] = NULL;
748
749 // child side
750
751 dup2(fd, STDIN_FILENO);
752 dup2(fd, STDOUT_FILENO);
753 adb_close(STDERR_FILENO);
754 adb_close(fd);
755
756 err = execvp("pppd", (char * const *)ppp_args);
757
758 if (err < 0) {
759 perror("execing pppd");
760 }
761 exit(-1);
762 } else {
763 // parent side
764
765 adb_close(fd);
766 return 0;
767 }
768#endif /* !HAVE_WIN32_PROC */
769}
770
771static int send_shellcommand(transport_type transport, char* serial, char* buf)
772{
773 int fd, ret;
774
775 for(;;) {
776 fd = adb_connect(buf);
777 if(fd >= 0)
778 break;
779 fprintf(stderr,"- waiting for device -\n");
780 adb_sleep_ms(1000);
781 do_cmd(transport, serial, "wait-for-device", 0);
782 }
783
784 read_and_dump(fd);
785 ret = adb_close(fd);
786 if (ret)
787 perror("close");
788
789 return ret;
790}
791
792static int logcat(transport_type transport, char* serial, int argc, char **argv)
793{
794 char buf[4096];
795
796 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700797 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800798
799 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700800 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800801 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700802 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700803 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800804
Jeff Sharkey824d1062014-06-10 11:31:24 -0700805 if (!strcmp(argv[0], "longcat")) {
806 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800807 }
808
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800809 argc -= 1;
810 argv += 1;
811 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700812 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700813 strncat(buf, " ", sizeof(buf) - 1);
814 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800815 free(quoted);
816 }
817
818 send_shellcommand(transport, serial, buf);
819 return 0;
820}
821
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700822static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800823{
824 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700825 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800826
827 for(;;) {
828 x = adb_dirstart(x);
829 if(x == 0) return 0;
830 *x = 0;
831 ret = adb_mkdir(path, 0775);
832 *x = OS_PATH_SEPARATOR;
833 if((ret < 0) && (errno != EEXIST)) {
834 return ret;
835 }
836 x++;
837 }
838 return 0;
839}
840
Christopher Tate73779122011-04-21 12:53:28 -0700841static int backup(int argc, char** argv) {
842 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800843 char default_name[32];
844 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700845 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700846 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700847
Christopher Tatefba22972011-06-01 17:56:23 -0700848 /* find, extract, and use any -f argument */
849 for (i = 1; i < argc; i++) {
850 if (!strcmp("-f", argv[i])) {
851 if (i == argc-1) {
852 fprintf(stderr, "adb: -f passed with no filename\n");
853 return usage();
854 }
855 filename = argv[i+1];
856 for (j = i+2; j <= argc; ) {
857 argv[i++] = argv[j++];
858 }
859 argc -= 2;
860 argv[argc] = NULL;
861 }
Christopher Tate73779122011-04-21 12:53:28 -0700862 }
863
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700864 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
865 if (argc < 2) return usage();
866
Christopher Tate1e9f2392011-12-08 19:04:34 -0800867 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700868 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800869 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700870 if (outFd < 0) {
871 fprintf(stderr, "adb: unable to open file %s\n", filename);
872 return -1;
873 }
874
875 snprintf(buf, sizeof(buf), "backup");
876 for (argc--, argv++; argc; argc--, argv++) {
877 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
878 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
879 }
880
881 D("backup. filename=%s buf=%s\n", filename, buf);
882 fd = adb_connect(buf);
883 if (fd < 0) {
884 fprintf(stderr, "adb: unable to connect for backup\n");
885 adb_close(outFd);
886 return -1;
887 }
888
Christopher Tate9c829102012-01-06 15:43:03 -0800889 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700890 copy_to_file(fd, outFd);
891
892 adb_close(fd);
893 adb_close(outFd);
894 return 0;
895}
896
Christopher Tatecf5379b2011-05-17 15:52:54 -0700897static int restore(int argc, char** argv) {
898 const char* filename;
899 int fd, tarFd;
900
901 if (argc != 2) return usage();
902
903 filename = argv[1];
904 tarFd = adb_open(filename, O_RDONLY);
905 if (tarFd < 0) {
906 fprintf(stderr, "adb: unable to open file %s\n", filename);
907 return -1;
908 }
909
910 fd = adb_connect("restore:");
911 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700912 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700913 adb_close(tarFd);
914 return -1;
915 }
916
Christopher Tate9c829102012-01-06 15:43:03 -0800917 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700918 copy_to_file(tarFd, fd);
919
920 adb_close(fd);
921 adb_close(tarFd);
922 return 0;
923}
924
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800925#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
926static int top_works(const char *top)
927{
928 if (top != NULL && adb_is_absolute_host_path(top)) {
929 char path_buf[PATH_MAX];
930 snprintf(path_buf, sizeof(path_buf),
931 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
932 return access(path_buf, F_OK) == 0;
933 }
934 return 0;
935}
936
937static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
938{
939 strcpy(path_buf, indir);
940 while (1) {
941 if (top_works(path_buf)) {
942 return path_buf;
943 }
944 char *s = adb_dirstop(path_buf);
945 if (s != NULL) {
946 *s = '\0';
947 } else {
948 path_buf[0] = '\0';
949 return NULL;
950 }
951 }
952}
953
954static char *find_top(char path_buf[PATH_MAX])
955{
956 char *top = getenv("ANDROID_BUILD_TOP");
957 if (top != NULL && top[0] != '\0') {
958 if (!top_works(top)) {
959 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
960 return NULL;
961 }
962 } else {
963 top = getenv("TOP");
964 if (top != NULL && top[0] != '\0') {
965 if (!top_works(top)) {
966 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
967 return NULL;
968 }
969 } else {
970 top = NULL;
971 }
972 }
973
974 if (top != NULL) {
975 /* The environment pointed to a top directory that works.
976 */
977 strcpy(path_buf, top);
978 return path_buf;
979 }
980
981 /* The environment didn't help. Walk up the tree from the CWD
982 * to see if we can find the top.
983 */
984 char dir[PATH_MAX];
985 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
986 if (top == NULL) {
987 /* If the CWD isn't under a good-looking top, see if the
988 * executable is.
989 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100990 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800991 top = find_top_from(dir, path_buf);
992 }
993 return top;
994}
995
996/* <hint> may be:
997 * - A simple product name
998 * e.g., "sooner"
999TODO: debug? sooner-debug, sooner:debug?
1000 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1001 * e.g., "out/target/product/sooner"
1002 * - An absolute path to the PRODUCT_OUT dir
1003 * e.g., "/src/device/out/target/product/sooner"
1004 *
1005 * Given <hint>, try to construct an absolute path to the
1006 * ANDROID_PRODUCT_OUT dir.
1007 */
1008static const char *find_product_out_path(const char *hint)
1009{
1010 static char path_buf[PATH_MAX];
1011
1012 if (hint == NULL || hint[0] == '\0') {
1013 return NULL;
1014 }
1015
1016 /* If it's already absolute, don't bother doing any work.
1017 */
1018 if (adb_is_absolute_host_path(hint)) {
1019 strcpy(path_buf, hint);
1020 return path_buf;
1021 }
1022
1023 /* If there are any slashes in it, assume it's a relative path;
1024 * make it absolute.
1025 */
1026 if (adb_dirstart(hint) != NULL) {
1027 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1028 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1029 return NULL;
1030 }
1031 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1032 fprintf(stderr, "adb: Couldn't assemble path\n");
1033 return NULL;
1034 }
1035 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1036 strcat(path_buf, hint);
1037 return path_buf;
1038 }
1039
1040 /* It's a string without any slashes. Try to do something with it.
1041 *
1042 * Try to find the root of the build tree, and build a PRODUCT_OUT
1043 * path from there.
1044 */
1045 char top_buf[PATH_MAX];
1046 const char *top = find_top(top_buf);
1047 if (top == NULL) {
1048 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1049 return NULL;
1050 }
1051//TODO: if we have a way to indicate debug, look in out/debug/target/...
1052 snprintf(path_buf, sizeof(path_buf),
1053 "%s" OS_PATH_SEPARATOR_STR
1054 "out" OS_PATH_SEPARATOR_STR
1055 "target" OS_PATH_SEPARATOR_STR
1056 "product" OS_PATH_SEPARATOR_STR
1057 "%s", top_buf, hint);
1058 if (access(path_buf, F_OK) < 0) {
1059 fprintf(stderr, "adb: Couldn't find a product dir "
1060 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1061 return NULL;
1062 }
1063 return path_buf;
1064}
1065
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001066static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1067 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001068 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001069 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001070
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001071 while (narg > 0) {
1072 if (!strcmp(*arg, "-p")) {
1073 *show_progress = 1;
1074 } else if (!strcmp(*arg, "-a")) {
1075 *copy_attrs = 1;
1076 } else {
1077 break;
1078 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001079 ++arg;
1080 --narg;
1081 }
1082
1083 if (narg > 0) {
1084 *path1 = *arg;
1085 ++arg;
1086 --narg;
1087 }
1088
1089 if (narg > 0) {
1090 *path2 = *arg;
1091 }
1092}
1093
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001094int adb_commandline(int argc, char **argv)
1095{
1096 char buf[4096];
1097 int no_daemon = 0;
1098 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001099 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001100 int persist = 0;
1101 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001102 transport_type ttype = kTransportAny;
1103 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001104 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001105
1106 /* If defined, this should be an absolute path to
1107 * the directory containing all of the various system images
1108 * for a particular product. If not defined, and the adb
1109 * command requires this information, then the user must
1110 * specify the path using "-p".
1111 */
1112 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1113 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1114 gProductOutPath = NULL;
1115 }
1116 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1117
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001118 serial = getenv("ANDROID_SERIAL");
1119
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001120 /* Validate and assign the server port */
1121 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1122 int server_port = DEFAULT_ADB_PORT;
1123 if (server_port_str && strlen(server_port_str) > 0) {
1124 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001125 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001126 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001127 "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 +01001128 server_port_str);
1129 return usage();
1130 }
1131 }
1132
1133 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001134 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001135 if(!strcmp(argv[0],"server")) {
1136 is_server = 1;
1137 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001138 no_daemon = 1;
1139 } else if (!strcmp(argv[0], "fork-server")) {
1140 /* this is a special flag used only when the ADB client launches the ADB Server */
1141 is_daemon = 1;
1142 } else if(!strcmp(argv[0],"persist")) {
1143 persist = 1;
1144 } else if(!strncmp(argv[0], "-p", 2)) {
1145 const char *product = NULL;
1146 if (argv[0][2] == '\0') {
1147 if (argc < 2) return usage();
1148 product = argv[1];
1149 argc--;
1150 argv++;
1151 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001152 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001153 }
1154 gProductOutPath = find_product_out_path(product);
1155 if (gProductOutPath == NULL) {
1156 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1157 product);
1158 return usage();
1159 }
1160 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1161 if (isdigit(argv[0][2])) {
1162 serial = argv[0] + 2;
1163 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001164 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001165 serial = argv[1];
1166 argc--;
1167 argv++;
1168 }
1169 } else if (!strcmp(argv[0],"-d")) {
1170 ttype = kTransportUsb;
1171 } else if (!strcmp(argv[0],"-e")) {
1172 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001173 } else if (!strcmp(argv[0],"-a")) {
1174 gListenAll = 1;
1175 } else if(!strncmp(argv[0], "-H", 2)) {
1176 const char *hostname = NULL;
1177 if (argv[0][2] == '\0') {
1178 if (argc < 2) return usage();
1179 hostname = argv[1];
1180 argc--;
1181 argv++;
1182 } else {
1183 hostname = argv[0] + 2;
1184 }
1185 adb_set_tcp_name(hostname);
1186
1187 } else if(!strncmp(argv[0], "-P", 2)) {
1188 if (argv[0][2] == '\0') {
1189 if (argc < 2) return usage();
1190 server_port_str = argv[1];
1191 argc--;
1192 argv++;
1193 } else {
1194 server_port_str = argv[0] + 2;
1195 }
1196 if (strlen(server_port_str) > 0) {
1197 server_port = (int) strtol(server_port_str, NULL, 0);
1198 if (server_port <= 0 || server_port > 65535) {
1199 fprintf(stderr,
1200 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1201 server_port_str);
1202 return usage();
1203 }
1204 } else {
1205 fprintf(stderr,
1206 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1207 return usage();
1208 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001209 } else {
1210 /* out of recognized modifiers and flags */
1211 break;
1212 }
1213 argc--;
1214 argv++;
1215 }
1216
1217 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001218 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001219
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001220 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001221 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001222 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001223 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001224 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001225 }
1226 if(r) {
1227 fprintf(stderr,"* could not start server *\n");
1228 }
1229 return r;
1230 }
1231
1232top:
1233 if(argc == 0) {
1234 return usage();
1235 }
1236
1237 /* adb_connect() commands */
1238
1239 if(!strcmp(argv[0], "devices")) {
1240 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001241 char *listopt;
1242 if (argc < 2)
1243 listopt = "";
1244 else if (argc == 2 && !strcmp(argv[1], "-l"))
1245 listopt = argv[1];
1246 else {
1247 fprintf(stderr, "Usage: adb devices [-l]\n");
1248 return 1;
1249 }
1250 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001251 tmp = adb_query(buf);
1252 if(tmp) {
1253 printf("List of devices attached \n");
1254 printf("%s\n", tmp);
1255 return 0;
1256 } else {
1257 return 1;
1258 }
1259 }
1260
Mike Lockwood01c2c302010-05-24 10:44:35 -04001261 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001262 char *tmp;
1263 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001264 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001265 return 1;
1266 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001267 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1268 tmp = adb_query(buf);
1269 if(tmp) {
1270 printf("%s\n", tmp);
1271 return 0;
1272 } else {
1273 return 1;
1274 }
1275 }
1276
1277 if(!strcmp(argv[0], "disconnect")) {
1278 char *tmp;
1279 if (argc > 2) {
1280 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1281 return 1;
1282 }
1283 if (argc == 2) {
1284 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1285 } else {
1286 snprintf(buf, sizeof buf, "host:disconnect:");
1287 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001288 tmp = adb_query(buf);
1289 if(tmp) {
1290 printf("%s\n", tmp);
1291 return 0;
1292 } else {
1293 return 1;
1294 }
1295 }
1296
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001297 if (!strcmp(argv[0], "emu")) {
1298 return adb_send_emulator_command(argc, argv);
1299 }
1300
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001301 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001302 int r;
1303 int fd;
1304
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001305 char h = (argv[0][0] == 'h');
1306
1307 if (h) {
1308 printf("\x1b[41;33m");
1309 fflush(stdout);
1310 }
1311
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001312 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001313 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001314 r = interactive_shell();
1315 if (h) {
1316 printf("\x1b[0m");
1317 fflush(stdout);
1318 }
1319 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001320 }
1321
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001322 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001323 argc -= 2;
1324 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001325 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001326 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001327 strncat(buf, " ", sizeof(buf) - 1);
1328 strncat(buf, quoted, sizeof(buf) - 1);
1329 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001330 }
1331
1332 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001333 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001334 fd = adb_connect(buf);
1335 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001336 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001337 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001338 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001339 adb_close(fd);
1340 r = 0;
1341 } else {
1342 fprintf(stderr,"error: %s\n", adb_error());
1343 r = -1;
1344 }
1345
1346 if(persist) {
1347 fprintf(stderr,"\n- waiting for device -\n");
1348 adb_sleep_ms(1000);
1349 do_cmd(ttype, serial, "wait-for-device", 0);
1350 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001351 if (h) {
1352 printf("\x1b[0m");
1353 fflush(stdout);
1354 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001355 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001356 return r;
1357 }
1358 }
1359 }
1360
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001361 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1362 int exec_in = !strcmp(argv[0], "exec-in");
1363 int fd;
1364
1365 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1366 argc -= 2;
1367 argv += 2;
1368 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001369 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001370 strncat(buf, " ", sizeof(buf) - 1);
1371 strncat(buf, quoted, sizeof(buf) - 1);
1372 free(quoted);
1373 }
1374
1375 fd = adb_connect(buf);
1376 if (fd < 0) {
1377 fprintf(stderr, "error: %s\n", adb_error());
1378 return -1;
1379 }
1380
1381 if (exec_in) {
1382 copy_to_file(STDIN_FILENO, fd);
1383 } else {
1384 copy_to_file(fd, STDOUT_FILENO);
1385 }
1386
1387 adb_close(fd);
1388 return 0;
1389 }
1390
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001391 if(!strcmp(argv[0], "kill-server")) {
1392 int fd;
1393 fd = _adb_connect("host:kill");
1394 if(fd == -1) {
1395 fprintf(stderr,"* server not running *\n");
1396 return 1;
1397 }
1398 return 0;
1399 }
1400
Doug Zongker6b217ed2012-01-09 14:54:53 -08001401 if(!strcmp(argv[0], "sideload")) {
1402 if(argc != 2) return usage();
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001403 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001404 return 1;
1405 } else {
1406 return 0;
1407 }
1408 }
1409
Mike Lockwood26b88e32009-08-24 15:58:40 -07001410 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001411 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001412 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001413 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001414 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001415 if (!strcmp(argv[0], "reboot-bootloader"))
1416 snprintf(command, sizeof(command), "reboot:bootloader");
1417 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001418 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001419 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001420 snprintf(command, sizeof(command), "%s:", argv[0]);
1421 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001422 if(fd >= 0) {
1423 read_and_dump(fd);
1424 adb_close(fd);
1425 return 0;
1426 }
1427 fprintf(stderr,"error: %s\n", adb_error());
1428 return 1;
1429 }
1430
Mike Lockwood78589f32009-09-03 14:54:58 -04001431 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001432 if (argc != 1) return usage();
1433 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001434 return 0;
1435 }
1436
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001437 /* adb_command() wrapper commands */
1438
1439 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1440 char* service = argv[0];
1441 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1442 if (ttype == kTransportUsb) {
1443 service = "wait-for-usb";
1444 } else if (ttype == kTransportLocal) {
1445 service = "wait-for-local";
1446 } else {
1447 service = "wait-for-any";
1448 }
1449 }
1450
1451 format_host_command(buf, sizeof buf, service, ttype, serial);
1452
1453 if (adb_command(buf)) {
1454 D("failure: %s *\n",adb_error());
1455 fprintf(stderr,"error: %s\n", adb_error());
1456 return 1;
1457 }
1458
1459 /* Allow a command to be run after wait-for-device,
1460 * e.g. 'adb wait-for-device shell'.
1461 */
1462 if(argc > 1) {
1463 argc--;
1464 argv++;
1465 goto top;
1466 }
1467 return 0;
1468 }
1469
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001470 if(!strcmp(argv[0], "forward") ||
1471 !strcmp(argv[0], "reverse"))
1472 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001473 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001474 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001475 char remove = 0;
1476 char remove_all = 0;
1477 char list = 0;
1478 char no_rebind = 0;
1479
1480 // Parse options here.
1481 while (argc > 1 && argv[1][0] == '-') {
1482 if (!strcmp(argv[1], "--list"))
1483 list = 1;
1484 else if (!strcmp(argv[1], "--remove"))
1485 remove = 1;
1486 else if (!strcmp(argv[1], "--remove-all"))
1487 remove_all = 1;
1488 else if (!strcmp(argv[1], "--no-rebind"))
1489 no_rebind = 1;
1490 else {
1491 return usage();
1492 }
1493 argc--;
1494 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001495 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001496
1497 // Ensure we can only use one option at a time.
1498 if (list + remove + remove_all + no_rebind > 1) {
1499 return usage();
1500 }
1501
1502 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001503 if (reverse) {
1504 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001505 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001506 if (serial) {
1507 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1508 serial);
1509 } else if (ttype == kTransportUsb) {
1510 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1511 } else if (ttype == kTransportLocal) {
1512 snprintf(host_prefix, sizeof host_prefix, "host-local");
1513 } else {
1514 snprintf(host_prefix, sizeof host_prefix, "host");
1515 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001516 }
1517
1518 // Implement forward --list
1519 if (list) {
1520 if (argc != 1)
1521 return usage();
1522 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1523 char* forwards = adb_query(buf);
1524 if (forwards == NULL) {
1525 fprintf(stderr, "error: %s\n", adb_error());
1526 return 1;
1527 }
1528 printf("%s", forwards);
1529 free(forwards);
1530 return 0;
1531 }
1532
1533 // Implement forward --remove-all
1534 else if (remove_all) {
1535 if (argc != 1)
1536 return usage();
1537 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1538 }
1539
1540 // Implement forward --remove <local>
1541 else if (remove) {
1542 if (argc != 2)
1543 return usage();
1544 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1545 }
1546 // Or implement one of:
1547 // forward <local> <remote>
1548 // forward --no-rebind <local> <remote>
1549 else
1550 {
1551 if (argc != 3)
1552 return usage();
1553 const char* command = no_rebind ? "forward:norebind:" : "forward";
1554 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1555 }
1556
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001557 if(adb_command(buf)) {
1558 fprintf(stderr,"error: %s\n", adb_error());
1559 return 1;
1560 }
1561 return 0;
1562 }
1563
1564 /* do_sync_*() commands */
1565
1566 if(!strcmp(argv[0], "ls")) {
1567 if(argc != 2) return usage();
1568 return do_sync_ls(argv[1]);
1569 }
1570
1571 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001572 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001573 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001574 const char* lpath = NULL, *rpath = NULL;
1575
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001576 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001577
1578 if ((lpath != NULL) && (rpath != NULL)) {
1579 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1580 }
1581
1582 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001583 }
1584
1585 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001586 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001587 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001588 const char* rpath = NULL, *lpath = ".";
1589
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001590 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001591
1592 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001593 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001594 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001595
1596 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001597 }
1598
1599 if(!strcmp(argv[0], "install")) {
1600 if (argc < 2) return usage();
1601 return install_app(ttype, serial, argc, argv);
1602 }
1603
1604 if(!strcmp(argv[0], "uninstall")) {
1605 if (argc < 2) return usage();
1606 return uninstall_app(ttype, serial, argc, argv);
1607 }
1608
1609 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001610 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001611 int listonly = 0;
1612
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001613 int ret;
1614 if(argc < 2) {
1615 /* No local path was specified. */
1616 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001617 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1618 listonly = 1;
1619 if (argc == 3) {
1620 srcarg = argv[2];
1621 } else {
1622 srcarg = NULL;
1623 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001624 } else if(argc == 2) {
1625 /* A local path or "android"/"data" arg was specified. */
1626 srcarg = argv[1];
1627 } else {
1628 return usage();
1629 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001630 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001631 if(ret != 0) return usage();
1632
1633 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001634 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001635 if(ret == 0 && vendor_srcpath != NULL)
1636 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001637 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001638 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001639
1640 free(android_srcpath);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001641 free(vendor_srcpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001642 free(data_srcpath);
1643 return ret;
1644 }
1645
1646 /* passthrough commands */
1647
1648 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001649 !strcmp(argv[0],"get-serialno") ||
1650 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001651 {
1652 char *tmp;
1653
1654 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1655 tmp = adb_query(buf);
1656 if(tmp) {
1657 printf("%s\n", tmp);
1658 return 0;
1659 } else {
1660 return 1;
1661 }
1662 }
1663
1664 /* other commands */
1665
1666 if(!strcmp(argv[0],"status-window")) {
1667 status_window(ttype, serial);
1668 return 0;
1669 }
1670
Christopher Tate7b9b5162011-11-30 13:00:33 -08001671 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001672 return logcat(ttype, serial, argc, argv);
1673 }
1674
1675 if(!strcmp(argv[0],"ppp")) {
1676 return ppp(argc, argv);
1677 }
1678
1679 if (!strcmp(argv[0], "start-server")) {
1680 return adb_connect("host:start-server");
1681 }
1682
Christopher Tate73779122011-04-21 12:53:28 -07001683 if (!strcmp(argv[0], "backup")) {
1684 return backup(argc, argv);
1685 }
1686
Christopher Tatecf5379b2011-05-17 15:52:54 -07001687 if (!strcmp(argv[0], "restore")) {
1688 return restore(argc, argv);
1689 }
1690
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001691 if (!strcmp(argv[0], "jdwp")) {
1692 int fd = adb_connect("jdwp");
1693 if (fd >= 0) {
1694 read_and_dump(fd);
1695 adb_close(fd);
1696 return 0;
1697 } else {
1698 fprintf(stderr, "error: %s\n", adb_error());
1699 return -1;
1700 }
1701 }
1702
1703 /* "adb /?" is a common idiom under Windows */
1704 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1705 help();
1706 return 0;
1707 }
1708
1709 if(!strcmp(argv[0], "version")) {
1710 version(stdout);
1711 return 0;
1712 }
1713
1714 usage();
1715 return 1;
1716}
1717
1718static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1719{
1720 char *argv[16];
1721 int argc;
1722 va_list ap;
1723
1724 va_start(ap, cmd);
1725 argc = 0;
1726
1727 if (serial) {
1728 argv[argc++] = "-s";
1729 argv[argc++] = serial;
1730 } else if (ttype == kTransportUsb) {
1731 argv[argc++] = "-d";
1732 } else if (ttype == kTransportLocal) {
1733 argv[argc++] = "-e";
1734 }
1735
1736 argv[argc++] = cmd;
1737 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1738 va_end(ap);
1739
1740#if 0
1741 int n;
1742 fprintf(stderr,"argc = %d\n",argc);
1743 for(n = 0; n < argc; n++) {
1744 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1745 }
1746#endif
1747
1748 return adb_commandline(argc, argv);
1749}
1750
1751int find_sync_dirs(const char *srcarg,
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001752 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001753{
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001754 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1755 struct stat st;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001756
1757 if(srcarg == NULL) {
1758 android_srcdir = product_file("system");
1759 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001760 vendor_srcdir = product_file("vendor");
1761 /* Check if vendor partition exists */
1762 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1763 vendor_srcdir = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001764 } else {
1765 /* srcarg may be "data", "system" or NULL.
1766 * if srcarg is NULL, then both data and system are synced
1767 */
1768 if(strcmp(srcarg, "system") == 0) {
1769 android_srcdir = product_file("system");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001770 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001771 data_srcdir = product_file("data");
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001772 } else if(strcmp(srcarg, "vendor") == 0) {
1773 vendor_srcdir = product_file("vendor");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001774 } else {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001775 /* It's not "system", "vendor", or "data".
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001776 */
1777 return 1;
1778 }
1779 }
1780
1781 if(android_srcdir_out != NULL)
1782 *android_srcdir_out = android_srcdir;
1783 else
1784 free(android_srcdir);
1785
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001786 if(vendor_srcdir_out != NULL)
1787 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001788 else
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001789 free(vendor_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001790
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -07001791 if(data_srcdir_out != NULL)
1792 *data_srcdir_out = data_srcdir;
1793 else
1794 free(data_srcdir);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001795 return 0;
1796}
1797
1798static int pm_command(transport_type transport, char* serial,
1799 int argc, char** argv)
1800{
1801 char buf[4096];
1802
1803 snprintf(buf, sizeof(buf), "shell:pm");
1804
1805 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001806 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001807 strncat(buf, " ", sizeof(buf) - 1);
1808 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001809 free(quoted);
1810 }
1811
1812 send_shellcommand(transport, serial, buf);
1813 return 0;
1814}
1815
1816int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1817{
1818 /* if the user choose the -k option, we refuse to do it until devices are
1819 out with the option to uninstall the remaining data somehow (adb/ui) */
1820 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1821 {
1822 printf(
1823 "The -k option uninstalls the application while retaining the data/cache.\n"
1824 "At the moment, there is no way to remove the remaining data.\n"
1825 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1826 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1827 return -1;
1828 }
1829
1830 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1831 return pm_command(transport, serial, argc, argv);
1832}
1833
1834static int delete_file(transport_type transport, char* serial, char* filename)
1835{
1836 char buf[4096];
1837 char* quoted;
1838
1839 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001840 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001841 strncat(buf, quoted, sizeof(buf)-1);
1842 free(quoted);
1843
1844 send_shellcommand(transport, serial, buf);
1845 return 0;
1846}
1847
Kenny Root3802c992011-08-05 11:19:45 -07001848static const char* get_basename(const char* filename)
1849{
1850 const char* basename = adb_dirstop(filename);
1851 if (basename) {
1852 basename++;
1853 return basename;
1854 } else {
1855 return filename;
1856 }
1857}
1858
1859static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001860{
1861 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001862
Kenny Root3802c992011-08-05 11:19:45 -07001863 if (filename == NULL) {
1864 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001865 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001866
Kenny Root3802c992011-08-05 11:19:45 -07001867 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001868 fprintf(stderr, "can't find '%s' to install\n", filename);
1869 return 1;
1870 }
Kenny Root3802c992011-08-05 11:19:45 -07001871
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001872 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001873 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001874 return 1;
1875 }
1876
Kenny Root3802c992011-08-05 11:19:45 -07001877 return 0;
1878}
1879
1880int install_app(transport_type transport, char* serial, int argc, char** argv)
1881{
1882 static const char *const DATA_DEST = "/data/local/tmp/%s";
1883 static const char *const SD_DEST = "/sdcard/tmp/%s";
1884 const char* where = DATA_DEST;
1885 char apk_dest[PATH_MAX];
1886 char verification_dest[PATH_MAX];
1887 char* apk_file;
1888 char* verification_file = NULL;
1889 int file_arg = -1;
1890 int err;
1891 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001892 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001893
1894 for (i = 1; i < argc; i++) {
1895 if (*argv[i] != '-') {
1896 file_arg = i;
1897 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001898 } else if (!strcmp(argv[i], "-i")) {
1899 // Skip the installer package name.
1900 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001901 } else if (!strcmp(argv[i], "-s")) {
1902 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001903 } else if (!strcmp(argv[i], "--algo")) {
1904 verify_apk = 0;
1905 i++;
1906 } else if (!strcmp(argv[i], "--iv")) {
1907 verify_apk = 0;
1908 i++;
1909 } else if (!strcmp(argv[i], "--key")) {
1910 verify_apk = 0;
1911 i++;
Narayan Kamath9416eaa2014-05-29 15:52:02 +01001912 } else if (!strcmp(argv[i], "--abi")) {
1913 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001914 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001915 }
1916
Kenny Root3802c992011-08-05 11:19:45 -07001917 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001918 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001919 return 1;
1920 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001921 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001922 return 1;
1923 }
1924
1925 apk_file = argv[file_arg];
1926
1927 if (file_arg != argc - 1) {
1928 verification_file = argv[file_arg + 1];
1929 }
1930
1931 if (check_file(apk_file) || check_file(verification_file)) {
1932 return 1;
1933 }
1934
1935 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1936 if (verification_file != NULL) {
1937 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1938
1939 if (!strcmp(apk_dest, verification_dest)) {
1940 fprintf(stderr, "APK and verification file can't have the same name\n");
1941 return 1;
1942 }
1943 }
1944
Mark Lindner9f9d1452014-03-11 17:55:59 -07001945 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001946 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001947 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001948 } else {
1949 argv[file_arg] = apk_dest; /* destination name, not source location */
1950 }
1951
1952 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001953 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1954 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001955 if (err) {
1956 goto cleanup_apk;
1957 } else {
1958 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1959 }
1960 }
1961
1962 pm_command(transport, serial, argc, argv);
1963
Kenny Root58d5f222012-03-26 16:14:02 -07001964cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001965 if (verification_file != NULL) {
1966 delete_file(transport, serial, verification_dest);
1967 }
1968
Kenny Root3802c992011-08-05 11:19:45 -07001969 delete_file(transport, serial, apk_dest);
1970
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001971 return err;
1972}