blob: 61167b215446008f149c94238e7e6ee19b771e65 [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"
110 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato23595b02010-01-05 13:42:25 -0800111 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800112 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600113 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800114 " (see 'adb help all')\n"
115 " adb shell - run remote shell interactively\n"
116 " adb shell <command> - run remote shell command\n"
117 " adb emu <command> - run emulator console command\n"
118 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100119 " adb forward --list - list all forward socket connections.\n"
120 " the format is a list of lines with the following format:\n"
121 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800122 " adb forward <local> <remote> - forward socket connections\n"
123 " forward specs are one of: \n"
124 " tcp:<port>\n"
125 " localabstract:<unix domain socket name>\n"
126 " localreserved:<unix domain socket name>\n"
127 " localfilesystem:<unix domain socket name>\n"
128 " dev:<character device name>\n"
129 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100130 " adb forward --no-rebind <local> <remote>\n"
131 " - same as 'adb forward <local> <remote>' but fails\n"
132 " if <local> is already forwarded\n"
133 " adb forward --remove <local> - remove a specific forward socket connection\n"
134 " adb forward --remove-all - remove all forward socket connections\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800135 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700136 " 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 -0700137 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800138 " ('-l' means forward-lock the app)\n"
139 " ('-r' means reinstall the app, keeping its data)\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700140 " ('-d' means allow version code downgrade)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500141 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700142 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800143 " adb uninstall [-k] <package> - remove this app package from the device\n"
144 " ('-k' means keep the data and cache directories)\n"
145 " adb bugreport - return all information from the device\n"
146 " that should be included in a bug report.\n"
147 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800148 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700149 " - write an archive of the device's data to <file>.\n"
150 " If no -f option is supplied then the data is written\n"
151 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700152 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700153 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800154 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
155 " (aka .obb) files associated with each application; the default\n"
156 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700157 " (-shared|-noshared enable/disable backup of the device's\n"
158 " shared storage / SD card contents; the default is noshared.)\n"
159 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700160 " (-system|-nosystem toggles whether -all automatically includes\n"
161 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700162 " (<packages...> is the list of applications to be backed up. If\n"
163 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700164 " list is optional. Applications explicitly given on the\n"
165 " command line will be included even if -nosystem would\n"
166 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700167 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700168 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700169 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800170 " adb help - show this help message\n"
171 " adb version - show version num\n"
172 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800173 "scripting:\n"
174 " adb wait-for-device - block until device is online\n"
175 " adb start-server - ensure that there is a server running\n"
176 " adb kill-server - kill the server if it is running\n"
177 " adb get-state - prints: offline | bootloader | device\n"
178 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700179 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800180 " adb status-window - continuously print device status for a specified device\n"
181 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400182 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800183 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700184 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800185 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700186 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800187 "\n"
188 "networking:\n"
189 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500190 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800191 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
192 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
193 "\n"
194 "adb sync notes: adb sync [ <directory> ]\n"
195 " <localdir> can be interpreted in several ways:\n"
196 "\n"
197 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
198 "\n"
199 " - If it is \"system\" or \"data\", only the corresponding partition\n"
200 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000201 "\n"
202 "environmental variables:\n"
203 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
204 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
205 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
206 " 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 -0800207 );
208}
209
210int usage()
211{
212 help();
213 return 1;
214}
215
216#ifdef HAVE_TERMIO_H
217static struct termios tio_save;
218
219static void stdin_raw_init(int fd)
220{
221 struct termios tio;
222
223 if(tcgetattr(fd, &tio)) return;
224 if(tcgetattr(fd, &tio_save)) return;
225
226 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
227
228 /* no timeout but request at least one character per read */
229 tio.c_cc[VTIME] = 0;
230 tio.c_cc[VMIN] = 1;
231
232 tcsetattr(fd, TCSANOW, &tio);
233 tcflush(fd, TCIFLUSH);
234}
235
236static void stdin_raw_restore(int fd)
237{
238 tcsetattr(fd, TCSANOW, &tio_save);
239 tcflush(fd, TCIFLUSH);
240}
241#endif
242
243static void read_and_dump(int fd)
244{
245 char buf[4096];
246 int len;
247
248 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700249 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800250 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700251 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800252 if(len == 0) {
253 break;
254 }
255
256 if(len < 0) {
257 if(errno == EINTR) continue;
258 break;
259 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400260 fwrite(buf, 1, len, stdout);
261 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800262 }
263}
264
Christopher Tate73779122011-04-21 12:53:28 -0700265static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700266 const size_t BUFSIZE = 32 * 1024;
267 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700268 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700269 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700270
271 D("copy_to_file(%d -> %d)\n", inFd, outFd);
272 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700273 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700274 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700275 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700276 break;
277 }
278 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700279 if (errno == EINTR) {
280 D("copy_to_file() : EINTR, retrying\n");
281 continue;
282 }
Christopher Tate73779122011-04-21 12:53:28 -0700283 D("copy_to_file() : error %d\n", errno);
284 break;
285 }
286 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700287 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700288 }
Christopher Tatefba22972011-06-01 17:56:23 -0700289 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700290 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700291}
292
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800293static void *stdin_read_thread(void *x)
294{
295 int fd, fdi;
296 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800297 int r, n;
298 int state = 0;
299
300 int *fds = (int*) x;
301 fd = fds[0];
302 fdi = fds[1];
303 free(fds);
304
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800305 for(;;) {
306 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700307 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800308 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700309 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800310 if(r == 0) break;
311 if(r < 0) {
312 if(errno == EINTR) continue;
313 break;
314 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400315 for(n = 0; n < r; n++){
316 switch(buf[n]) {
317 case '\n':
318 state = 1;
319 break;
320 case '\r':
321 state = 1;
322 break;
323 case '~':
324 if(state == 1) state++;
325 break;
326 case '.':
327 if(state == 2) {
328 fprintf(stderr,"\n* disconnect *\n");
329#ifdef HAVE_TERMIO_H
330 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800331#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400332 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800333 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400334 default:
335 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800336 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800337 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800338 r = adb_write(fd, buf, r);
339 if(r <= 0) {
340 break;
341 }
342 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800343 return 0;
344}
345
346int interactive_shell(void)
347{
348 adb_thread_t thr;
349 int fdi, fd;
350 int *fds;
351
352 fd = adb_connect("shell:");
353 if(fd < 0) {
354 fprintf(stderr,"error: %s\n", adb_error());
355 return 1;
356 }
357 fdi = 0; //dup(0);
358
359 fds = malloc(sizeof(int) * 2);
360 fds[0] = fd;
361 fds[1] = fdi;
362
363#ifdef HAVE_TERMIO_H
364 stdin_raw_init(fdi);
365#endif
366 adb_thread_create(&thr, stdin_read_thread, fds);
367 read_and_dump(fd);
368#ifdef HAVE_TERMIO_H
369 stdin_raw_restore(fdi);
370#endif
371 return 0;
372}
373
374
375static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
376{
377 if (serial) {
378 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
379 } else {
380 const char* prefix = "host";
381 if (ttype == kTransportUsb)
382 prefix = "host-usb";
383 else if (ttype == kTransportLocal)
384 prefix = "host-local";
385
386 snprintf(buffer, buflen, "%s:%s", prefix, command);
387 }
388}
389
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100390int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800391 unsigned progress)
392{
393 char buf[4096];
394 unsigned total;
395 int fd;
396 const unsigned char *ptr;
397
398 sprintf(buf,"%s:%d", service, sz);
399 fd = adb_connect(buf);
400 if(fd < 0) {
401 fprintf(stderr,"error: %s\n", adb_error());
402 return -1;
403 }
404
405 int opt = CHUNK_SIZE;
406 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
407
408 total = sz;
409 ptr = data;
410
411 if(progress) {
412 char *x = strrchr(service, ':');
413 if(x) service = x + 1;
414 }
415
416 while(sz > 0) {
417 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
418 if(writex(fd, ptr, xfer)) {
419 adb_status(fd);
420 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
421 return -1;
422 }
423 sz -= xfer;
424 ptr += xfer;
425 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100426 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800427 fflush(stdout);
428 }
429 }
430 if(progress) {
431 printf("\n");
432 }
433
434 if(readx(fd, buf, 4)){
435 fprintf(stderr,"* error reading response *\n");
436 adb_close(fd);
437 return -1;
438 }
439 if(memcmp(buf, "OKAY", 4)) {
440 buf[4] = 0;
441 fprintf(stderr,"* error response '%s' *\n", buf);
442 adb_close(fd);
443 return -1;
444 }
445
446 adb_close(fd);
447 return 0;
448}
449
450
451int adb_download(const char *service, const char *fn, unsigned progress)
452{
453 void *data;
454 unsigned sz;
455
456 data = load_file(fn, &sz);
457 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100458 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800459 return -1;
460 }
461
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100462 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800463 free(data);
464 return status;
465}
466
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800467static void status_window(transport_type ttype, const char* serial)
468{
469 char command[4096];
470 char *state = 0;
471 char *laststate = 0;
472
473 /* silence stderr */
474#ifdef _WIN32
475 /* XXX: TODO */
476#else
477 int fd;
478 fd = unix_open("/dev/null", O_WRONLY);
479 dup2(fd, 2);
480 adb_close(fd);
481#endif
482
483 format_host_command(command, sizeof command, "get-state", ttype, serial);
484
485 for(;;) {
486 adb_sleep_ms(250);
487
488 if(state) {
489 free(state);
490 state = 0;
491 }
492
493 state = adb_query(command);
494
495 if(state) {
496 if(laststate && !strcmp(state,laststate)){
497 continue;
498 } else {
499 if(laststate) free(laststate);
500 laststate = strdup(state);
501 }
502 }
503
504 printf("%c[2J%c[2H", 27, 27);
505 printf("Android Debug Bridge\n");
506 printf("State: %s\n", state ? state : "offline");
507 fflush(stdout);
508 }
509}
510
511/** duplicate string and quote all \ " ( ) chars + space character. */
512static char *
513dupAndQuote(const char *s)
514{
515 const char *ts;
516 size_t alloc_len;
517 char *ret;
518 char *dest;
519
520 ts = s;
521
522 alloc_len = 0;
523
524 for( ;*ts != '\0'; ts++) {
525 alloc_len++;
526 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
527 alloc_len++;
528 }
529 }
530
531 ret = (char *)malloc(alloc_len + 1);
532
533 ts = s;
534 dest = ret;
535
536 for ( ;*ts != '\0'; ts++) {
537 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
538 *dest++ = '\\';
539 }
540
541 *dest++ = *ts;
542 }
543
544 *dest++ = '\0';
545
546 return ret;
547}
548
549/**
550 * Run ppp in "notty" mode against a resource listed as the first parameter
551 * eg:
552 *
553 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
554 *
555 */
556int ppp(int argc, char **argv)
557{
558#ifdef HAVE_WIN32_PROC
559 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
560 return -1;
561#else
562 char *adb_service_name;
563 pid_t pid;
564 int fd;
565
566 if (argc < 2) {
567 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
568 argv[0]);
569
570 return 1;
571 }
572
573 adb_service_name = argv[1];
574
575 fd = adb_connect(adb_service_name);
576
577 if(fd < 0) {
578 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
579 adb_service_name, adb_error());
580 return 1;
581 }
582
583 pid = fork();
584
585 if (pid < 0) {
586 perror("from fork()");
587 return 1;
588 } else if (pid == 0) {
589 int err;
590 int i;
591 const char **ppp_args;
592
593 // copy args
594 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
595 ppp_args[0] = "pppd";
596 for (i = 2 ; i < argc ; i++) {
597 //argv[2] and beyond become ppp_args[1] and beyond
598 ppp_args[i - 1] = argv[i];
599 }
600 ppp_args[i-1] = NULL;
601
602 // child side
603
604 dup2(fd, STDIN_FILENO);
605 dup2(fd, STDOUT_FILENO);
606 adb_close(STDERR_FILENO);
607 adb_close(fd);
608
609 err = execvp("pppd", (char * const *)ppp_args);
610
611 if (err < 0) {
612 perror("execing pppd");
613 }
614 exit(-1);
615 } else {
616 // parent side
617
618 adb_close(fd);
619 return 0;
620 }
621#endif /* !HAVE_WIN32_PROC */
622}
623
624static int send_shellcommand(transport_type transport, char* serial, char* buf)
625{
626 int fd, ret;
627
628 for(;;) {
629 fd = adb_connect(buf);
630 if(fd >= 0)
631 break;
632 fprintf(stderr,"- waiting for device -\n");
633 adb_sleep_ms(1000);
634 do_cmd(transport, serial, "wait-for-device", 0);
635 }
636
637 read_and_dump(fd);
638 ret = adb_close(fd);
639 if (ret)
640 perror("close");
641
642 return ret;
643}
644
645static int logcat(transport_type transport, char* serial, int argc, char **argv)
646{
647 char buf[4096];
648
649 char *log_tags;
650 char *quoted_log_tags;
651
652 log_tags = getenv("ANDROID_LOG_TAGS");
653 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
654
655 snprintf(buf, sizeof(buf),
656 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
657 quoted_log_tags);
658
659 free(quoted_log_tags);
660
Christopher Tate7b9b5162011-11-30 13:00:33 -0800661 if (!strcmp(argv[0],"longcat")) {
662 strncat(buf, " -v long", sizeof(buf)-1);
663 }
664
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800665 argc -= 1;
666 argv += 1;
667 while(argc-- > 0) {
668 char *quoted;
669
670 quoted = dupAndQuote (*argv++);
671
672 strncat(buf, " ", sizeof(buf)-1);
673 strncat(buf, quoted, sizeof(buf)-1);
674 free(quoted);
675 }
676
677 send_shellcommand(transport, serial, buf);
678 return 0;
679}
680
Christopher Tate1e9f2392011-12-08 19:04:34 -0800681static int mkdirs(char *path)
682{
683 int ret;
684 char *x = path + 1;
685
686 for(;;) {
687 x = adb_dirstart(x);
688 if(x == 0) return 0;
689 *x = 0;
690 ret = adb_mkdir(path, 0775);
691 *x = OS_PATH_SEPARATOR;
692 if((ret < 0) && (errno != EEXIST)) {
693 return ret;
694 }
695 x++;
696 }
697 return 0;
698}
699
Christopher Tate73779122011-04-21 12:53:28 -0700700static int backup(int argc, char** argv) {
701 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800702 char default_name[32];
703 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700704 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700705 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700706
Christopher Tatefba22972011-06-01 17:56:23 -0700707 /* find, extract, and use any -f argument */
708 for (i = 1; i < argc; i++) {
709 if (!strcmp("-f", argv[i])) {
710 if (i == argc-1) {
711 fprintf(stderr, "adb: -f passed with no filename\n");
712 return usage();
713 }
714 filename = argv[i+1];
715 for (j = i+2; j <= argc; ) {
716 argv[i++] = argv[j++];
717 }
718 argc -= 2;
719 argv[argc] = NULL;
720 }
Christopher Tate73779122011-04-21 12:53:28 -0700721 }
722
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700723 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
724 if (argc < 2) return usage();
725
Christopher Tate1e9f2392011-12-08 19:04:34 -0800726 adb_unlink(filename);
727 mkdirs((char *)filename);
728 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700729 if (outFd < 0) {
730 fprintf(stderr, "adb: unable to open file %s\n", filename);
731 return -1;
732 }
733
734 snprintf(buf, sizeof(buf), "backup");
735 for (argc--, argv++; argc; argc--, argv++) {
736 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
737 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
738 }
739
740 D("backup. filename=%s buf=%s\n", filename, buf);
741 fd = adb_connect(buf);
742 if (fd < 0) {
743 fprintf(stderr, "adb: unable to connect for backup\n");
744 adb_close(outFd);
745 return -1;
746 }
747
Christopher Tate9c829102012-01-06 15:43:03 -0800748 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700749 copy_to_file(fd, outFd);
750
751 adb_close(fd);
752 adb_close(outFd);
753 return 0;
754}
755
Christopher Tatecf5379b2011-05-17 15:52:54 -0700756static int restore(int argc, char** argv) {
757 const char* filename;
758 int fd, tarFd;
759
760 if (argc != 2) return usage();
761
762 filename = argv[1];
763 tarFd = adb_open(filename, O_RDONLY);
764 if (tarFd < 0) {
765 fprintf(stderr, "adb: unable to open file %s\n", filename);
766 return -1;
767 }
768
769 fd = adb_connect("restore:");
770 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700771 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700772 adb_close(tarFd);
773 return -1;
774 }
775
Christopher Tate9c829102012-01-06 15:43:03 -0800776 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700777 copy_to_file(tarFd, fd);
778
779 adb_close(fd);
780 adb_close(tarFd);
781 return 0;
782}
783
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800784#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
785static int top_works(const char *top)
786{
787 if (top != NULL && adb_is_absolute_host_path(top)) {
788 char path_buf[PATH_MAX];
789 snprintf(path_buf, sizeof(path_buf),
790 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
791 return access(path_buf, F_OK) == 0;
792 }
793 return 0;
794}
795
796static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
797{
798 strcpy(path_buf, indir);
799 while (1) {
800 if (top_works(path_buf)) {
801 return path_buf;
802 }
803 char *s = adb_dirstop(path_buf);
804 if (s != NULL) {
805 *s = '\0';
806 } else {
807 path_buf[0] = '\0';
808 return NULL;
809 }
810 }
811}
812
813static char *find_top(char path_buf[PATH_MAX])
814{
815 char *top = getenv("ANDROID_BUILD_TOP");
816 if (top != NULL && top[0] != '\0') {
817 if (!top_works(top)) {
818 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
819 return NULL;
820 }
821 } else {
822 top = getenv("TOP");
823 if (top != NULL && top[0] != '\0') {
824 if (!top_works(top)) {
825 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
826 return NULL;
827 }
828 } else {
829 top = NULL;
830 }
831 }
832
833 if (top != NULL) {
834 /* The environment pointed to a top directory that works.
835 */
836 strcpy(path_buf, top);
837 return path_buf;
838 }
839
840 /* The environment didn't help. Walk up the tree from the CWD
841 * to see if we can find the top.
842 */
843 char dir[PATH_MAX];
844 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
845 if (top == NULL) {
846 /* If the CWD isn't under a good-looking top, see if the
847 * executable is.
848 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100849 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800850 top = find_top_from(dir, path_buf);
851 }
852 return top;
853}
854
855/* <hint> may be:
856 * - A simple product name
857 * e.g., "sooner"
858TODO: debug? sooner-debug, sooner:debug?
859 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
860 * e.g., "out/target/product/sooner"
861 * - An absolute path to the PRODUCT_OUT dir
862 * e.g., "/src/device/out/target/product/sooner"
863 *
864 * Given <hint>, try to construct an absolute path to the
865 * ANDROID_PRODUCT_OUT dir.
866 */
867static const char *find_product_out_path(const char *hint)
868{
869 static char path_buf[PATH_MAX];
870
871 if (hint == NULL || hint[0] == '\0') {
872 return NULL;
873 }
874
875 /* If it's already absolute, don't bother doing any work.
876 */
877 if (adb_is_absolute_host_path(hint)) {
878 strcpy(path_buf, hint);
879 return path_buf;
880 }
881
882 /* If there are any slashes in it, assume it's a relative path;
883 * make it absolute.
884 */
885 if (adb_dirstart(hint) != NULL) {
886 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
887 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
888 return NULL;
889 }
890 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
891 fprintf(stderr, "adb: Couldn't assemble path\n");
892 return NULL;
893 }
894 strcat(path_buf, OS_PATH_SEPARATOR_STR);
895 strcat(path_buf, hint);
896 return path_buf;
897 }
898
899 /* It's a string without any slashes. Try to do something with it.
900 *
901 * Try to find the root of the build tree, and build a PRODUCT_OUT
902 * path from there.
903 */
904 char top_buf[PATH_MAX];
905 const char *top = find_top(top_buf);
906 if (top == NULL) {
907 fprintf(stderr, "adb: Couldn't find top of build tree\n");
908 return NULL;
909 }
910//TODO: if we have a way to indicate debug, look in out/debug/target/...
911 snprintf(path_buf, sizeof(path_buf),
912 "%s" OS_PATH_SEPARATOR_STR
913 "out" OS_PATH_SEPARATOR_STR
914 "target" OS_PATH_SEPARATOR_STR
915 "product" OS_PATH_SEPARATOR_STR
916 "%s", top_buf, hint);
917 if (access(path_buf, F_OK) < 0) {
918 fprintf(stderr, "adb: Couldn't find a product dir "
919 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
920 return NULL;
921 }
922 return path_buf;
923}
924
925int adb_commandline(int argc, char **argv)
926{
927 char buf[4096];
928 int no_daemon = 0;
929 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100930 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800931 int persist = 0;
932 int r;
933 int quote;
934 transport_type ttype = kTransportAny;
935 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100936 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800937
938 /* If defined, this should be an absolute path to
939 * the directory containing all of the various system images
940 * for a particular product. If not defined, and the adb
941 * command requires this information, then the user must
942 * specify the path using "-p".
943 */
944 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
945 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
946 gProductOutPath = NULL;
947 }
948 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
949
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700950 serial = getenv("ANDROID_SERIAL");
951
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100952 /* Validate and assign the server port */
953 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
954 int server_port = DEFAULT_ADB_PORT;
955 if (server_port_str && strlen(server_port_str) > 0) {
956 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -0800957 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100958 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -0800959 "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 +0100960 server_port_str);
961 return usage();
962 }
963 }
964
965 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800966 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100967 if(!strcmp(argv[0],"server")) {
968 is_server = 1;
969 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800970 no_daemon = 1;
971 } else if (!strcmp(argv[0], "fork-server")) {
972 /* this is a special flag used only when the ADB client launches the ADB Server */
973 is_daemon = 1;
974 } else if(!strcmp(argv[0],"persist")) {
975 persist = 1;
976 } else if(!strncmp(argv[0], "-p", 2)) {
977 const char *product = NULL;
978 if (argv[0][2] == '\0') {
979 if (argc < 2) return usage();
980 product = argv[1];
981 argc--;
982 argv++;
983 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -0700984 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800985 }
986 gProductOutPath = find_product_out_path(product);
987 if (gProductOutPath == NULL) {
988 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
989 product);
990 return usage();
991 }
992 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
993 if (isdigit(argv[0][2])) {
994 serial = argv[0] + 2;
995 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100996 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800997 serial = argv[1];
998 argc--;
999 argv++;
1000 }
1001 } else if (!strcmp(argv[0],"-d")) {
1002 ttype = kTransportUsb;
1003 } else if (!strcmp(argv[0],"-e")) {
1004 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001005 } else if (!strcmp(argv[0],"-a")) {
1006 gListenAll = 1;
1007 } else if(!strncmp(argv[0], "-H", 2)) {
1008 const char *hostname = NULL;
1009 if (argv[0][2] == '\0') {
1010 if (argc < 2) return usage();
1011 hostname = argv[1];
1012 argc--;
1013 argv++;
1014 } else {
1015 hostname = argv[0] + 2;
1016 }
1017 adb_set_tcp_name(hostname);
1018
1019 } else if(!strncmp(argv[0], "-P", 2)) {
1020 if (argv[0][2] == '\0') {
1021 if (argc < 2) return usage();
1022 server_port_str = argv[1];
1023 argc--;
1024 argv++;
1025 } else {
1026 server_port_str = argv[0] + 2;
1027 }
1028 if (strlen(server_port_str) > 0) {
1029 server_port = (int) strtol(server_port_str, NULL, 0);
1030 if (server_port <= 0 || server_port > 65535) {
1031 fprintf(stderr,
1032 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1033 server_port_str);
1034 return usage();
1035 }
1036 } else {
1037 fprintf(stderr,
1038 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1039 return usage();
1040 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001041 } else {
1042 /* out of recognized modifiers and flags */
1043 break;
1044 }
1045 argc--;
1046 argv++;
1047 }
1048
1049 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001050 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001051
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001052 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001053 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001054 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001055 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001056 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001057 }
1058 if(r) {
1059 fprintf(stderr,"* could not start server *\n");
1060 }
1061 return r;
1062 }
1063
1064top:
1065 if(argc == 0) {
1066 return usage();
1067 }
1068
1069 /* adb_connect() commands */
1070
1071 if(!strcmp(argv[0], "devices")) {
1072 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001073 char *listopt;
1074 if (argc < 2)
1075 listopt = "";
1076 else if (argc == 2 && !strcmp(argv[1], "-l"))
1077 listopt = argv[1];
1078 else {
1079 fprintf(stderr, "Usage: adb devices [-l]\n");
1080 return 1;
1081 }
1082 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001083 tmp = adb_query(buf);
1084 if(tmp) {
1085 printf("List of devices attached \n");
1086 printf("%s\n", tmp);
1087 return 0;
1088 } else {
1089 return 1;
1090 }
1091 }
1092
Mike Lockwood01c2c302010-05-24 10:44:35 -04001093 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001094 char *tmp;
1095 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001096 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001097 return 1;
1098 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001099 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1100 tmp = adb_query(buf);
1101 if(tmp) {
1102 printf("%s\n", tmp);
1103 return 0;
1104 } else {
1105 return 1;
1106 }
1107 }
1108
1109 if(!strcmp(argv[0], "disconnect")) {
1110 char *tmp;
1111 if (argc > 2) {
1112 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1113 return 1;
1114 }
1115 if (argc == 2) {
1116 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1117 } else {
1118 snprintf(buf, sizeof buf, "host:disconnect:");
1119 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001120 tmp = adb_query(buf);
1121 if(tmp) {
1122 printf("%s\n", tmp);
1123 return 0;
1124 } else {
1125 return 1;
1126 }
1127 }
1128
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001129 if (!strcmp(argv[0], "emu")) {
1130 return adb_send_emulator_command(argc, argv);
1131 }
1132
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001133 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001134 int r;
1135 int fd;
1136
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001137 char h = (argv[0][0] == 'h');
1138
1139 if (h) {
1140 printf("\x1b[41;33m");
1141 fflush(stdout);
1142 }
1143
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001144 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001145 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001146 r = interactive_shell();
1147 if (h) {
1148 printf("\x1b[0m");
1149 fflush(stdout);
1150 }
1151 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001152 }
1153
1154 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1155 argc -= 2;
1156 argv += 2;
1157 while(argc-- > 0) {
1158 strcat(buf, " ");
1159
1160 /* quote empty strings and strings with spaces */
1161 quote = (**argv == 0 || strchr(*argv, ' '));
1162 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001163 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001164 strcat(buf, *argv++);
1165 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001166 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001167 }
1168
1169 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001170 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001171 fd = adb_connect(buf);
1172 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001173 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001174 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001175 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001176 adb_close(fd);
1177 r = 0;
1178 } else {
1179 fprintf(stderr,"error: %s\n", adb_error());
1180 r = -1;
1181 }
1182
1183 if(persist) {
1184 fprintf(stderr,"\n- waiting for device -\n");
1185 adb_sleep_ms(1000);
1186 do_cmd(ttype, serial, "wait-for-device", 0);
1187 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001188 if (h) {
1189 printf("\x1b[0m");
1190 fflush(stdout);
1191 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001192 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001193 return r;
1194 }
1195 }
1196 }
1197
1198 if(!strcmp(argv[0], "kill-server")) {
1199 int fd;
1200 fd = _adb_connect("host:kill");
1201 if(fd == -1) {
1202 fprintf(stderr,"* server not running *\n");
1203 return 1;
1204 }
1205 return 0;
1206 }
1207
Doug Zongker6b217ed2012-01-09 14:54:53 -08001208 if(!strcmp(argv[0], "sideload")) {
1209 if(argc != 2) return usage();
1210 if(adb_download("sideload", argv[1], 1)) {
1211 return 1;
1212 } else {
1213 return 0;
1214 }
1215 }
1216
Mike Lockwood26b88e32009-08-24 15:58:40 -07001217 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001218 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001219 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001220 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001221 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001222 if (!strcmp(argv[0], "reboot-bootloader"))
1223 snprintf(command, sizeof(command), "reboot:bootloader");
1224 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001225 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001226 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001227 snprintf(command, sizeof(command), "%s:", argv[0]);
1228 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001229 if(fd >= 0) {
1230 read_and_dump(fd);
1231 adb_close(fd);
1232 return 0;
1233 }
1234 fprintf(stderr,"error: %s\n", adb_error());
1235 return 1;
1236 }
1237
Mike Lockwood78589f32009-09-03 14:54:58 -04001238 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001239 if (argc != 1) return usage();
1240 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001241 return 0;
1242 }
1243
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001244 /* adb_command() wrapper commands */
1245
1246 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1247 char* service = argv[0];
1248 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1249 if (ttype == kTransportUsb) {
1250 service = "wait-for-usb";
1251 } else if (ttype == kTransportLocal) {
1252 service = "wait-for-local";
1253 } else {
1254 service = "wait-for-any";
1255 }
1256 }
1257
1258 format_host_command(buf, sizeof buf, service, ttype, serial);
1259
1260 if (adb_command(buf)) {
1261 D("failure: %s *\n",adb_error());
1262 fprintf(stderr,"error: %s\n", adb_error());
1263 return 1;
1264 }
1265
1266 /* Allow a command to be run after wait-for-device,
1267 * e.g. 'adb wait-for-device shell'.
1268 */
1269 if(argc > 1) {
1270 argc--;
1271 argv++;
1272 goto top;
1273 }
1274 return 0;
1275 }
1276
1277 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001278 char host_prefix[64];
1279 char remove = 0;
1280 char remove_all = 0;
1281 char list = 0;
1282 char no_rebind = 0;
1283
1284 // Parse options here.
1285 while (argc > 1 && argv[1][0] == '-') {
1286 if (!strcmp(argv[1], "--list"))
1287 list = 1;
1288 else if (!strcmp(argv[1], "--remove"))
1289 remove = 1;
1290 else if (!strcmp(argv[1], "--remove-all"))
1291 remove_all = 1;
1292 else if (!strcmp(argv[1], "--no-rebind"))
1293 no_rebind = 1;
1294 else {
1295 return usage();
1296 }
1297 argc--;
1298 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001299 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001300
1301 // Ensure we can only use one option at a time.
1302 if (list + remove + remove_all + no_rebind > 1) {
1303 return usage();
1304 }
1305
1306 // Determine the <host-prefix> for this command.
1307 if (serial) {
1308 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1309 serial);
1310 } else if (ttype == kTransportUsb) {
1311 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1312 } else if (ttype == kTransportLocal) {
1313 snprintf(host_prefix, sizeof host_prefix, "host-local");
1314 } else {
1315 snprintf(host_prefix, sizeof host_prefix, "host");
1316 }
1317
1318 // Implement forward --list
1319 if (list) {
1320 if (argc != 1)
1321 return usage();
1322 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1323 char* forwards = adb_query(buf);
1324 if (forwards == NULL) {
1325 fprintf(stderr, "error: %s\n", adb_error());
1326 return 1;
1327 }
1328 printf("%s", forwards);
1329 free(forwards);
1330 return 0;
1331 }
1332
1333 // Implement forward --remove-all
1334 else if (remove_all) {
1335 if (argc != 1)
1336 return usage();
1337 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1338 }
1339
1340 // Implement forward --remove <local>
1341 else if (remove) {
1342 if (argc != 2)
1343 return usage();
1344 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1345 }
1346 // Or implement one of:
1347 // forward <local> <remote>
1348 // forward --no-rebind <local> <remote>
1349 else
1350 {
1351 if (argc != 3)
1352 return usage();
1353 const char* command = no_rebind ? "forward:norebind:" : "forward";
1354 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1355 }
1356
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001357 if(adb_command(buf)) {
1358 fprintf(stderr,"error: %s\n", adb_error());
1359 return 1;
1360 }
1361 return 0;
1362 }
1363
1364 /* do_sync_*() commands */
1365
1366 if(!strcmp(argv[0], "ls")) {
1367 if(argc != 2) return usage();
1368 return do_sync_ls(argv[1]);
1369 }
1370
1371 if(!strcmp(argv[0], "push")) {
1372 if(argc != 3) return usage();
1373 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1374 }
1375
1376 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001377 if (argc == 2) {
1378 return do_sync_pull(argv[1], ".");
1379 } else if (argc == 3) {
1380 return do_sync_pull(argv[1], argv[2]);
1381 } else {
1382 return usage();
1383 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001384 }
1385
1386 if(!strcmp(argv[0], "install")) {
1387 if (argc < 2) return usage();
1388 return install_app(ttype, serial, argc, argv);
1389 }
1390
1391 if(!strcmp(argv[0], "uninstall")) {
1392 if (argc < 2) return usage();
1393 return uninstall_app(ttype, serial, argc, argv);
1394 }
1395
1396 if(!strcmp(argv[0], "sync")) {
1397 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001398 int listonly = 0;
1399
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001400 int ret;
1401 if(argc < 2) {
1402 /* No local path was specified. */
1403 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001404 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1405 listonly = 1;
1406 if (argc == 3) {
1407 srcarg = argv[2];
1408 } else {
1409 srcarg = NULL;
1410 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001411 } else if(argc == 2) {
1412 /* A local path or "android"/"data" arg was specified. */
1413 srcarg = argv[1];
1414 } else {
1415 return usage();
1416 }
1417 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1418 if(ret != 0) return usage();
1419
1420 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001421 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001422 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001423 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001424
1425 free(android_srcpath);
1426 free(data_srcpath);
1427 return ret;
1428 }
1429
1430 /* passthrough commands */
1431
1432 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001433 !strcmp(argv[0],"get-serialno") ||
1434 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001435 {
1436 char *tmp;
1437
1438 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1439 tmp = adb_query(buf);
1440 if(tmp) {
1441 printf("%s\n", tmp);
1442 return 0;
1443 } else {
1444 return 1;
1445 }
1446 }
1447
1448 /* other commands */
1449
1450 if(!strcmp(argv[0],"status-window")) {
1451 status_window(ttype, serial);
1452 return 0;
1453 }
1454
Christopher Tate7b9b5162011-11-30 13:00:33 -08001455 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001456 return logcat(ttype, serial, argc, argv);
1457 }
1458
1459 if(!strcmp(argv[0],"ppp")) {
1460 return ppp(argc, argv);
1461 }
1462
1463 if (!strcmp(argv[0], "start-server")) {
1464 return adb_connect("host:start-server");
1465 }
1466
Christopher Tate73779122011-04-21 12:53:28 -07001467 if (!strcmp(argv[0], "backup")) {
1468 return backup(argc, argv);
1469 }
1470
Christopher Tatecf5379b2011-05-17 15:52:54 -07001471 if (!strcmp(argv[0], "restore")) {
1472 return restore(argc, argv);
1473 }
1474
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001475 if (!strcmp(argv[0], "jdwp")) {
1476 int fd = adb_connect("jdwp");
1477 if (fd >= 0) {
1478 read_and_dump(fd);
1479 adb_close(fd);
1480 return 0;
1481 } else {
1482 fprintf(stderr, "error: %s\n", adb_error());
1483 return -1;
1484 }
1485 }
1486
1487 /* "adb /?" is a common idiom under Windows */
1488 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1489 help();
1490 return 0;
1491 }
1492
1493 if(!strcmp(argv[0], "version")) {
1494 version(stdout);
1495 return 0;
1496 }
1497
1498 usage();
1499 return 1;
1500}
1501
1502static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1503{
1504 char *argv[16];
1505 int argc;
1506 va_list ap;
1507
1508 va_start(ap, cmd);
1509 argc = 0;
1510
1511 if (serial) {
1512 argv[argc++] = "-s";
1513 argv[argc++] = serial;
1514 } else if (ttype == kTransportUsb) {
1515 argv[argc++] = "-d";
1516 } else if (ttype == kTransportLocal) {
1517 argv[argc++] = "-e";
1518 }
1519
1520 argv[argc++] = cmd;
1521 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1522 va_end(ap);
1523
1524#if 0
1525 int n;
1526 fprintf(stderr,"argc = %d\n",argc);
1527 for(n = 0; n < argc; n++) {
1528 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1529 }
1530#endif
1531
1532 return adb_commandline(argc, argv);
1533}
1534
1535int find_sync_dirs(const char *srcarg,
1536 char **android_srcdir_out, char **data_srcdir_out)
1537{
1538 char *android_srcdir, *data_srcdir;
1539
1540 if(srcarg == NULL) {
1541 android_srcdir = product_file("system");
1542 data_srcdir = product_file("data");
1543 } else {
1544 /* srcarg may be "data", "system" or NULL.
1545 * if srcarg is NULL, then both data and system are synced
1546 */
1547 if(strcmp(srcarg, "system") == 0) {
1548 android_srcdir = product_file("system");
1549 data_srcdir = NULL;
1550 } else if(strcmp(srcarg, "data") == 0) {
1551 android_srcdir = NULL;
1552 data_srcdir = product_file("data");
1553 } else {
1554 /* It's not "system" or "data".
1555 */
1556 return 1;
1557 }
1558 }
1559
1560 if(android_srcdir_out != NULL)
1561 *android_srcdir_out = android_srcdir;
1562 else
1563 free(android_srcdir);
1564
1565 if(data_srcdir_out != NULL)
1566 *data_srcdir_out = data_srcdir;
1567 else
1568 free(data_srcdir);
1569
1570 return 0;
1571}
1572
1573static int pm_command(transport_type transport, char* serial,
1574 int argc, char** argv)
1575{
1576 char buf[4096];
1577
1578 snprintf(buf, sizeof(buf), "shell:pm");
1579
1580 while(argc-- > 0) {
1581 char *quoted;
1582
1583 quoted = dupAndQuote(*argv++);
1584
1585 strncat(buf, " ", sizeof(buf)-1);
1586 strncat(buf, quoted, sizeof(buf)-1);
1587 free(quoted);
1588 }
1589
1590 send_shellcommand(transport, serial, buf);
1591 return 0;
1592}
1593
1594int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1595{
1596 /* if the user choose the -k option, we refuse to do it until devices are
1597 out with the option to uninstall the remaining data somehow (adb/ui) */
1598 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1599 {
1600 printf(
1601 "The -k option uninstalls the application while retaining the data/cache.\n"
1602 "At the moment, there is no way to remove the remaining data.\n"
1603 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1604 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1605 return -1;
1606 }
1607
1608 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1609 return pm_command(transport, serial, argc, argv);
1610}
1611
1612static int delete_file(transport_type transport, char* serial, char* filename)
1613{
1614 char buf[4096];
1615 char* quoted;
1616
1617 snprintf(buf, sizeof(buf), "shell:rm ");
1618 quoted = dupAndQuote(filename);
1619 strncat(buf, quoted, sizeof(buf)-1);
1620 free(quoted);
1621
1622 send_shellcommand(transport, serial, buf);
1623 return 0;
1624}
1625
Kenny Root3802c992011-08-05 11:19:45 -07001626static const char* get_basename(const char* filename)
1627{
1628 const char* basename = adb_dirstop(filename);
1629 if (basename) {
1630 basename++;
1631 return basename;
1632 } else {
1633 return filename;
1634 }
1635}
1636
1637static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001638{
1639 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001640
Kenny Root3802c992011-08-05 11:19:45 -07001641 if (filename == NULL) {
1642 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001643 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001644
Kenny Root3802c992011-08-05 11:19:45 -07001645 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001646 fprintf(stderr, "can't find '%s' to install\n", filename);
1647 return 1;
1648 }
Kenny Root3802c992011-08-05 11:19:45 -07001649
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001650 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001651 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001652 return 1;
1653 }
1654
Kenny Root3802c992011-08-05 11:19:45 -07001655 return 0;
1656}
1657
1658int install_app(transport_type transport, char* serial, int argc, char** argv)
1659{
1660 static const char *const DATA_DEST = "/data/local/tmp/%s";
1661 static const char *const SD_DEST = "/sdcard/tmp/%s";
1662 const char* where = DATA_DEST;
1663 char apk_dest[PATH_MAX];
1664 char verification_dest[PATH_MAX];
1665 char* apk_file;
1666 char* verification_file = NULL;
1667 int file_arg = -1;
1668 int err;
1669 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001670 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001671
1672 for (i = 1; i < argc; i++) {
1673 if (*argv[i] != '-') {
1674 file_arg = i;
1675 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001676 } else if (!strcmp(argv[i], "-i")) {
1677 // Skip the installer package name.
1678 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001679 } else if (!strcmp(argv[i], "-s")) {
1680 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001681 } else if (!strcmp(argv[i], "--algo")) {
1682 verify_apk = 0;
1683 i++;
1684 } else if (!strcmp(argv[i], "--iv")) {
1685 verify_apk = 0;
1686 i++;
1687 } else if (!strcmp(argv[i], "--key")) {
1688 verify_apk = 0;
1689 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001690 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001691 }
1692
Kenny Root3802c992011-08-05 11:19:45 -07001693 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001694 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001695 return 1;
1696 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001697 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001698 return 1;
1699 }
1700
1701 apk_file = argv[file_arg];
1702
1703 if (file_arg != argc - 1) {
1704 verification_file = argv[file_arg + 1];
1705 }
1706
1707 if (check_file(apk_file) || check_file(verification_file)) {
1708 return 1;
1709 }
1710
1711 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1712 if (verification_file != NULL) {
1713 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1714
1715 if (!strcmp(apk_dest, verification_dest)) {
1716 fprintf(stderr, "APK and verification file can't have the same name\n");
1717 return 1;
1718 }
1719 }
1720
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001721 err = do_sync_push(apk_file, apk_dest, verify_apk);
Kenny Root3802c992011-08-05 11:19:45 -07001722 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001723 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001724 } else {
1725 argv[file_arg] = apk_dest; /* destination name, not source location */
1726 }
1727
1728 if (verification_file != NULL) {
1729 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1730 if (err) {
1731 goto cleanup_apk;
1732 } else {
1733 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1734 }
1735 }
1736
1737 pm_command(transport, serial, argc, argv);
1738
Kenny Root58d5f222012-03-26 16:14:02 -07001739cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001740 if (verification_file != NULL) {
1741 delete_file(transport, serial, verification_dest);
1742 }
1743
Kenny Root3802c992011-08-05 11:19:45 -07001744 delete_file(transport, serial, apk_dest);
1745
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001746 return err;
1747}