blob: 507f73e6a5ccf9fe4a60c8b52ebb4460b433ca81 [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,
44 char **android_srcdir_out, char **data_srcdir_out);
45int 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"
199 " adb remount - remounts the /system partition 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"
215 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
216 "\n"
217 " - If it is \"system\" or \"data\", only the corresponding partition\n"
218 " 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
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800504static void status_window(transport_type ttype, const char* serial)
505{
506 char command[4096];
507 char *state = 0;
508 char *laststate = 0;
509
510 /* silence stderr */
511#ifdef _WIN32
512 /* XXX: TODO */
513#else
514 int fd;
515 fd = unix_open("/dev/null", O_WRONLY);
516 dup2(fd, 2);
517 adb_close(fd);
518#endif
519
520 format_host_command(command, sizeof command, "get-state", ttype, serial);
521
522 for(;;) {
523 adb_sleep_ms(250);
524
525 if(state) {
526 free(state);
527 state = 0;
528 }
529
530 state = adb_query(command);
531
532 if(state) {
533 if(laststate && !strcmp(state,laststate)){
534 continue;
535 } else {
536 if(laststate) free(laststate);
537 laststate = strdup(state);
538 }
539 }
540
541 printf("%c[2J%c[2H", 27, 27);
542 printf("Android Debug Bridge\n");
543 printf("State: %s\n", state ? state : "offline");
544 fflush(stdout);
545 }
546}
547
Jeff Sharkey824d1062014-06-10 11:31:24 -0700548/** Duplicate and escape given argument. */
Jeff Sharkey026d9622014-06-10 16:22:17 -0700549static char *escape_arg(const char *s)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800550{
551 const char *ts;
552 size_t alloc_len;
553 char *ret;
554 char *dest;
555
Jeff Sharkey026d9622014-06-10 16:22:17 -0700556 alloc_len = 0;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700557 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800558 alloc_len++;
Jeff Sharkey026d9622014-06-10 16:22:17 -0700559 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800560 alloc_len++;
561 }
562 }
563
Jeff Sharkey026d9622014-06-10 16:22:17 -0700564 if (alloc_len == 0) {
565 // Preserve empty arguments
566 ret = (char *) malloc(3);
567 ret[0] = '\"';
568 ret[1] = '\"';
569 ret[2] = '\0';
570 return ret;
571 }
572
Jeff Sharkey824d1062014-06-10 11:31:24 -0700573 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800574 dest = ret;
575
Jeff Sharkey824d1062014-06-10 11:31:24 -0700576 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700577 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800578 *dest++ = '\\';
579 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800580 *dest++ = *ts;
581 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800582 *dest++ = '\0';
583
584 return ret;
585}
586
587/**
588 * Run ppp in "notty" mode against a resource listed as the first parameter
589 * eg:
590 *
591 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
592 *
593 */
594int ppp(int argc, char **argv)
595{
596#ifdef HAVE_WIN32_PROC
597 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
598 return -1;
599#else
600 char *adb_service_name;
601 pid_t pid;
602 int fd;
603
604 if (argc < 2) {
605 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
606 argv[0]);
607
608 return 1;
609 }
610
611 adb_service_name = argv[1];
612
613 fd = adb_connect(adb_service_name);
614
615 if(fd < 0) {
616 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
617 adb_service_name, adb_error());
618 return 1;
619 }
620
621 pid = fork();
622
623 if (pid < 0) {
624 perror("from fork()");
625 return 1;
626 } else if (pid == 0) {
627 int err;
628 int i;
629 const char **ppp_args;
630
631 // copy args
632 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
633 ppp_args[0] = "pppd";
634 for (i = 2 ; i < argc ; i++) {
635 //argv[2] and beyond become ppp_args[1] and beyond
636 ppp_args[i - 1] = argv[i];
637 }
638 ppp_args[i-1] = NULL;
639
640 // child side
641
642 dup2(fd, STDIN_FILENO);
643 dup2(fd, STDOUT_FILENO);
644 adb_close(STDERR_FILENO);
645 adb_close(fd);
646
647 err = execvp("pppd", (char * const *)ppp_args);
648
649 if (err < 0) {
650 perror("execing pppd");
651 }
652 exit(-1);
653 } else {
654 // parent side
655
656 adb_close(fd);
657 return 0;
658 }
659#endif /* !HAVE_WIN32_PROC */
660}
661
662static int send_shellcommand(transport_type transport, char* serial, char* buf)
663{
664 int fd, ret;
665
666 for(;;) {
667 fd = adb_connect(buf);
668 if(fd >= 0)
669 break;
670 fprintf(stderr,"- waiting for device -\n");
671 adb_sleep_ms(1000);
672 do_cmd(transport, serial, "wait-for-device", 0);
673 }
674
675 read_and_dump(fd);
676 ret = adb_close(fd);
677 if (ret)
678 perror("close");
679
680 return ret;
681}
682
683static int logcat(transport_type transport, char* serial, int argc, char **argv)
684{
685 char buf[4096];
686
687 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700688 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800689
690 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey026d9622014-06-10 16:22:17 -0700691 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800692 snprintf(buf, sizeof(buf),
Jeff Sharkey026d9622014-06-10 16:22:17 -0700693 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700694 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800695
Jeff Sharkey824d1062014-06-10 11:31:24 -0700696 if (!strcmp(argv[0], "longcat")) {
697 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800698 }
699
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800700 argc -= 1;
701 argv += 1;
702 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -0700703 quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -0700704 strncat(buf, " ", sizeof(buf) - 1);
705 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800706 free(quoted);
707 }
708
709 send_shellcommand(transport, serial, buf);
710 return 0;
711}
712
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700713static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800714{
715 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700716 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800717
718 for(;;) {
719 x = adb_dirstart(x);
720 if(x == 0) return 0;
721 *x = 0;
722 ret = adb_mkdir(path, 0775);
723 *x = OS_PATH_SEPARATOR;
724 if((ret < 0) && (errno != EEXIST)) {
725 return ret;
726 }
727 x++;
728 }
729 return 0;
730}
731
Christopher Tate73779122011-04-21 12:53:28 -0700732static int backup(int argc, char** argv) {
733 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800734 char default_name[32];
735 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700736 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700737 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700738
Christopher Tatefba22972011-06-01 17:56:23 -0700739 /* find, extract, and use any -f argument */
740 for (i = 1; i < argc; i++) {
741 if (!strcmp("-f", argv[i])) {
742 if (i == argc-1) {
743 fprintf(stderr, "adb: -f passed with no filename\n");
744 return usage();
745 }
746 filename = argv[i+1];
747 for (j = i+2; j <= argc; ) {
748 argv[i++] = argv[j++];
749 }
750 argc -= 2;
751 argv[argc] = NULL;
752 }
Christopher Tate73779122011-04-21 12:53:28 -0700753 }
754
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700755 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
756 if (argc < 2) return usage();
757
Christopher Tate1e9f2392011-12-08 19:04:34 -0800758 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700759 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800760 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700761 if (outFd < 0) {
762 fprintf(stderr, "adb: unable to open file %s\n", filename);
763 return -1;
764 }
765
766 snprintf(buf, sizeof(buf), "backup");
767 for (argc--, argv++; argc; argc--, argv++) {
768 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
769 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
770 }
771
772 D("backup. filename=%s buf=%s\n", filename, buf);
773 fd = adb_connect(buf);
774 if (fd < 0) {
775 fprintf(stderr, "adb: unable to connect for backup\n");
776 adb_close(outFd);
777 return -1;
778 }
779
Christopher Tate9c829102012-01-06 15:43:03 -0800780 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700781 copy_to_file(fd, outFd);
782
783 adb_close(fd);
784 adb_close(outFd);
785 return 0;
786}
787
Christopher Tatecf5379b2011-05-17 15:52:54 -0700788static int restore(int argc, char** argv) {
789 const char* filename;
790 int fd, tarFd;
791
792 if (argc != 2) return usage();
793
794 filename = argv[1];
795 tarFd = adb_open(filename, O_RDONLY);
796 if (tarFd < 0) {
797 fprintf(stderr, "adb: unable to open file %s\n", filename);
798 return -1;
799 }
800
801 fd = adb_connect("restore:");
802 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700803 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700804 adb_close(tarFd);
805 return -1;
806 }
807
Christopher Tate9c829102012-01-06 15:43:03 -0800808 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700809 copy_to_file(tarFd, fd);
810
811 adb_close(fd);
812 adb_close(tarFd);
813 return 0;
814}
815
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800816#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
817static int top_works(const char *top)
818{
819 if (top != NULL && adb_is_absolute_host_path(top)) {
820 char path_buf[PATH_MAX];
821 snprintf(path_buf, sizeof(path_buf),
822 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
823 return access(path_buf, F_OK) == 0;
824 }
825 return 0;
826}
827
828static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
829{
830 strcpy(path_buf, indir);
831 while (1) {
832 if (top_works(path_buf)) {
833 return path_buf;
834 }
835 char *s = adb_dirstop(path_buf);
836 if (s != NULL) {
837 *s = '\0';
838 } else {
839 path_buf[0] = '\0';
840 return NULL;
841 }
842 }
843}
844
845static char *find_top(char path_buf[PATH_MAX])
846{
847 char *top = getenv("ANDROID_BUILD_TOP");
848 if (top != NULL && top[0] != '\0') {
849 if (!top_works(top)) {
850 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
851 return NULL;
852 }
853 } else {
854 top = getenv("TOP");
855 if (top != NULL && top[0] != '\0') {
856 if (!top_works(top)) {
857 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
858 return NULL;
859 }
860 } else {
861 top = NULL;
862 }
863 }
864
865 if (top != NULL) {
866 /* The environment pointed to a top directory that works.
867 */
868 strcpy(path_buf, top);
869 return path_buf;
870 }
871
872 /* The environment didn't help. Walk up the tree from the CWD
873 * to see if we can find the top.
874 */
875 char dir[PATH_MAX];
876 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
877 if (top == NULL) {
878 /* If the CWD isn't under a good-looking top, see if the
879 * executable is.
880 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100881 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800882 top = find_top_from(dir, path_buf);
883 }
884 return top;
885}
886
887/* <hint> may be:
888 * - A simple product name
889 * e.g., "sooner"
890TODO: debug? sooner-debug, sooner:debug?
891 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
892 * e.g., "out/target/product/sooner"
893 * - An absolute path to the PRODUCT_OUT dir
894 * e.g., "/src/device/out/target/product/sooner"
895 *
896 * Given <hint>, try to construct an absolute path to the
897 * ANDROID_PRODUCT_OUT dir.
898 */
899static const char *find_product_out_path(const char *hint)
900{
901 static char path_buf[PATH_MAX];
902
903 if (hint == NULL || hint[0] == '\0') {
904 return NULL;
905 }
906
907 /* If it's already absolute, don't bother doing any work.
908 */
909 if (adb_is_absolute_host_path(hint)) {
910 strcpy(path_buf, hint);
911 return path_buf;
912 }
913
914 /* If there are any slashes in it, assume it's a relative path;
915 * make it absolute.
916 */
917 if (adb_dirstart(hint) != NULL) {
918 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
919 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
920 return NULL;
921 }
922 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
923 fprintf(stderr, "adb: Couldn't assemble path\n");
924 return NULL;
925 }
926 strcat(path_buf, OS_PATH_SEPARATOR_STR);
927 strcat(path_buf, hint);
928 return path_buf;
929 }
930
931 /* It's a string without any slashes. Try to do something with it.
932 *
933 * Try to find the root of the build tree, and build a PRODUCT_OUT
934 * path from there.
935 */
936 char top_buf[PATH_MAX];
937 const char *top = find_top(top_buf);
938 if (top == NULL) {
939 fprintf(stderr, "adb: Couldn't find top of build tree\n");
940 return NULL;
941 }
942//TODO: if we have a way to indicate debug, look in out/debug/target/...
943 snprintf(path_buf, sizeof(path_buf),
944 "%s" OS_PATH_SEPARATOR_STR
945 "out" OS_PATH_SEPARATOR_STR
946 "target" OS_PATH_SEPARATOR_STR
947 "product" OS_PATH_SEPARATOR_STR
948 "%s", top_buf, hint);
949 if (access(path_buf, F_OK) < 0) {
950 fprintf(stderr, "adb: Couldn't find a product dir "
951 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
952 return NULL;
953 }
954 return path_buf;
955}
956
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700957static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
958 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -0700959 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700960 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700961
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700962 while (narg > 0) {
963 if (!strcmp(*arg, "-p")) {
964 *show_progress = 1;
965 } else if (!strcmp(*arg, "-a")) {
966 *copy_attrs = 1;
967 } else {
968 break;
969 }
Mark Lindner9f9d1452014-03-11 17:55:59 -0700970 ++arg;
971 --narg;
972 }
973
974 if (narg > 0) {
975 *path1 = *arg;
976 ++arg;
977 --narg;
978 }
979
980 if (narg > 0) {
981 *path2 = *arg;
982 }
983}
984
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800985int adb_commandline(int argc, char **argv)
986{
987 char buf[4096];
988 int no_daemon = 0;
989 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100990 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800991 int persist = 0;
992 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800993 transport_type ttype = kTransportAny;
994 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100995 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800996
997 /* If defined, this should be an absolute path to
998 * the directory containing all of the various system images
999 * for a particular product. If not defined, and the adb
1000 * command requires this information, then the user must
1001 * specify the path using "-p".
1002 */
1003 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1004 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1005 gProductOutPath = NULL;
1006 }
1007 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1008
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001009 serial = getenv("ANDROID_SERIAL");
1010
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001011 /* Validate and assign the server port */
1012 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1013 int server_port = DEFAULT_ADB_PORT;
1014 if (server_port_str && strlen(server_port_str) > 0) {
1015 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001016 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001017 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001018 "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 +01001019 server_port_str);
1020 return usage();
1021 }
1022 }
1023
1024 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001025 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001026 if(!strcmp(argv[0],"server")) {
1027 is_server = 1;
1028 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001029 no_daemon = 1;
1030 } else if (!strcmp(argv[0], "fork-server")) {
1031 /* this is a special flag used only when the ADB client launches the ADB Server */
1032 is_daemon = 1;
1033 } else if(!strcmp(argv[0],"persist")) {
1034 persist = 1;
1035 } else if(!strncmp(argv[0], "-p", 2)) {
1036 const char *product = NULL;
1037 if (argv[0][2] == '\0') {
1038 if (argc < 2) return usage();
1039 product = argv[1];
1040 argc--;
1041 argv++;
1042 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001043 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001044 }
1045 gProductOutPath = find_product_out_path(product);
1046 if (gProductOutPath == NULL) {
1047 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1048 product);
1049 return usage();
1050 }
1051 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1052 if (isdigit(argv[0][2])) {
1053 serial = argv[0] + 2;
1054 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001055 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001056 serial = argv[1];
1057 argc--;
1058 argv++;
1059 }
1060 } else if (!strcmp(argv[0],"-d")) {
1061 ttype = kTransportUsb;
1062 } else if (!strcmp(argv[0],"-e")) {
1063 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001064 } else if (!strcmp(argv[0],"-a")) {
1065 gListenAll = 1;
1066 } else if(!strncmp(argv[0], "-H", 2)) {
1067 const char *hostname = NULL;
1068 if (argv[0][2] == '\0') {
1069 if (argc < 2) return usage();
1070 hostname = argv[1];
1071 argc--;
1072 argv++;
1073 } else {
1074 hostname = argv[0] + 2;
1075 }
1076 adb_set_tcp_name(hostname);
1077
1078 } else if(!strncmp(argv[0], "-P", 2)) {
1079 if (argv[0][2] == '\0') {
1080 if (argc < 2) return usage();
1081 server_port_str = argv[1];
1082 argc--;
1083 argv++;
1084 } else {
1085 server_port_str = argv[0] + 2;
1086 }
1087 if (strlen(server_port_str) > 0) {
1088 server_port = (int) strtol(server_port_str, NULL, 0);
1089 if (server_port <= 0 || server_port > 65535) {
1090 fprintf(stderr,
1091 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1092 server_port_str);
1093 return usage();
1094 }
1095 } else {
1096 fprintf(stderr,
1097 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1098 return usage();
1099 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001100 } else {
1101 /* out of recognized modifiers and flags */
1102 break;
1103 }
1104 argc--;
1105 argv++;
1106 }
1107
1108 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001109 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001110
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001111 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001112 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001113 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001114 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001115 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001116 }
1117 if(r) {
1118 fprintf(stderr,"* could not start server *\n");
1119 }
1120 return r;
1121 }
1122
1123top:
1124 if(argc == 0) {
1125 return usage();
1126 }
1127
1128 /* adb_connect() commands */
1129
1130 if(!strcmp(argv[0], "devices")) {
1131 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001132 char *listopt;
1133 if (argc < 2)
1134 listopt = "";
1135 else if (argc == 2 && !strcmp(argv[1], "-l"))
1136 listopt = argv[1];
1137 else {
1138 fprintf(stderr, "Usage: adb devices [-l]\n");
1139 return 1;
1140 }
1141 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001142 tmp = adb_query(buf);
1143 if(tmp) {
1144 printf("List of devices attached \n");
1145 printf("%s\n", tmp);
1146 return 0;
1147 } else {
1148 return 1;
1149 }
1150 }
1151
Mike Lockwood01c2c302010-05-24 10:44:35 -04001152 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001153 char *tmp;
1154 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001155 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001156 return 1;
1157 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001158 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1159 tmp = adb_query(buf);
1160 if(tmp) {
1161 printf("%s\n", tmp);
1162 return 0;
1163 } else {
1164 return 1;
1165 }
1166 }
1167
1168 if(!strcmp(argv[0], "disconnect")) {
1169 char *tmp;
1170 if (argc > 2) {
1171 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1172 return 1;
1173 }
1174 if (argc == 2) {
1175 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1176 } else {
1177 snprintf(buf, sizeof buf, "host:disconnect:");
1178 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001179 tmp = adb_query(buf);
1180 if(tmp) {
1181 printf("%s\n", tmp);
1182 return 0;
1183 } else {
1184 return 1;
1185 }
1186 }
1187
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001188 if (!strcmp(argv[0], "emu")) {
1189 return adb_send_emulator_command(argc, argv);
1190 }
1191
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001192 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001193 int r;
1194 int fd;
1195
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001196 char h = (argv[0][0] == 'h');
1197
1198 if (h) {
1199 printf("\x1b[41;33m");
1200 fflush(stdout);
1201 }
1202
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001203 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001204 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001205 r = interactive_shell();
1206 if (h) {
1207 printf("\x1b[0m");
1208 fflush(stdout);
1209 }
1210 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001211 }
1212
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001213 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001214 argc -= 2;
1215 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001216 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001217 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001218 strncat(buf, " ", sizeof(buf) - 1);
1219 strncat(buf, quoted, sizeof(buf) - 1);
1220 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001221 }
1222
1223 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001224 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001225 fd = adb_connect(buf);
1226 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001227 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001228 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001229 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001230 adb_close(fd);
1231 r = 0;
1232 } else {
1233 fprintf(stderr,"error: %s\n", adb_error());
1234 r = -1;
1235 }
1236
1237 if(persist) {
1238 fprintf(stderr,"\n- waiting for device -\n");
1239 adb_sleep_ms(1000);
1240 do_cmd(ttype, serial, "wait-for-device", 0);
1241 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001242 if (h) {
1243 printf("\x1b[0m");
1244 fflush(stdout);
1245 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001246 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001247 return r;
1248 }
1249 }
1250 }
1251
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001252 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1253 int exec_in = !strcmp(argv[0], "exec-in");
1254 int fd;
1255
1256 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1257 argc -= 2;
1258 argv += 2;
1259 while (argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001260 char *quoted = escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001261 strncat(buf, " ", sizeof(buf) - 1);
1262 strncat(buf, quoted, sizeof(buf) - 1);
1263 free(quoted);
1264 }
1265
1266 fd = adb_connect(buf);
1267 if (fd < 0) {
1268 fprintf(stderr, "error: %s\n", adb_error());
1269 return -1;
1270 }
1271
1272 if (exec_in) {
1273 copy_to_file(STDIN_FILENO, fd);
1274 } else {
1275 copy_to_file(fd, STDOUT_FILENO);
1276 }
1277
1278 adb_close(fd);
1279 return 0;
1280 }
1281
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001282 if(!strcmp(argv[0], "kill-server")) {
1283 int fd;
1284 fd = _adb_connect("host:kill");
1285 if(fd == -1) {
1286 fprintf(stderr,"* server not running *\n");
1287 return 1;
1288 }
1289 return 0;
1290 }
1291
Doug Zongker6b217ed2012-01-09 14:54:53 -08001292 if(!strcmp(argv[0], "sideload")) {
1293 if(argc != 2) return usage();
1294 if(adb_download("sideload", argv[1], 1)) {
1295 return 1;
1296 } else {
1297 return 0;
1298 }
1299 }
1300
Mike Lockwood26b88e32009-08-24 15:58:40 -07001301 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001302 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001303 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001304 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001305 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001306 if (!strcmp(argv[0], "reboot-bootloader"))
1307 snprintf(command, sizeof(command), "reboot:bootloader");
1308 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001309 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001310 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001311 snprintf(command, sizeof(command), "%s:", argv[0]);
1312 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001313 if(fd >= 0) {
1314 read_and_dump(fd);
1315 adb_close(fd);
1316 return 0;
1317 }
1318 fprintf(stderr,"error: %s\n", adb_error());
1319 return 1;
1320 }
1321
Mike Lockwood78589f32009-09-03 14:54:58 -04001322 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001323 if (argc != 1) return usage();
1324 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001325 return 0;
1326 }
1327
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001328 /* adb_command() wrapper commands */
1329
1330 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1331 char* service = argv[0];
1332 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1333 if (ttype == kTransportUsb) {
1334 service = "wait-for-usb";
1335 } else if (ttype == kTransportLocal) {
1336 service = "wait-for-local";
1337 } else {
1338 service = "wait-for-any";
1339 }
1340 }
1341
1342 format_host_command(buf, sizeof buf, service, ttype, serial);
1343
1344 if (adb_command(buf)) {
1345 D("failure: %s *\n",adb_error());
1346 fprintf(stderr,"error: %s\n", adb_error());
1347 return 1;
1348 }
1349
1350 /* Allow a command to be run after wait-for-device,
1351 * e.g. 'adb wait-for-device shell'.
1352 */
1353 if(argc > 1) {
1354 argc--;
1355 argv++;
1356 goto top;
1357 }
1358 return 0;
1359 }
1360
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001361 if(!strcmp(argv[0], "forward") ||
1362 !strcmp(argv[0], "reverse"))
1363 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001364 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001365 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001366 char remove = 0;
1367 char remove_all = 0;
1368 char list = 0;
1369 char no_rebind = 0;
1370
1371 // Parse options here.
1372 while (argc > 1 && argv[1][0] == '-') {
1373 if (!strcmp(argv[1], "--list"))
1374 list = 1;
1375 else if (!strcmp(argv[1], "--remove"))
1376 remove = 1;
1377 else if (!strcmp(argv[1], "--remove-all"))
1378 remove_all = 1;
1379 else if (!strcmp(argv[1], "--no-rebind"))
1380 no_rebind = 1;
1381 else {
1382 return usage();
1383 }
1384 argc--;
1385 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001386 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001387
1388 // Ensure we can only use one option at a time.
1389 if (list + remove + remove_all + no_rebind > 1) {
1390 return usage();
1391 }
1392
1393 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001394 if (reverse) {
1395 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001396 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001397 if (serial) {
1398 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1399 serial);
1400 } else if (ttype == kTransportUsb) {
1401 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1402 } else if (ttype == kTransportLocal) {
1403 snprintf(host_prefix, sizeof host_prefix, "host-local");
1404 } else {
1405 snprintf(host_prefix, sizeof host_prefix, "host");
1406 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001407 }
1408
1409 // Implement forward --list
1410 if (list) {
1411 if (argc != 1)
1412 return usage();
1413 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1414 char* forwards = adb_query(buf);
1415 if (forwards == NULL) {
1416 fprintf(stderr, "error: %s\n", adb_error());
1417 return 1;
1418 }
1419 printf("%s", forwards);
1420 free(forwards);
1421 return 0;
1422 }
1423
1424 // Implement forward --remove-all
1425 else if (remove_all) {
1426 if (argc != 1)
1427 return usage();
1428 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1429 }
1430
1431 // Implement forward --remove <local>
1432 else if (remove) {
1433 if (argc != 2)
1434 return usage();
1435 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1436 }
1437 // Or implement one of:
1438 // forward <local> <remote>
1439 // forward --no-rebind <local> <remote>
1440 else
1441 {
1442 if (argc != 3)
1443 return usage();
1444 const char* command = no_rebind ? "forward:norebind:" : "forward";
1445 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1446 }
1447
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001448 if(adb_command(buf)) {
1449 fprintf(stderr,"error: %s\n", adb_error());
1450 return 1;
1451 }
1452 return 0;
1453 }
1454
1455 /* do_sync_*() commands */
1456
1457 if(!strcmp(argv[0], "ls")) {
1458 if(argc != 2) return usage();
1459 return do_sync_ls(argv[1]);
1460 }
1461
1462 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001463 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001464 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001465 const char* lpath = NULL, *rpath = NULL;
1466
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001467 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001468
1469 if ((lpath != NULL) && (rpath != NULL)) {
1470 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1471 }
1472
1473 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001474 }
1475
1476 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001477 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001478 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001479 const char* rpath = NULL, *lpath = ".";
1480
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001481 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001482
1483 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001484 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001485 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001486
1487 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001488 }
1489
1490 if(!strcmp(argv[0], "install")) {
1491 if (argc < 2) return usage();
1492 return install_app(ttype, serial, argc, argv);
1493 }
1494
1495 if(!strcmp(argv[0], "uninstall")) {
1496 if (argc < 2) return usage();
1497 return uninstall_app(ttype, serial, argc, argv);
1498 }
1499
1500 if(!strcmp(argv[0], "sync")) {
1501 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001502 int listonly = 0;
1503
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001504 int ret;
1505 if(argc < 2) {
1506 /* No local path was specified. */
1507 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001508 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1509 listonly = 1;
1510 if (argc == 3) {
1511 srcarg = argv[2];
1512 } else {
1513 srcarg = NULL;
1514 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001515 } else if(argc == 2) {
1516 /* A local path or "android"/"data" arg was specified. */
1517 srcarg = argv[1];
1518 } else {
1519 return usage();
1520 }
1521 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1522 if(ret != 0) return usage();
1523
1524 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001525 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001526 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001527 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001528
1529 free(android_srcpath);
1530 free(data_srcpath);
1531 return ret;
1532 }
1533
1534 /* passthrough commands */
1535
1536 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001537 !strcmp(argv[0],"get-serialno") ||
1538 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001539 {
1540 char *tmp;
1541
1542 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1543 tmp = adb_query(buf);
1544 if(tmp) {
1545 printf("%s\n", tmp);
1546 return 0;
1547 } else {
1548 return 1;
1549 }
1550 }
1551
1552 /* other commands */
1553
1554 if(!strcmp(argv[0],"status-window")) {
1555 status_window(ttype, serial);
1556 return 0;
1557 }
1558
Christopher Tate7b9b5162011-11-30 13:00:33 -08001559 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001560 return logcat(ttype, serial, argc, argv);
1561 }
1562
1563 if(!strcmp(argv[0],"ppp")) {
1564 return ppp(argc, argv);
1565 }
1566
1567 if (!strcmp(argv[0], "start-server")) {
1568 return adb_connect("host:start-server");
1569 }
1570
Christopher Tate73779122011-04-21 12:53:28 -07001571 if (!strcmp(argv[0], "backup")) {
1572 return backup(argc, argv);
1573 }
1574
Christopher Tatecf5379b2011-05-17 15:52:54 -07001575 if (!strcmp(argv[0], "restore")) {
1576 return restore(argc, argv);
1577 }
1578
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001579 if (!strcmp(argv[0], "jdwp")) {
1580 int fd = adb_connect("jdwp");
1581 if (fd >= 0) {
1582 read_and_dump(fd);
1583 adb_close(fd);
1584 return 0;
1585 } else {
1586 fprintf(stderr, "error: %s\n", adb_error());
1587 return -1;
1588 }
1589 }
1590
1591 /* "adb /?" is a common idiom under Windows */
1592 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1593 help();
1594 return 0;
1595 }
1596
1597 if(!strcmp(argv[0], "version")) {
1598 version(stdout);
1599 return 0;
1600 }
1601
1602 usage();
1603 return 1;
1604}
1605
1606static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1607{
1608 char *argv[16];
1609 int argc;
1610 va_list ap;
1611
1612 va_start(ap, cmd);
1613 argc = 0;
1614
1615 if (serial) {
1616 argv[argc++] = "-s";
1617 argv[argc++] = serial;
1618 } else if (ttype == kTransportUsb) {
1619 argv[argc++] = "-d";
1620 } else if (ttype == kTransportLocal) {
1621 argv[argc++] = "-e";
1622 }
1623
1624 argv[argc++] = cmd;
1625 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1626 va_end(ap);
1627
1628#if 0
1629 int n;
1630 fprintf(stderr,"argc = %d\n",argc);
1631 for(n = 0; n < argc; n++) {
1632 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1633 }
1634#endif
1635
1636 return adb_commandline(argc, argv);
1637}
1638
1639int find_sync_dirs(const char *srcarg,
1640 char **android_srcdir_out, char **data_srcdir_out)
1641{
1642 char *android_srcdir, *data_srcdir;
1643
1644 if(srcarg == NULL) {
1645 android_srcdir = product_file("system");
1646 data_srcdir = product_file("data");
1647 } else {
1648 /* srcarg may be "data", "system" or NULL.
1649 * if srcarg is NULL, then both data and system are synced
1650 */
1651 if(strcmp(srcarg, "system") == 0) {
1652 android_srcdir = product_file("system");
1653 data_srcdir = NULL;
1654 } else if(strcmp(srcarg, "data") == 0) {
1655 android_srcdir = NULL;
1656 data_srcdir = product_file("data");
1657 } else {
1658 /* It's not "system" or "data".
1659 */
1660 return 1;
1661 }
1662 }
1663
1664 if(android_srcdir_out != NULL)
1665 *android_srcdir_out = android_srcdir;
1666 else
1667 free(android_srcdir);
1668
1669 if(data_srcdir_out != NULL)
1670 *data_srcdir_out = data_srcdir;
1671 else
1672 free(data_srcdir);
1673
1674 return 0;
1675}
1676
1677static int pm_command(transport_type transport, char* serial,
1678 int argc, char** argv)
1679{
1680 char buf[4096];
1681
1682 snprintf(buf, sizeof(buf), "shell:pm");
1683
1684 while(argc-- > 0) {
Jeff Sharkey026d9622014-06-10 16:22:17 -07001685 char *quoted = escape_arg(*argv++);
Jeff Sharkey824d1062014-06-10 11:31:24 -07001686 strncat(buf, " ", sizeof(buf) - 1);
1687 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001688 free(quoted);
1689 }
1690
1691 send_shellcommand(transport, serial, buf);
1692 return 0;
1693}
1694
1695int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1696{
1697 /* if the user choose the -k option, we refuse to do it until devices are
1698 out with the option to uninstall the remaining data somehow (adb/ui) */
1699 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1700 {
1701 printf(
1702 "The -k option uninstalls the application while retaining the data/cache.\n"
1703 "At the moment, there is no way to remove the remaining data.\n"
1704 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1705 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1706 return -1;
1707 }
1708
1709 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1710 return pm_command(transport, serial, argc, argv);
1711}
1712
1713static int delete_file(transport_type transport, char* serial, char* filename)
1714{
1715 char buf[4096];
1716 char* quoted;
1717
1718 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey026d9622014-06-10 16:22:17 -07001719 quoted = escape_arg(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001720 strncat(buf, quoted, sizeof(buf)-1);
1721 free(quoted);
1722
1723 send_shellcommand(transport, serial, buf);
1724 return 0;
1725}
1726
Kenny Root3802c992011-08-05 11:19:45 -07001727static const char* get_basename(const char* filename)
1728{
1729 const char* basename = adb_dirstop(filename);
1730 if (basename) {
1731 basename++;
1732 return basename;
1733 } else {
1734 return filename;
1735 }
1736}
1737
1738static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001739{
1740 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001741
Kenny Root3802c992011-08-05 11:19:45 -07001742 if (filename == NULL) {
1743 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001744 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001745
Kenny Root3802c992011-08-05 11:19:45 -07001746 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001747 fprintf(stderr, "can't find '%s' to install\n", filename);
1748 return 1;
1749 }
Kenny Root3802c992011-08-05 11:19:45 -07001750
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001751 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001752 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001753 return 1;
1754 }
1755
Kenny Root3802c992011-08-05 11:19:45 -07001756 return 0;
1757}
1758
1759int install_app(transport_type transport, char* serial, int argc, char** argv)
1760{
1761 static const char *const DATA_DEST = "/data/local/tmp/%s";
1762 static const char *const SD_DEST = "/sdcard/tmp/%s";
1763 const char* where = DATA_DEST;
1764 char apk_dest[PATH_MAX];
1765 char verification_dest[PATH_MAX];
1766 char* apk_file;
1767 char* verification_file = NULL;
1768 int file_arg = -1;
1769 int err;
1770 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001771 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001772
1773 for (i = 1; i < argc; i++) {
1774 if (*argv[i] != '-') {
1775 file_arg = i;
1776 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001777 } else if (!strcmp(argv[i], "-i")) {
1778 // Skip the installer package name.
1779 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001780 } else if (!strcmp(argv[i], "-s")) {
1781 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001782 } else if (!strcmp(argv[i], "--algo")) {
1783 verify_apk = 0;
1784 i++;
1785 } else if (!strcmp(argv[i], "--iv")) {
1786 verify_apk = 0;
1787 i++;
1788 } else if (!strcmp(argv[i], "--key")) {
1789 verify_apk = 0;
1790 i++;
Narayan Kamath9416eaa2014-05-29 15:52:02 +01001791 } else if (!strcmp(argv[i], "--abi")) {
1792 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001793 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001794 }
1795
Kenny Root3802c992011-08-05 11:19:45 -07001796 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001797 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001798 return 1;
1799 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001800 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001801 return 1;
1802 }
1803
1804 apk_file = argv[file_arg];
1805
1806 if (file_arg != argc - 1) {
1807 verification_file = argv[file_arg + 1];
1808 }
1809
1810 if (check_file(apk_file) || check_file(verification_file)) {
1811 return 1;
1812 }
1813
1814 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1815 if (verification_file != NULL) {
1816 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1817
1818 if (!strcmp(apk_dest, verification_dest)) {
1819 fprintf(stderr, "APK and verification file can't have the same name\n");
1820 return 1;
1821 }
1822 }
1823
Mark Lindner9f9d1452014-03-11 17:55:59 -07001824 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001825 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001826 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001827 } else {
1828 argv[file_arg] = apk_dest; /* destination name, not source location */
1829 }
1830
1831 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001832 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1833 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001834 if (err) {
1835 goto cleanup_apk;
1836 } else {
1837 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1838 }
1839 }
1840
1841 pm_command(transport, serial, argc, argv);
1842
Kenny Root58d5f222012-03-26 16:14:02 -07001843cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001844 if (verification_file != NULL) {
1845 delete_file(transport, serial, verification_dest);
1846 }
1847
Kenny Root3802c992011-08-05 11:19:45 -07001848 delete_file(transport, serial, apk_dest);
1849
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001850 return err;
1851}