blob: 32121d36d7f4a23315d93a8fc743801d58edb023 [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. */
549static char *escape_argv(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 Sharkey824d1062014-06-10 11:31:24 -0700556 alloc_len = 2;
557 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800558 alloc_len++;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700559 if (*ts == '"' || *ts == '\\') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800560 alloc_len++;
561 }
562 }
563
Jeff Sharkey824d1062014-06-10 11:31:24 -0700564 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800565 dest = ret;
566
Jeff Sharkey824d1062014-06-10 11:31:24 -0700567 *dest++ = '"';
568 for (ts = s; *ts != '\0'; ts++) {
569 if (*ts == '"' || *ts == '\\') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800570 *dest++ = '\\';
571 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800572 *dest++ = *ts;
573 }
Jeff Sharkey824d1062014-06-10 11:31:24 -0700574 *dest++ = '"';
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800575 *dest++ = '\0';
576
577 return ret;
578}
579
580/**
581 * Run ppp in "notty" mode against a resource listed as the first parameter
582 * eg:
583 *
584 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
585 *
586 */
587int ppp(int argc, char **argv)
588{
589#ifdef HAVE_WIN32_PROC
590 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
591 return -1;
592#else
593 char *adb_service_name;
594 pid_t pid;
595 int fd;
596
597 if (argc < 2) {
598 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
599 argv[0]);
600
601 return 1;
602 }
603
604 adb_service_name = argv[1];
605
606 fd = adb_connect(adb_service_name);
607
608 if(fd < 0) {
609 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
610 adb_service_name, adb_error());
611 return 1;
612 }
613
614 pid = fork();
615
616 if (pid < 0) {
617 perror("from fork()");
618 return 1;
619 } else if (pid == 0) {
620 int err;
621 int i;
622 const char **ppp_args;
623
624 // copy args
625 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
626 ppp_args[0] = "pppd";
627 for (i = 2 ; i < argc ; i++) {
628 //argv[2] and beyond become ppp_args[1] and beyond
629 ppp_args[i - 1] = argv[i];
630 }
631 ppp_args[i-1] = NULL;
632
633 // child side
634
635 dup2(fd, STDIN_FILENO);
636 dup2(fd, STDOUT_FILENO);
637 adb_close(STDERR_FILENO);
638 adb_close(fd);
639
640 err = execvp("pppd", (char * const *)ppp_args);
641
642 if (err < 0) {
643 perror("execing pppd");
644 }
645 exit(-1);
646 } else {
647 // parent side
648
649 adb_close(fd);
650 return 0;
651 }
652#endif /* !HAVE_WIN32_PROC */
653}
654
655static int send_shellcommand(transport_type transport, char* serial, char* buf)
656{
657 int fd, ret;
658
659 for(;;) {
660 fd = adb_connect(buf);
661 if(fd >= 0)
662 break;
663 fprintf(stderr,"- waiting for device -\n");
664 adb_sleep_ms(1000);
665 do_cmd(transport, serial, "wait-for-device", 0);
666 }
667
668 read_and_dump(fd);
669 ret = adb_close(fd);
670 if (ret)
671 perror("close");
672
673 return ret;
674}
675
676static int logcat(transport_type transport, char* serial, int argc, char **argv)
677{
678 char buf[4096];
679
680 char *log_tags;
Jeff Sharkey824d1062014-06-10 11:31:24 -0700681 char *quoted;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800682
683 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey824d1062014-06-10 11:31:24 -0700684 quoted = escape_argv(log_tags == NULL ? "" : log_tags);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800685 snprintf(buf, sizeof(buf),
Jeff Sharkey824d1062014-06-10 11:31:24 -0700686 "shell:export ANDROID_LOG_TAGS=%s ; exec logcat", quoted);
687 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800688
Jeff Sharkey824d1062014-06-10 11:31:24 -0700689 if (!strcmp(argv[0], "longcat")) {
690 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tate7b9b5162011-11-30 13:00:33 -0800691 }
692
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800693 argc -= 1;
694 argv += 1;
695 while(argc-- > 0) {
Jeff Sharkey824d1062014-06-10 11:31:24 -0700696 quoted = escape_argv(*argv++);
697 strncat(buf, " ", sizeof(buf) - 1);
698 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800699 free(quoted);
700 }
701
702 send_shellcommand(transport, serial, buf);
703 return 0;
704}
705
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700706static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800707{
708 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700709 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800710
711 for(;;) {
712 x = adb_dirstart(x);
713 if(x == 0) return 0;
714 *x = 0;
715 ret = adb_mkdir(path, 0775);
716 *x = OS_PATH_SEPARATOR;
717 if((ret < 0) && (errno != EEXIST)) {
718 return ret;
719 }
720 x++;
721 }
722 return 0;
723}
724
Christopher Tate73779122011-04-21 12:53:28 -0700725static int backup(int argc, char** argv) {
726 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800727 char default_name[32];
728 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700729 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700730 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700731
Christopher Tatefba22972011-06-01 17:56:23 -0700732 /* find, extract, and use any -f argument */
733 for (i = 1; i < argc; i++) {
734 if (!strcmp("-f", argv[i])) {
735 if (i == argc-1) {
736 fprintf(stderr, "adb: -f passed with no filename\n");
737 return usage();
738 }
739 filename = argv[i+1];
740 for (j = i+2; j <= argc; ) {
741 argv[i++] = argv[j++];
742 }
743 argc -= 2;
744 argv[argc] = NULL;
745 }
Christopher Tate73779122011-04-21 12:53:28 -0700746 }
747
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700748 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
749 if (argc < 2) return usage();
750
Christopher Tate1e9f2392011-12-08 19:04:34 -0800751 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700752 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800753 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700754 if (outFd < 0) {
755 fprintf(stderr, "adb: unable to open file %s\n", filename);
756 return -1;
757 }
758
759 snprintf(buf, sizeof(buf), "backup");
760 for (argc--, argv++; argc; argc--, argv++) {
761 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
762 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
763 }
764
765 D("backup. filename=%s buf=%s\n", filename, buf);
766 fd = adb_connect(buf);
767 if (fd < 0) {
768 fprintf(stderr, "adb: unable to connect for backup\n");
769 adb_close(outFd);
770 return -1;
771 }
772
Christopher Tate9c829102012-01-06 15:43:03 -0800773 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700774 copy_to_file(fd, outFd);
775
776 adb_close(fd);
777 adb_close(outFd);
778 return 0;
779}
780
Christopher Tatecf5379b2011-05-17 15:52:54 -0700781static int restore(int argc, char** argv) {
782 const char* filename;
783 int fd, tarFd;
784
785 if (argc != 2) return usage();
786
787 filename = argv[1];
788 tarFd = adb_open(filename, O_RDONLY);
789 if (tarFd < 0) {
790 fprintf(stderr, "adb: unable to open file %s\n", filename);
791 return -1;
792 }
793
794 fd = adb_connect("restore:");
795 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700796 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700797 adb_close(tarFd);
798 return -1;
799 }
800
Christopher Tate9c829102012-01-06 15:43:03 -0800801 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700802 copy_to_file(tarFd, fd);
803
804 adb_close(fd);
805 adb_close(tarFd);
806 return 0;
807}
808
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800809#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
810static int top_works(const char *top)
811{
812 if (top != NULL && adb_is_absolute_host_path(top)) {
813 char path_buf[PATH_MAX];
814 snprintf(path_buf, sizeof(path_buf),
815 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
816 return access(path_buf, F_OK) == 0;
817 }
818 return 0;
819}
820
821static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
822{
823 strcpy(path_buf, indir);
824 while (1) {
825 if (top_works(path_buf)) {
826 return path_buf;
827 }
828 char *s = adb_dirstop(path_buf);
829 if (s != NULL) {
830 *s = '\0';
831 } else {
832 path_buf[0] = '\0';
833 return NULL;
834 }
835 }
836}
837
838static char *find_top(char path_buf[PATH_MAX])
839{
840 char *top = getenv("ANDROID_BUILD_TOP");
841 if (top != NULL && top[0] != '\0') {
842 if (!top_works(top)) {
843 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
844 return NULL;
845 }
846 } else {
847 top = getenv("TOP");
848 if (top != NULL && top[0] != '\0') {
849 if (!top_works(top)) {
850 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
851 return NULL;
852 }
853 } else {
854 top = NULL;
855 }
856 }
857
858 if (top != NULL) {
859 /* The environment pointed to a top directory that works.
860 */
861 strcpy(path_buf, top);
862 return path_buf;
863 }
864
865 /* The environment didn't help. Walk up the tree from the CWD
866 * to see if we can find the top.
867 */
868 char dir[PATH_MAX];
869 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
870 if (top == NULL) {
871 /* If the CWD isn't under a good-looking top, see if the
872 * executable is.
873 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100874 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800875 top = find_top_from(dir, path_buf);
876 }
877 return top;
878}
879
880/* <hint> may be:
881 * - A simple product name
882 * e.g., "sooner"
883TODO: debug? sooner-debug, sooner:debug?
884 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
885 * e.g., "out/target/product/sooner"
886 * - An absolute path to the PRODUCT_OUT dir
887 * e.g., "/src/device/out/target/product/sooner"
888 *
889 * Given <hint>, try to construct an absolute path to the
890 * ANDROID_PRODUCT_OUT dir.
891 */
892static const char *find_product_out_path(const char *hint)
893{
894 static char path_buf[PATH_MAX];
895
896 if (hint == NULL || hint[0] == '\0') {
897 return NULL;
898 }
899
900 /* If it's already absolute, don't bother doing any work.
901 */
902 if (adb_is_absolute_host_path(hint)) {
903 strcpy(path_buf, hint);
904 return path_buf;
905 }
906
907 /* If there are any slashes in it, assume it's a relative path;
908 * make it absolute.
909 */
910 if (adb_dirstart(hint) != NULL) {
911 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
912 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
913 return NULL;
914 }
915 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
916 fprintf(stderr, "adb: Couldn't assemble path\n");
917 return NULL;
918 }
919 strcat(path_buf, OS_PATH_SEPARATOR_STR);
920 strcat(path_buf, hint);
921 return path_buf;
922 }
923
924 /* It's a string without any slashes. Try to do something with it.
925 *
926 * Try to find the root of the build tree, and build a PRODUCT_OUT
927 * path from there.
928 */
929 char top_buf[PATH_MAX];
930 const char *top = find_top(top_buf);
931 if (top == NULL) {
932 fprintf(stderr, "adb: Couldn't find top of build tree\n");
933 return NULL;
934 }
935//TODO: if we have a way to indicate debug, look in out/debug/target/...
936 snprintf(path_buf, sizeof(path_buf),
937 "%s" OS_PATH_SEPARATOR_STR
938 "out" OS_PATH_SEPARATOR_STR
939 "target" OS_PATH_SEPARATOR_STR
940 "product" OS_PATH_SEPARATOR_STR
941 "%s", top_buf, hint);
942 if (access(path_buf, F_OK) < 0) {
943 fprintf(stderr, "adb: Couldn't find a product dir "
944 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
945 return NULL;
946 }
947 return path_buf;
948}
949
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700950static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
951 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -0700952 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700953 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700954
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700955 while (narg > 0) {
956 if (!strcmp(*arg, "-p")) {
957 *show_progress = 1;
958 } else if (!strcmp(*arg, "-a")) {
959 *copy_attrs = 1;
960 } else {
961 break;
962 }
Mark Lindner9f9d1452014-03-11 17:55:59 -0700963 ++arg;
964 --narg;
965 }
966
967 if (narg > 0) {
968 *path1 = *arg;
969 ++arg;
970 --narg;
971 }
972
973 if (narg > 0) {
974 *path2 = *arg;
975 }
976}
977
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800978int adb_commandline(int argc, char **argv)
979{
980 char buf[4096];
981 int no_daemon = 0;
982 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100983 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800984 int persist = 0;
985 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800986 transport_type ttype = kTransportAny;
987 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100988 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800989
990 /* If defined, this should be an absolute path to
991 * the directory containing all of the various system images
992 * for a particular product. If not defined, and the adb
993 * command requires this information, then the user must
994 * specify the path using "-p".
995 */
996 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
997 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
998 gProductOutPath = NULL;
999 }
1000 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1001
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001002 serial = getenv("ANDROID_SERIAL");
1003
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001004 /* Validate and assign the server port */
1005 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1006 int server_port = DEFAULT_ADB_PORT;
1007 if (server_port_str && strlen(server_port_str) > 0) {
1008 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001009 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001010 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001011 "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 +01001012 server_port_str);
1013 return usage();
1014 }
1015 }
1016
1017 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001018 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001019 if(!strcmp(argv[0],"server")) {
1020 is_server = 1;
1021 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001022 no_daemon = 1;
1023 } else if (!strcmp(argv[0], "fork-server")) {
1024 /* this is a special flag used only when the ADB client launches the ADB Server */
1025 is_daemon = 1;
1026 } else if(!strcmp(argv[0],"persist")) {
1027 persist = 1;
1028 } else if(!strncmp(argv[0], "-p", 2)) {
1029 const char *product = NULL;
1030 if (argv[0][2] == '\0') {
1031 if (argc < 2) return usage();
1032 product = argv[1];
1033 argc--;
1034 argv++;
1035 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001036 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001037 }
1038 gProductOutPath = find_product_out_path(product);
1039 if (gProductOutPath == NULL) {
1040 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1041 product);
1042 return usage();
1043 }
1044 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1045 if (isdigit(argv[0][2])) {
1046 serial = argv[0] + 2;
1047 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001048 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001049 serial = argv[1];
1050 argc--;
1051 argv++;
1052 }
1053 } else if (!strcmp(argv[0],"-d")) {
1054 ttype = kTransportUsb;
1055 } else if (!strcmp(argv[0],"-e")) {
1056 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001057 } else if (!strcmp(argv[0],"-a")) {
1058 gListenAll = 1;
1059 } else if(!strncmp(argv[0], "-H", 2)) {
1060 const char *hostname = NULL;
1061 if (argv[0][2] == '\0') {
1062 if (argc < 2) return usage();
1063 hostname = argv[1];
1064 argc--;
1065 argv++;
1066 } else {
1067 hostname = argv[0] + 2;
1068 }
1069 adb_set_tcp_name(hostname);
1070
1071 } else if(!strncmp(argv[0], "-P", 2)) {
1072 if (argv[0][2] == '\0') {
1073 if (argc < 2) return usage();
1074 server_port_str = argv[1];
1075 argc--;
1076 argv++;
1077 } else {
1078 server_port_str = argv[0] + 2;
1079 }
1080 if (strlen(server_port_str) > 0) {
1081 server_port = (int) strtol(server_port_str, NULL, 0);
1082 if (server_port <= 0 || server_port > 65535) {
1083 fprintf(stderr,
1084 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1085 server_port_str);
1086 return usage();
1087 }
1088 } else {
1089 fprintf(stderr,
1090 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1091 return usage();
1092 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001093 } else {
1094 /* out of recognized modifiers and flags */
1095 break;
1096 }
1097 argc--;
1098 argv++;
1099 }
1100
1101 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001102 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001103
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001104 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001105 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001106 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001107 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001108 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001109 }
1110 if(r) {
1111 fprintf(stderr,"* could not start server *\n");
1112 }
1113 return r;
1114 }
1115
1116top:
1117 if(argc == 0) {
1118 return usage();
1119 }
1120
1121 /* adb_connect() commands */
1122
1123 if(!strcmp(argv[0], "devices")) {
1124 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001125 char *listopt;
1126 if (argc < 2)
1127 listopt = "";
1128 else if (argc == 2 && !strcmp(argv[1], "-l"))
1129 listopt = argv[1];
1130 else {
1131 fprintf(stderr, "Usage: adb devices [-l]\n");
1132 return 1;
1133 }
1134 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001135 tmp = adb_query(buf);
1136 if(tmp) {
1137 printf("List of devices attached \n");
1138 printf("%s\n", tmp);
1139 return 0;
1140 } else {
1141 return 1;
1142 }
1143 }
1144
Mike Lockwood01c2c302010-05-24 10:44:35 -04001145 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001146 char *tmp;
1147 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001148 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001149 return 1;
1150 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001151 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1152 tmp = adb_query(buf);
1153 if(tmp) {
1154 printf("%s\n", tmp);
1155 return 0;
1156 } else {
1157 return 1;
1158 }
1159 }
1160
1161 if(!strcmp(argv[0], "disconnect")) {
1162 char *tmp;
1163 if (argc > 2) {
1164 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1165 return 1;
1166 }
1167 if (argc == 2) {
1168 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1169 } else {
1170 snprintf(buf, sizeof buf, "host:disconnect:");
1171 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001172 tmp = adb_query(buf);
1173 if(tmp) {
1174 printf("%s\n", tmp);
1175 return 0;
1176 } else {
1177 return 1;
1178 }
1179 }
1180
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001181 if (!strcmp(argv[0], "emu")) {
1182 return adb_send_emulator_command(argc, argv);
1183 }
1184
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001185 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001186 int r;
1187 int fd;
1188
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001189 char h = (argv[0][0] == 'h');
1190
1191 if (h) {
1192 printf("\x1b[41;33m");
1193 fflush(stdout);
1194 }
1195
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001196 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001197 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001198 r = interactive_shell();
1199 if (h) {
1200 printf("\x1b[0m");
1201 fflush(stdout);
1202 }
1203 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001204 }
1205
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001206 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001207 argc -= 2;
1208 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001209 while (argc-- > 0) {
Jeff Sharkey824d1062014-06-10 11:31:24 -07001210 char *quoted = escape_argv(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001211 strncat(buf, " ", sizeof(buf) - 1);
1212 strncat(buf, quoted, sizeof(buf) - 1);
1213 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001214 }
1215
1216 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001217 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001218 fd = adb_connect(buf);
1219 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001220 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001221 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001222 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001223 adb_close(fd);
1224 r = 0;
1225 } else {
1226 fprintf(stderr,"error: %s\n", adb_error());
1227 r = -1;
1228 }
1229
1230 if(persist) {
1231 fprintf(stderr,"\n- waiting for device -\n");
1232 adb_sleep_ms(1000);
1233 do_cmd(ttype, serial, "wait-for-device", 0);
1234 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001235 if (h) {
1236 printf("\x1b[0m");
1237 fflush(stdout);
1238 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001239 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001240 return r;
1241 }
1242 }
1243 }
1244
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001245 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1246 int exec_in = !strcmp(argv[0], "exec-in");
1247 int fd;
1248
1249 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1250 argc -= 2;
1251 argv += 2;
1252 while (argc-- > 0) {
Jeff Sharkey824d1062014-06-10 11:31:24 -07001253 char *quoted = escape_argv(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001254 strncat(buf, " ", sizeof(buf) - 1);
1255 strncat(buf, quoted, sizeof(buf) - 1);
1256 free(quoted);
1257 }
1258
1259 fd = adb_connect(buf);
1260 if (fd < 0) {
1261 fprintf(stderr, "error: %s\n", adb_error());
1262 return -1;
1263 }
1264
1265 if (exec_in) {
1266 copy_to_file(STDIN_FILENO, fd);
1267 } else {
1268 copy_to_file(fd, STDOUT_FILENO);
1269 }
1270
1271 adb_close(fd);
1272 return 0;
1273 }
1274
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001275 if(!strcmp(argv[0], "kill-server")) {
1276 int fd;
1277 fd = _adb_connect("host:kill");
1278 if(fd == -1) {
1279 fprintf(stderr,"* server not running *\n");
1280 return 1;
1281 }
1282 return 0;
1283 }
1284
Doug Zongker6b217ed2012-01-09 14:54:53 -08001285 if(!strcmp(argv[0], "sideload")) {
1286 if(argc != 2) return usage();
1287 if(adb_download("sideload", argv[1], 1)) {
1288 return 1;
1289 } else {
1290 return 0;
1291 }
1292 }
1293
Mike Lockwood26b88e32009-08-24 15:58:40 -07001294 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001295 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001296 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001297 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001298 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001299 if (!strcmp(argv[0], "reboot-bootloader"))
1300 snprintf(command, sizeof(command), "reboot:bootloader");
1301 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001302 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001303 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001304 snprintf(command, sizeof(command), "%s:", argv[0]);
1305 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001306 if(fd >= 0) {
1307 read_and_dump(fd);
1308 adb_close(fd);
1309 return 0;
1310 }
1311 fprintf(stderr,"error: %s\n", adb_error());
1312 return 1;
1313 }
1314
Mike Lockwood78589f32009-09-03 14:54:58 -04001315 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001316 if (argc != 1) return usage();
1317 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001318 return 0;
1319 }
1320
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001321 /* adb_command() wrapper commands */
1322
1323 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1324 char* service = argv[0];
1325 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1326 if (ttype == kTransportUsb) {
1327 service = "wait-for-usb";
1328 } else if (ttype == kTransportLocal) {
1329 service = "wait-for-local";
1330 } else {
1331 service = "wait-for-any";
1332 }
1333 }
1334
1335 format_host_command(buf, sizeof buf, service, ttype, serial);
1336
1337 if (adb_command(buf)) {
1338 D("failure: %s *\n",adb_error());
1339 fprintf(stderr,"error: %s\n", adb_error());
1340 return 1;
1341 }
1342
1343 /* Allow a command to be run after wait-for-device,
1344 * e.g. 'adb wait-for-device shell'.
1345 */
1346 if(argc > 1) {
1347 argc--;
1348 argv++;
1349 goto top;
1350 }
1351 return 0;
1352 }
1353
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001354 if(!strcmp(argv[0], "forward") ||
1355 !strcmp(argv[0], "reverse"))
1356 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001357 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001358 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001359 char remove = 0;
1360 char remove_all = 0;
1361 char list = 0;
1362 char no_rebind = 0;
1363
1364 // Parse options here.
1365 while (argc > 1 && argv[1][0] == '-') {
1366 if (!strcmp(argv[1], "--list"))
1367 list = 1;
1368 else if (!strcmp(argv[1], "--remove"))
1369 remove = 1;
1370 else if (!strcmp(argv[1], "--remove-all"))
1371 remove_all = 1;
1372 else if (!strcmp(argv[1], "--no-rebind"))
1373 no_rebind = 1;
1374 else {
1375 return usage();
1376 }
1377 argc--;
1378 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001379 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001380
1381 // Ensure we can only use one option at a time.
1382 if (list + remove + remove_all + no_rebind > 1) {
1383 return usage();
1384 }
1385
1386 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001387 if (reverse) {
1388 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001389 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001390 if (serial) {
1391 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1392 serial);
1393 } else if (ttype == kTransportUsb) {
1394 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1395 } else if (ttype == kTransportLocal) {
1396 snprintf(host_prefix, sizeof host_prefix, "host-local");
1397 } else {
1398 snprintf(host_prefix, sizeof host_prefix, "host");
1399 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001400 }
1401
1402 // Implement forward --list
1403 if (list) {
1404 if (argc != 1)
1405 return usage();
1406 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1407 char* forwards = adb_query(buf);
1408 if (forwards == NULL) {
1409 fprintf(stderr, "error: %s\n", adb_error());
1410 return 1;
1411 }
1412 printf("%s", forwards);
1413 free(forwards);
1414 return 0;
1415 }
1416
1417 // Implement forward --remove-all
1418 else if (remove_all) {
1419 if (argc != 1)
1420 return usage();
1421 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1422 }
1423
1424 // Implement forward --remove <local>
1425 else if (remove) {
1426 if (argc != 2)
1427 return usage();
1428 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1429 }
1430 // Or implement one of:
1431 // forward <local> <remote>
1432 // forward --no-rebind <local> <remote>
1433 else
1434 {
1435 if (argc != 3)
1436 return usage();
1437 const char* command = no_rebind ? "forward:norebind:" : "forward";
1438 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1439 }
1440
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001441 if(adb_command(buf)) {
1442 fprintf(stderr,"error: %s\n", adb_error());
1443 return 1;
1444 }
1445 return 0;
1446 }
1447
1448 /* do_sync_*() commands */
1449
1450 if(!strcmp(argv[0], "ls")) {
1451 if(argc != 2) return usage();
1452 return do_sync_ls(argv[1]);
1453 }
1454
1455 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001456 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001457 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001458 const char* lpath = NULL, *rpath = NULL;
1459
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001460 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001461
1462 if ((lpath != NULL) && (rpath != NULL)) {
1463 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1464 }
1465
1466 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001467 }
1468
1469 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001470 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001471 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001472 const char* rpath = NULL, *lpath = ".";
1473
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001474 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001475
1476 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001477 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001478 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001479
1480 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001481 }
1482
1483 if(!strcmp(argv[0], "install")) {
1484 if (argc < 2) return usage();
1485 return install_app(ttype, serial, argc, argv);
1486 }
1487
1488 if(!strcmp(argv[0], "uninstall")) {
1489 if (argc < 2) return usage();
1490 return uninstall_app(ttype, serial, argc, argv);
1491 }
1492
1493 if(!strcmp(argv[0], "sync")) {
1494 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001495 int listonly = 0;
1496
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001497 int ret;
1498 if(argc < 2) {
1499 /* No local path was specified. */
1500 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001501 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1502 listonly = 1;
1503 if (argc == 3) {
1504 srcarg = argv[2];
1505 } else {
1506 srcarg = NULL;
1507 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001508 } else if(argc == 2) {
1509 /* A local path or "android"/"data" arg was specified. */
1510 srcarg = argv[1];
1511 } else {
1512 return usage();
1513 }
1514 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1515 if(ret != 0) return usage();
1516
1517 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001518 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001519 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001520 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001521
1522 free(android_srcpath);
1523 free(data_srcpath);
1524 return ret;
1525 }
1526
1527 /* passthrough commands */
1528
1529 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001530 !strcmp(argv[0],"get-serialno") ||
1531 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001532 {
1533 char *tmp;
1534
1535 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1536 tmp = adb_query(buf);
1537 if(tmp) {
1538 printf("%s\n", tmp);
1539 return 0;
1540 } else {
1541 return 1;
1542 }
1543 }
1544
1545 /* other commands */
1546
1547 if(!strcmp(argv[0],"status-window")) {
1548 status_window(ttype, serial);
1549 return 0;
1550 }
1551
Christopher Tate7b9b5162011-11-30 13:00:33 -08001552 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001553 return logcat(ttype, serial, argc, argv);
1554 }
1555
1556 if(!strcmp(argv[0],"ppp")) {
1557 return ppp(argc, argv);
1558 }
1559
1560 if (!strcmp(argv[0], "start-server")) {
1561 return adb_connect("host:start-server");
1562 }
1563
Christopher Tate73779122011-04-21 12:53:28 -07001564 if (!strcmp(argv[0], "backup")) {
1565 return backup(argc, argv);
1566 }
1567
Christopher Tatecf5379b2011-05-17 15:52:54 -07001568 if (!strcmp(argv[0], "restore")) {
1569 return restore(argc, argv);
1570 }
1571
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001572 if (!strcmp(argv[0], "jdwp")) {
1573 int fd = adb_connect("jdwp");
1574 if (fd >= 0) {
1575 read_and_dump(fd);
1576 adb_close(fd);
1577 return 0;
1578 } else {
1579 fprintf(stderr, "error: %s\n", adb_error());
1580 return -1;
1581 }
1582 }
1583
1584 /* "adb /?" is a common idiom under Windows */
1585 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1586 help();
1587 return 0;
1588 }
1589
1590 if(!strcmp(argv[0], "version")) {
1591 version(stdout);
1592 return 0;
1593 }
1594
1595 usage();
1596 return 1;
1597}
1598
1599static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1600{
1601 char *argv[16];
1602 int argc;
1603 va_list ap;
1604
1605 va_start(ap, cmd);
1606 argc = 0;
1607
1608 if (serial) {
1609 argv[argc++] = "-s";
1610 argv[argc++] = serial;
1611 } else if (ttype == kTransportUsb) {
1612 argv[argc++] = "-d";
1613 } else if (ttype == kTransportLocal) {
1614 argv[argc++] = "-e";
1615 }
1616
1617 argv[argc++] = cmd;
1618 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1619 va_end(ap);
1620
1621#if 0
1622 int n;
1623 fprintf(stderr,"argc = %d\n",argc);
1624 for(n = 0; n < argc; n++) {
1625 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1626 }
1627#endif
1628
1629 return adb_commandline(argc, argv);
1630}
1631
1632int find_sync_dirs(const char *srcarg,
1633 char **android_srcdir_out, char **data_srcdir_out)
1634{
1635 char *android_srcdir, *data_srcdir;
1636
1637 if(srcarg == NULL) {
1638 android_srcdir = product_file("system");
1639 data_srcdir = product_file("data");
1640 } else {
1641 /* srcarg may be "data", "system" or NULL.
1642 * if srcarg is NULL, then both data and system are synced
1643 */
1644 if(strcmp(srcarg, "system") == 0) {
1645 android_srcdir = product_file("system");
1646 data_srcdir = NULL;
1647 } else if(strcmp(srcarg, "data") == 0) {
1648 android_srcdir = NULL;
1649 data_srcdir = product_file("data");
1650 } else {
1651 /* It's not "system" or "data".
1652 */
1653 return 1;
1654 }
1655 }
1656
1657 if(android_srcdir_out != NULL)
1658 *android_srcdir_out = android_srcdir;
1659 else
1660 free(android_srcdir);
1661
1662 if(data_srcdir_out != NULL)
1663 *data_srcdir_out = data_srcdir;
1664 else
1665 free(data_srcdir);
1666
1667 return 0;
1668}
1669
1670static int pm_command(transport_type transport, char* serial,
1671 int argc, char** argv)
1672{
1673 char buf[4096];
1674
1675 snprintf(buf, sizeof(buf), "shell:pm");
1676
1677 while(argc-- > 0) {
Jeff Sharkey824d1062014-06-10 11:31:24 -07001678 char *quoted = escape_argv(*argv++);
1679 strncat(buf, " ", sizeof(buf) - 1);
1680 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001681 free(quoted);
1682 }
1683
1684 send_shellcommand(transport, serial, buf);
1685 return 0;
1686}
1687
1688int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1689{
1690 /* if the user choose the -k option, we refuse to do it until devices are
1691 out with the option to uninstall the remaining data somehow (adb/ui) */
1692 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1693 {
1694 printf(
1695 "The -k option uninstalls the application while retaining the data/cache.\n"
1696 "At the moment, there is no way to remove the remaining data.\n"
1697 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1698 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1699 return -1;
1700 }
1701
1702 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1703 return pm_command(transport, serial, argc, argv);
1704}
1705
1706static int delete_file(transport_type transport, char* serial, char* filename)
1707{
1708 char buf[4096];
1709 char* quoted;
1710
1711 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey824d1062014-06-10 11:31:24 -07001712 quoted = escape_argv(filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001713 strncat(buf, quoted, sizeof(buf)-1);
1714 free(quoted);
1715
1716 send_shellcommand(transport, serial, buf);
1717 return 0;
1718}
1719
Kenny Root3802c992011-08-05 11:19:45 -07001720static const char* get_basename(const char* filename)
1721{
1722 const char* basename = adb_dirstop(filename);
1723 if (basename) {
1724 basename++;
1725 return basename;
1726 } else {
1727 return filename;
1728 }
1729}
1730
1731static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001732{
1733 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001734
Kenny Root3802c992011-08-05 11:19:45 -07001735 if (filename == NULL) {
1736 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001737 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001738
Kenny Root3802c992011-08-05 11:19:45 -07001739 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001740 fprintf(stderr, "can't find '%s' to install\n", filename);
1741 return 1;
1742 }
Kenny Root3802c992011-08-05 11:19:45 -07001743
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001744 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001745 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001746 return 1;
1747 }
1748
Kenny Root3802c992011-08-05 11:19:45 -07001749 return 0;
1750}
1751
1752int install_app(transport_type transport, char* serial, int argc, char** argv)
1753{
1754 static const char *const DATA_DEST = "/data/local/tmp/%s";
1755 static const char *const SD_DEST = "/sdcard/tmp/%s";
1756 const char* where = DATA_DEST;
1757 char apk_dest[PATH_MAX];
1758 char verification_dest[PATH_MAX];
1759 char* apk_file;
1760 char* verification_file = NULL;
1761 int file_arg = -1;
1762 int err;
1763 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001764 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001765
1766 for (i = 1; i < argc; i++) {
1767 if (*argv[i] != '-') {
1768 file_arg = i;
1769 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001770 } else if (!strcmp(argv[i], "-i")) {
1771 // Skip the installer package name.
1772 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001773 } else if (!strcmp(argv[i], "-s")) {
1774 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001775 } else if (!strcmp(argv[i], "--algo")) {
1776 verify_apk = 0;
1777 i++;
1778 } else if (!strcmp(argv[i], "--iv")) {
1779 verify_apk = 0;
1780 i++;
1781 } else if (!strcmp(argv[i], "--key")) {
1782 verify_apk = 0;
1783 i++;
Narayan Kamath9416eaa2014-05-29 15:52:02 +01001784 } else if (!strcmp(argv[i], "--abi")) {
1785 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001786 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001787 }
1788
Kenny Root3802c992011-08-05 11:19:45 -07001789 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001790 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001791 return 1;
1792 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001793 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001794 return 1;
1795 }
1796
1797 apk_file = argv[file_arg];
1798
1799 if (file_arg != argc - 1) {
1800 verification_file = argv[file_arg + 1];
1801 }
1802
1803 if (check_file(apk_file) || check_file(verification_file)) {
1804 return 1;
1805 }
1806
1807 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1808 if (verification_file != NULL) {
1809 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1810
1811 if (!strcmp(apk_dest, verification_dest)) {
1812 fprintf(stderr, "APK and verification file can't have the same name\n");
1813 return 1;
1814 }
1815 }
1816
Mark Lindner9f9d1452014-03-11 17:55:59 -07001817 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001818 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001819 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001820 } else {
1821 argv[file_arg] = apk_dest; /* destination name, not source location */
1822 }
1823
1824 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001825 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1826 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001827 if (err) {
1828 goto cleanup_apk;
1829 } else {
1830 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1831 }
1832 }
1833
1834 pm_command(transport, serial, argc, argv);
1835
Kenny Root58d5f222012-03-26 16:14:02 -07001836cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001837 if (verification_file != NULL) {
1838 delete_file(transport, serial, verification_dest);
1839 }
1840
Kenny Root3802c992011-08-05 11:19:45 -07001841 delete_file(transport, serial, apk_dest);
1842
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001843 return err;
1844}