blob: 47c9becb72b91e6cde5c0939c06685c423d967d1 [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;
49
50static char *product_file(const char *extra)
51{
52 int n;
53 char *x;
54
55 if (gProductOutPath == NULL) {
56 fprintf(stderr, "adb: Product directory not specified; "
57 "use -p or define ANDROID_PRODUCT_OUT\n");
58 exit(1);
59 }
60
61 n = strlen(gProductOutPath) + strlen(extra) + 2;
62 x = malloc(n);
63 if (x == 0) {
64 fprintf(stderr, "adb: Out of memory (product_file())\n");
65 exit(1);
66 }
67
68 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
69 return x;
70}
71
72void version(FILE * out) {
73 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
74 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
75}
76
77void help()
78{
79 version(stderr);
80
81 fprintf(stderr,
82 "\n"
83 " -d - directs command to the only connected USB device\n"
84 " returns an error if more than one USB device is present.\n"
85 " -e - directs command to the only running emulator.\n"
86 " returns an error if more than one emulator is running.\n"
87 " -s <serial number> - directs command to the USB device or emulator with\n"
Nick Pellyaf2fe9b2009-05-07 12:48:03 -070088 " the given serial number. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080090 " -p <product name or path> - simple product name like 'sooner', or\n"
91 " a relative/absolute path to a product\n"
92 " out directory like 'out/target/product/sooner'.\n"
93 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94 " environment variable is used, which must\n"
95 " be an absolute path.\n"
96 " devices - list all connected devices\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -040097 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
98 " Port 5555 is used by default if no port number is specified.\n"
99 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
100 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischerc3e82b82011-04-26 12:46:05 +0200101 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400102 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800103 "\n"
104 "device commands:\n"
105 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato23595b02010-01-05 13:42:25 -0800106 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800107 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600108 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800109 " (see 'adb help all')\n"
110 " adb shell - run remote shell interactively\n"
111 " adb shell <command> - run remote shell command\n"
112 " adb emu <command> - run emulator console command\n"
113 " adb logcat [ <filter-spec> ] - View device log\n"
114 " adb forward <local> <remote> - forward socket connections\n"
115 " forward specs are one of: \n"
116 " tcp:<port>\n"
117 " localabstract:<unix domain socket name>\n"
118 " localreserved:<unix domain socket name>\n"
119 " localfilesystem:<unix domain socket name>\n"
120 " dev:<character device name>\n"
121 " jdwp:<process pid> (remote only)\n"
122 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700123 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
124 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800125 " ('-l' means forward-lock the app)\n"
126 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500127 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700128 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800129 " adb uninstall [-k] <package> - remove this app package from the device\n"
130 " ('-k' means keep the data and cache directories)\n"
131 " adb bugreport - return all information from the device\n"
132 " that should be included in a bug report.\n"
133 "\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700134 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
135 " - write an archive of the device's data to <file>.\n"
136 " If no -f option is supplied then the data is written\n"
137 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700138 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700139 " in the archive; the default is noapk.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700140 " (-shared|-noshared enable/disable backup of the device's\n"
141 " shared storage / SD card contents; the default is noshared.)\n"
142 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700143 " (-system|-nosystem toggles whether -all automatically includes\n"
144 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700145 " (<packages...> is the list of applications to be backed up. If\n"
146 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700147 " list is optional. Applications explicitly given on the\n"
148 " command line will be included even if -nosystem would\n"
149 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700150 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700151 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700152 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800153 " adb help - show this help message\n"
154 " adb version - show version num\n"
155 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800156 "scripting:\n"
157 " adb wait-for-device - block until device is online\n"
158 " adb start-server - ensure that there is a server running\n"
159 " adb kill-server - kill the server if it is running\n"
160 " adb get-state - prints: offline | bootloader | device\n"
161 " adb get-serialno - prints: <serial-number>\n"
162 " adb status-window - continuously print device status for a specified device\n"
163 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400164 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800165 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700166 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800167 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700168 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800169 "\n"
170 "networking:\n"
171 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500172 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800173 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
174 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
175 "\n"
176 "adb sync notes: adb sync [ <directory> ]\n"
177 " <localdir> can be interpreted in several ways:\n"
178 "\n"
179 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
180 "\n"
181 " - If it is \"system\" or \"data\", only the corresponding partition\n"
182 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000183 "\n"
184 "environmental variables:\n"
185 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
186 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
187 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
188 " 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 -0800189 );
190}
191
192int usage()
193{
194 help();
195 return 1;
196}
197
198#ifdef HAVE_TERMIO_H
199static struct termios tio_save;
200
201static void stdin_raw_init(int fd)
202{
203 struct termios tio;
204
205 if(tcgetattr(fd, &tio)) return;
206 if(tcgetattr(fd, &tio_save)) return;
207
208 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
209
210 /* no timeout but request at least one character per read */
211 tio.c_cc[VTIME] = 0;
212 tio.c_cc[VMIN] = 1;
213
214 tcsetattr(fd, TCSANOW, &tio);
215 tcflush(fd, TCIFLUSH);
216}
217
218static void stdin_raw_restore(int fd)
219{
220 tcsetattr(fd, TCSANOW, &tio_save);
221 tcflush(fd, TCIFLUSH);
222}
223#endif
224
225static void read_and_dump(int fd)
226{
227 char buf[4096];
228 int len;
229
230 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700231 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800232 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700233 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800234 if(len == 0) {
235 break;
236 }
237
238 if(len < 0) {
239 if(errno == EINTR) continue;
240 break;
241 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400242 fwrite(buf, 1, len, stdout);
243 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800244 }
245}
246
Christopher Tate73779122011-04-21 12:53:28 -0700247static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700248 const size_t BUFSIZE = 32 * 1024;
249 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700250 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700251 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700252
253 D("copy_to_file(%d -> %d)\n", inFd, outFd);
254 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700255 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700256 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700257 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700258 break;
259 }
260 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700261 if (errno == EINTR) {
262 D("copy_to_file() : EINTR, retrying\n");
263 continue;
264 }
Christopher Tate73779122011-04-21 12:53:28 -0700265 D("copy_to_file() : error %d\n", errno);
266 break;
267 }
268 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700269 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700270 }
Christopher Tatefba22972011-06-01 17:56:23 -0700271 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700272 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700273}
274
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800275static void *stdin_read_thread(void *x)
276{
277 int fd, fdi;
278 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800279 int r, n;
280 int state = 0;
281
282 int *fds = (int*) x;
283 fd = fds[0];
284 fdi = fds[1];
285 free(fds);
286
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800287 for(;;) {
288 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700289 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800290 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700291 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800292 if(r == 0) break;
293 if(r < 0) {
294 if(errno == EINTR) continue;
295 break;
296 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400297 for(n = 0; n < r; n++){
298 switch(buf[n]) {
299 case '\n':
300 state = 1;
301 break;
302 case '\r':
303 state = 1;
304 break;
305 case '~':
306 if(state == 1) state++;
307 break;
308 case '.':
309 if(state == 2) {
310 fprintf(stderr,"\n* disconnect *\n");
311#ifdef HAVE_TERMIO_H
312 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400314 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800315 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400316 default:
317 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800318 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800319 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800320 r = adb_write(fd, buf, r);
321 if(r <= 0) {
322 break;
323 }
324 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800325 return 0;
326}
327
328int interactive_shell(void)
329{
330 adb_thread_t thr;
331 int fdi, fd;
332 int *fds;
333
334 fd = adb_connect("shell:");
335 if(fd < 0) {
336 fprintf(stderr,"error: %s\n", adb_error());
337 return 1;
338 }
339 fdi = 0; //dup(0);
340
341 fds = malloc(sizeof(int) * 2);
342 fds[0] = fd;
343 fds[1] = fdi;
344
345#ifdef HAVE_TERMIO_H
346 stdin_raw_init(fdi);
347#endif
348 adb_thread_create(&thr, stdin_read_thread, fds);
349 read_and_dump(fd);
350#ifdef HAVE_TERMIO_H
351 stdin_raw_restore(fdi);
352#endif
353 return 0;
354}
355
356
357static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
358{
359 if (serial) {
360 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
361 } else {
362 const char* prefix = "host";
363 if (ttype == kTransportUsb)
364 prefix = "host-usb";
365 else if (ttype == kTransportLocal)
366 prefix = "host-local";
367
368 snprintf(buffer, buflen, "%s:%s", prefix, command);
369 }
370}
371
Doug Zongker6b217ed2012-01-09 14:54:53 -0800372int adb_download_buffer(const char *service, const void* data, int sz,
373 unsigned progress)
374{
375 char buf[4096];
376 unsigned total;
377 int fd;
378 const unsigned char *ptr;
379
380 sprintf(buf,"%s:%d", service, sz);
381 fd = adb_connect(buf);
382 if(fd < 0) {
383 fprintf(stderr,"error: %s\n", adb_error());
384 return -1;
385 }
386
387 int opt = CHUNK_SIZE;
388 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
389
390 total = sz;
391 ptr = data;
392
393 if(progress) {
394 char *x = strrchr(service, ':');
395 if(x) service = x + 1;
396 }
397
398 while(sz > 0) {
399 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
400 if(writex(fd, ptr, xfer)) {
401 adb_status(fd);
402 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
403 return -1;
404 }
405 sz -= xfer;
406 ptr += xfer;
407 if(progress) {
408 printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
409 fflush(stdout);
410 }
411 }
412 if(progress) {
413 printf("\n");
414 }
415
416 if(readx(fd, buf, 4)){
417 fprintf(stderr,"* error reading response *\n");
418 adb_close(fd);
419 return -1;
420 }
421 if(memcmp(buf, "OKAY", 4)) {
422 buf[4] = 0;
423 fprintf(stderr,"* error response '%s' *\n", buf);
424 adb_close(fd);
425 return -1;
426 }
427
428 adb_close(fd);
429 return 0;
430}
431
432
433int adb_download(const char *service, const char *fn, unsigned progress)
434{
435 void *data;
436 unsigned sz;
437
438 data = load_file(fn, &sz);
439 if(data == 0) {
440 fprintf(stderr,"* cannot read '%s' *\n", service);
441 return -1;
442 }
443
444 int status = adb_download_buffer(service, data, sz, progress);
445 free(data);
446 return status;
447}
448
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800449static void status_window(transport_type ttype, const char* serial)
450{
451 char command[4096];
452 char *state = 0;
453 char *laststate = 0;
454
455 /* silence stderr */
456#ifdef _WIN32
457 /* XXX: TODO */
458#else
459 int fd;
460 fd = unix_open("/dev/null", O_WRONLY);
461 dup2(fd, 2);
462 adb_close(fd);
463#endif
464
465 format_host_command(command, sizeof command, "get-state", ttype, serial);
466
467 for(;;) {
468 adb_sleep_ms(250);
469
470 if(state) {
471 free(state);
472 state = 0;
473 }
474
475 state = adb_query(command);
476
477 if(state) {
478 if(laststate && !strcmp(state,laststate)){
479 continue;
480 } else {
481 if(laststate) free(laststate);
482 laststate = strdup(state);
483 }
484 }
485
486 printf("%c[2J%c[2H", 27, 27);
487 printf("Android Debug Bridge\n");
488 printf("State: %s\n", state ? state : "offline");
489 fflush(stdout);
490 }
491}
492
493/** duplicate string and quote all \ " ( ) chars + space character. */
494static char *
495dupAndQuote(const char *s)
496{
497 const char *ts;
498 size_t alloc_len;
499 char *ret;
500 char *dest;
501
502 ts = s;
503
504 alloc_len = 0;
505
506 for( ;*ts != '\0'; ts++) {
507 alloc_len++;
508 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
509 alloc_len++;
510 }
511 }
512
513 ret = (char *)malloc(alloc_len + 1);
514
515 ts = s;
516 dest = ret;
517
518 for ( ;*ts != '\0'; ts++) {
519 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
520 *dest++ = '\\';
521 }
522
523 *dest++ = *ts;
524 }
525
526 *dest++ = '\0';
527
528 return ret;
529}
530
531/**
532 * Run ppp in "notty" mode against a resource listed as the first parameter
533 * eg:
534 *
535 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
536 *
537 */
538int ppp(int argc, char **argv)
539{
540#ifdef HAVE_WIN32_PROC
541 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
542 return -1;
543#else
544 char *adb_service_name;
545 pid_t pid;
546 int fd;
547
548 if (argc < 2) {
549 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
550 argv[0]);
551
552 return 1;
553 }
554
555 adb_service_name = argv[1];
556
557 fd = adb_connect(adb_service_name);
558
559 if(fd < 0) {
560 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
561 adb_service_name, adb_error());
562 return 1;
563 }
564
565 pid = fork();
566
567 if (pid < 0) {
568 perror("from fork()");
569 return 1;
570 } else if (pid == 0) {
571 int err;
572 int i;
573 const char **ppp_args;
574
575 // copy args
576 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
577 ppp_args[0] = "pppd";
578 for (i = 2 ; i < argc ; i++) {
579 //argv[2] and beyond become ppp_args[1] and beyond
580 ppp_args[i - 1] = argv[i];
581 }
582 ppp_args[i-1] = NULL;
583
584 // child side
585
586 dup2(fd, STDIN_FILENO);
587 dup2(fd, STDOUT_FILENO);
588 adb_close(STDERR_FILENO);
589 adb_close(fd);
590
591 err = execvp("pppd", (char * const *)ppp_args);
592
593 if (err < 0) {
594 perror("execing pppd");
595 }
596 exit(-1);
597 } else {
598 // parent side
599
600 adb_close(fd);
601 return 0;
602 }
603#endif /* !HAVE_WIN32_PROC */
604}
605
606static int send_shellcommand(transport_type transport, char* serial, char* buf)
607{
608 int fd, ret;
609
610 for(;;) {
611 fd = adb_connect(buf);
612 if(fd >= 0)
613 break;
614 fprintf(stderr,"- waiting for device -\n");
615 adb_sleep_ms(1000);
616 do_cmd(transport, serial, "wait-for-device", 0);
617 }
618
619 read_and_dump(fd);
620 ret = adb_close(fd);
621 if (ret)
622 perror("close");
623
624 return ret;
625}
626
627static int logcat(transport_type transport, char* serial, int argc, char **argv)
628{
629 char buf[4096];
630
631 char *log_tags;
632 char *quoted_log_tags;
633
634 log_tags = getenv("ANDROID_LOG_TAGS");
635 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
636
637 snprintf(buf, sizeof(buf),
638 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
639 quoted_log_tags);
640
641 free(quoted_log_tags);
642
Christopher Tate7b9b5162011-11-30 13:00:33 -0800643 if (!strcmp(argv[0],"longcat")) {
644 strncat(buf, " -v long", sizeof(buf)-1);
645 }
646
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800647 argc -= 1;
648 argv += 1;
649 while(argc-- > 0) {
650 char *quoted;
651
652 quoted = dupAndQuote (*argv++);
653
654 strncat(buf, " ", sizeof(buf)-1);
655 strncat(buf, quoted, sizeof(buf)-1);
656 free(quoted);
657 }
658
659 send_shellcommand(transport, serial, buf);
660 return 0;
661}
662
Christopher Tate1e9f2392011-12-08 19:04:34 -0800663static int mkdirs(char *path)
664{
665 int ret;
666 char *x = path + 1;
667
668 for(;;) {
669 x = adb_dirstart(x);
670 if(x == 0) return 0;
671 *x = 0;
672 ret = adb_mkdir(path, 0775);
673 *x = OS_PATH_SEPARATOR;
674 if((ret < 0) && (errno != EEXIST)) {
675 return ret;
676 }
677 x++;
678 }
679 return 0;
680}
681
Christopher Tate73779122011-04-21 12:53:28 -0700682static int backup(int argc, char** argv) {
683 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800684 char default_name[32];
685 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700686 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700687 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700688
Christopher Tatefba22972011-06-01 17:56:23 -0700689 /* find, extract, and use any -f argument */
690 for (i = 1; i < argc; i++) {
691 if (!strcmp("-f", argv[i])) {
692 if (i == argc-1) {
693 fprintf(stderr, "adb: -f passed with no filename\n");
694 return usage();
695 }
696 filename = argv[i+1];
697 for (j = i+2; j <= argc; ) {
698 argv[i++] = argv[j++];
699 }
700 argc -= 2;
701 argv[argc] = NULL;
702 }
Christopher Tate73779122011-04-21 12:53:28 -0700703 }
704
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700705 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
706 if (argc < 2) return usage();
707
Christopher Tate1e9f2392011-12-08 19:04:34 -0800708 adb_unlink(filename);
709 mkdirs((char *)filename);
710 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700711 if (outFd < 0) {
712 fprintf(stderr, "adb: unable to open file %s\n", filename);
713 return -1;
714 }
715
716 snprintf(buf, sizeof(buf), "backup");
717 for (argc--, argv++; argc; argc--, argv++) {
718 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
719 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
720 }
721
722 D("backup. filename=%s buf=%s\n", filename, buf);
723 fd = adb_connect(buf);
724 if (fd < 0) {
725 fprintf(stderr, "adb: unable to connect for backup\n");
726 adb_close(outFd);
727 return -1;
728 }
729
Christopher Tate9c829102012-01-06 15:43:03 -0800730 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700731 copy_to_file(fd, outFd);
732
733 adb_close(fd);
734 adb_close(outFd);
735 return 0;
736}
737
Christopher Tatecf5379b2011-05-17 15:52:54 -0700738static int restore(int argc, char** argv) {
739 const char* filename;
740 int fd, tarFd;
741
742 if (argc != 2) return usage();
743
744 filename = argv[1];
745 tarFd = adb_open(filename, O_RDONLY);
746 if (tarFd < 0) {
747 fprintf(stderr, "adb: unable to open file %s\n", filename);
748 return -1;
749 }
750
751 fd = adb_connect("restore:");
752 if (fd < 0) {
753 fprintf(stderr, "adb: unable to connect for backup\n");
754 adb_close(tarFd);
755 return -1;
756 }
757
Christopher Tate9c829102012-01-06 15:43:03 -0800758 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700759 copy_to_file(tarFd, fd);
760
761 adb_close(fd);
762 adb_close(tarFd);
763 return 0;
764}
765
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800766#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
767static int top_works(const char *top)
768{
769 if (top != NULL && adb_is_absolute_host_path(top)) {
770 char path_buf[PATH_MAX];
771 snprintf(path_buf, sizeof(path_buf),
772 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
773 return access(path_buf, F_OK) == 0;
774 }
775 return 0;
776}
777
778static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
779{
780 strcpy(path_buf, indir);
781 while (1) {
782 if (top_works(path_buf)) {
783 return path_buf;
784 }
785 char *s = adb_dirstop(path_buf);
786 if (s != NULL) {
787 *s = '\0';
788 } else {
789 path_buf[0] = '\0';
790 return NULL;
791 }
792 }
793}
794
795static char *find_top(char path_buf[PATH_MAX])
796{
797 char *top = getenv("ANDROID_BUILD_TOP");
798 if (top != NULL && top[0] != '\0') {
799 if (!top_works(top)) {
800 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
801 return NULL;
802 }
803 } else {
804 top = getenv("TOP");
805 if (top != NULL && top[0] != '\0') {
806 if (!top_works(top)) {
807 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
808 return NULL;
809 }
810 } else {
811 top = NULL;
812 }
813 }
814
815 if (top != NULL) {
816 /* The environment pointed to a top directory that works.
817 */
818 strcpy(path_buf, top);
819 return path_buf;
820 }
821
822 /* The environment didn't help. Walk up the tree from the CWD
823 * to see if we can find the top.
824 */
825 char dir[PATH_MAX];
826 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
827 if (top == NULL) {
828 /* If the CWD isn't under a good-looking top, see if the
829 * executable is.
830 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100831 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800832 top = find_top_from(dir, path_buf);
833 }
834 return top;
835}
836
837/* <hint> may be:
838 * - A simple product name
839 * e.g., "sooner"
840TODO: debug? sooner-debug, sooner:debug?
841 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
842 * e.g., "out/target/product/sooner"
843 * - An absolute path to the PRODUCT_OUT dir
844 * e.g., "/src/device/out/target/product/sooner"
845 *
846 * Given <hint>, try to construct an absolute path to the
847 * ANDROID_PRODUCT_OUT dir.
848 */
849static const char *find_product_out_path(const char *hint)
850{
851 static char path_buf[PATH_MAX];
852
853 if (hint == NULL || hint[0] == '\0') {
854 return NULL;
855 }
856
857 /* If it's already absolute, don't bother doing any work.
858 */
859 if (adb_is_absolute_host_path(hint)) {
860 strcpy(path_buf, hint);
861 return path_buf;
862 }
863
864 /* If there are any slashes in it, assume it's a relative path;
865 * make it absolute.
866 */
867 if (adb_dirstart(hint) != NULL) {
868 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
869 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
870 return NULL;
871 }
872 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
873 fprintf(stderr, "adb: Couldn't assemble path\n");
874 return NULL;
875 }
876 strcat(path_buf, OS_PATH_SEPARATOR_STR);
877 strcat(path_buf, hint);
878 return path_buf;
879 }
880
881 /* It's a string without any slashes. Try to do something with it.
882 *
883 * Try to find the root of the build tree, and build a PRODUCT_OUT
884 * path from there.
885 */
886 char top_buf[PATH_MAX];
887 const char *top = find_top(top_buf);
888 if (top == NULL) {
889 fprintf(stderr, "adb: Couldn't find top of build tree\n");
890 return NULL;
891 }
892//TODO: if we have a way to indicate debug, look in out/debug/target/...
893 snprintf(path_buf, sizeof(path_buf),
894 "%s" OS_PATH_SEPARATOR_STR
895 "out" OS_PATH_SEPARATOR_STR
896 "target" OS_PATH_SEPARATOR_STR
897 "product" OS_PATH_SEPARATOR_STR
898 "%s", top_buf, hint);
899 if (access(path_buf, F_OK) < 0) {
900 fprintf(stderr, "adb: Couldn't find a product dir "
901 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
902 return NULL;
903 }
904 return path_buf;
905}
906
907int adb_commandline(int argc, char **argv)
908{
909 char buf[4096];
910 int no_daemon = 0;
911 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100912 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800913 int persist = 0;
914 int r;
915 int quote;
916 transport_type ttype = kTransportAny;
917 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100918 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800919
920 /* If defined, this should be an absolute path to
921 * the directory containing all of the various system images
922 * for a particular product. If not defined, and the adb
923 * command requires this information, then the user must
924 * specify the path using "-p".
925 */
926 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
927 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
928 gProductOutPath = NULL;
929 }
930 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
931
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700932 serial = getenv("ANDROID_SERIAL");
933
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100934 /* Validate and assign the server port */
935 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
936 int server_port = DEFAULT_ADB_PORT;
937 if (server_port_str && strlen(server_port_str) > 0) {
938 server_port = (int) strtol(server_port_str, NULL, 0);
939 if (server_port <= 0) {
940 fprintf(stderr,
941 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
942 server_port_str);
943 return usage();
944 }
945 }
946
947 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800948 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100949 if(!strcmp(argv[0],"server")) {
950 is_server = 1;
951 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800952 no_daemon = 1;
953 } else if (!strcmp(argv[0], "fork-server")) {
954 /* this is a special flag used only when the ADB client launches the ADB Server */
955 is_daemon = 1;
956 } else if(!strcmp(argv[0],"persist")) {
957 persist = 1;
958 } else if(!strncmp(argv[0], "-p", 2)) {
959 const char *product = NULL;
960 if (argv[0][2] == '\0') {
961 if (argc < 2) return usage();
962 product = argv[1];
963 argc--;
964 argv++;
965 } else {
966 product = argv[1] + 2;
967 }
968 gProductOutPath = find_product_out_path(product);
969 if (gProductOutPath == NULL) {
970 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
971 product);
972 return usage();
973 }
974 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
975 if (isdigit(argv[0][2])) {
976 serial = argv[0] + 2;
977 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100978 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800979 serial = argv[1];
980 argc--;
981 argv++;
982 }
983 } else if (!strcmp(argv[0],"-d")) {
984 ttype = kTransportUsb;
985 } else if (!strcmp(argv[0],"-e")) {
986 ttype = kTransportLocal;
987 } else {
988 /* out of recognized modifiers and flags */
989 break;
990 }
991 argc--;
992 argv++;
993 }
994
995 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100996 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800997
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100998 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800999 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001000 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001001 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001002 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001003 }
1004 if(r) {
1005 fprintf(stderr,"* could not start server *\n");
1006 }
1007 return r;
1008 }
1009
1010top:
1011 if(argc == 0) {
1012 return usage();
1013 }
1014
1015 /* adb_connect() commands */
1016
1017 if(!strcmp(argv[0], "devices")) {
1018 char *tmp;
1019 snprintf(buf, sizeof buf, "host:%s", argv[0]);
1020 tmp = adb_query(buf);
1021 if(tmp) {
1022 printf("List of devices attached \n");
1023 printf("%s\n", tmp);
1024 return 0;
1025 } else {
1026 return 1;
1027 }
1028 }
1029
Mike Lockwood01c2c302010-05-24 10:44:35 -04001030 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001031 char *tmp;
1032 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001033 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001034 return 1;
1035 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001036 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1037 tmp = adb_query(buf);
1038 if(tmp) {
1039 printf("%s\n", tmp);
1040 return 0;
1041 } else {
1042 return 1;
1043 }
1044 }
1045
1046 if(!strcmp(argv[0], "disconnect")) {
1047 char *tmp;
1048 if (argc > 2) {
1049 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1050 return 1;
1051 }
1052 if (argc == 2) {
1053 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1054 } else {
1055 snprintf(buf, sizeof buf, "host:disconnect:");
1056 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001057 tmp = adb_query(buf);
1058 if(tmp) {
1059 printf("%s\n", tmp);
1060 return 0;
1061 } else {
1062 return 1;
1063 }
1064 }
1065
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001066 if (!strcmp(argv[0], "emu")) {
1067 return adb_send_emulator_command(argc, argv);
1068 }
1069
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001070 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001071 int r;
1072 int fd;
1073
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001074 char h = (argv[0][0] == 'h');
1075
1076 if (h) {
1077 printf("\x1b[41;33m");
1078 fflush(stdout);
1079 }
1080
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001081 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001082 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001083 r = interactive_shell();
1084 if (h) {
1085 printf("\x1b[0m");
1086 fflush(stdout);
1087 }
1088 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001089 }
1090
1091 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1092 argc -= 2;
1093 argv += 2;
1094 while(argc-- > 0) {
1095 strcat(buf, " ");
1096
1097 /* quote empty strings and strings with spaces */
1098 quote = (**argv == 0 || strchr(*argv, ' '));
1099 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001100 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001101 strcat(buf, *argv++);
1102 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001103 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001104 }
1105
1106 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001107 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001108 fd = adb_connect(buf);
1109 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001110 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001111 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001112 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001113 adb_close(fd);
1114 r = 0;
1115 } else {
1116 fprintf(stderr,"error: %s\n", adb_error());
1117 r = -1;
1118 }
1119
1120 if(persist) {
1121 fprintf(stderr,"\n- waiting for device -\n");
1122 adb_sleep_ms(1000);
1123 do_cmd(ttype, serial, "wait-for-device", 0);
1124 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001125 if (h) {
1126 printf("\x1b[0m");
1127 fflush(stdout);
1128 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001129 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001130 return r;
1131 }
1132 }
1133 }
1134
1135 if(!strcmp(argv[0], "kill-server")) {
1136 int fd;
1137 fd = _adb_connect("host:kill");
1138 if(fd == -1) {
1139 fprintf(stderr,"* server not running *\n");
1140 return 1;
1141 }
1142 return 0;
1143 }
1144
Doug Zongker6b217ed2012-01-09 14:54:53 -08001145 if(!strcmp(argv[0], "sideload")) {
1146 if(argc != 2) return usage();
1147 if(adb_download("sideload", argv[1], 1)) {
1148 return 1;
1149 } else {
1150 return 0;
1151 }
1152 }
1153
Mike Lockwood26b88e32009-08-24 15:58:40 -07001154 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001155 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001156 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001157 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001158 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001159 if (!strcmp(argv[0], "reboot-bootloader"))
1160 snprintf(command, sizeof(command), "reboot:bootloader");
1161 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001162 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001163 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001164 snprintf(command, sizeof(command), "%s:", argv[0]);
1165 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001166 if(fd >= 0) {
1167 read_and_dump(fd);
1168 adb_close(fd);
1169 return 0;
1170 }
1171 fprintf(stderr,"error: %s\n", adb_error());
1172 return 1;
1173 }
1174
Mike Lockwood78589f32009-09-03 14:54:58 -04001175 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001176 if (argc != 1) return usage();
1177 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001178 return 0;
1179 }
1180
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001181 /* adb_command() wrapper commands */
1182
1183 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1184 char* service = argv[0];
1185 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1186 if (ttype == kTransportUsb) {
1187 service = "wait-for-usb";
1188 } else if (ttype == kTransportLocal) {
1189 service = "wait-for-local";
1190 } else {
1191 service = "wait-for-any";
1192 }
1193 }
1194
1195 format_host_command(buf, sizeof buf, service, ttype, serial);
1196
1197 if (adb_command(buf)) {
1198 D("failure: %s *\n",adb_error());
1199 fprintf(stderr,"error: %s\n", adb_error());
1200 return 1;
1201 }
1202
1203 /* Allow a command to be run after wait-for-device,
1204 * e.g. 'adb wait-for-device shell'.
1205 */
1206 if(argc > 1) {
1207 argc--;
1208 argv++;
1209 goto top;
1210 }
1211 return 0;
1212 }
1213
1214 if(!strcmp(argv[0], "forward")) {
1215 if(argc != 3) return usage();
1216 if (serial) {
Mike Lockwood47b41622009-11-28 12:46:13 -05001217 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1218 } else if (ttype == kTransportUsb) {
1219 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1220 } else if (ttype == kTransportLocal) {
1221 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001222 } else {
Mike Lockwood47b41622009-11-28 12:46:13 -05001223 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001224 }
1225 if(adb_command(buf)) {
1226 fprintf(stderr,"error: %s\n", adb_error());
1227 return 1;
1228 }
1229 return 0;
1230 }
1231
1232 /* do_sync_*() commands */
1233
1234 if(!strcmp(argv[0], "ls")) {
1235 if(argc != 2) return usage();
1236 return do_sync_ls(argv[1]);
1237 }
1238
1239 if(!strcmp(argv[0], "push")) {
1240 if(argc != 3) return usage();
1241 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1242 }
1243
1244 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001245 if (argc == 2) {
1246 return do_sync_pull(argv[1], ".");
1247 } else if (argc == 3) {
1248 return do_sync_pull(argv[1], argv[2]);
1249 } else {
1250 return usage();
1251 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001252 }
1253
1254 if(!strcmp(argv[0], "install")) {
1255 if (argc < 2) return usage();
1256 return install_app(ttype, serial, argc, argv);
1257 }
1258
1259 if(!strcmp(argv[0], "uninstall")) {
1260 if (argc < 2) return usage();
1261 return uninstall_app(ttype, serial, argc, argv);
1262 }
1263
1264 if(!strcmp(argv[0], "sync")) {
1265 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001266 int listonly = 0;
1267
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001268 int ret;
1269 if(argc < 2) {
1270 /* No local path was specified. */
1271 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001272 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1273 listonly = 1;
1274 if (argc == 3) {
1275 srcarg = argv[2];
1276 } else {
1277 srcarg = NULL;
1278 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001279 } else if(argc == 2) {
1280 /* A local path or "android"/"data" arg was specified. */
1281 srcarg = argv[1];
1282 } else {
1283 return usage();
1284 }
1285 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1286 if(ret != 0) return usage();
1287
1288 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001289 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001290 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001291 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001292
1293 free(android_srcpath);
1294 free(data_srcpath);
1295 return ret;
1296 }
1297
1298 /* passthrough commands */
1299
1300 if(!strcmp(argv[0],"get-state") ||
1301 !strcmp(argv[0],"get-serialno"))
1302 {
1303 char *tmp;
1304
1305 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1306 tmp = adb_query(buf);
1307 if(tmp) {
1308 printf("%s\n", tmp);
1309 return 0;
1310 } else {
1311 return 1;
1312 }
1313 }
1314
1315 /* other commands */
1316
1317 if(!strcmp(argv[0],"status-window")) {
1318 status_window(ttype, serial);
1319 return 0;
1320 }
1321
Christopher Tate7b9b5162011-11-30 13:00:33 -08001322 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001323 return logcat(ttype, serial, argc, argv);
1324 }
1325
1326 if(!strcmp(argv[0],"ppp")) {
1327 return ppp(argc, argv);
1328 }
1329
1330 if (!strcmp(argv[0], "start-server")) {
1331 return adb_connect("host:start-server");
1332 }
1333
Christopher Tate73779122011-04-21 12:53:28 -07001334 if (!strcmp(argv[0], "backup")) {
1335 return backup(argc, argv);
1336 }
1337
Christopher Tatecf5379b2011-05-17 15:52:54 -07001338 if (!strcmp(argv[0], "restore")) {
1339 return restore(argc, argv);
1340 }
1341
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001342 if (!strcmp(argv[0], "jdwp")) {
1343 int fd = adb_connect("jdwp");
1344 if (fd >= 0) {
1345 read_and_dump(fd);
1346 adb_close(fd);
1347 return 0;
1348 } else {
1349 fprintf(stderr, "error: %s\n", adb_error());
1350 return -1;
1351 }
1352 }
1353
1354 /* "adb /?" is a common idiom under Windows */
1355 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1356 help();
1357 return 0;
1358 }
1359
1360 if(!strcmp(argv[0], "version")) {
1361 version(stdout);
1362 return 0;
1363 }
1364
1365 usage();
1366 return 1;
1367}
1368
1369static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1370{
1371 char *argv[16];
1372 int argc;
1373 va_list ap;
1374
1375 va_start(ap, cmd);
1376 argc = 0;
1377
1378 if (serial) {
1379 argv[argc++] = "-s";
1380 argv[argc++] = serial;
1381 } else if (ttype == kTransportUsb) {
1382 argv[argc++] = "-d";
1383 } else if (ttype == kTransportLocal) {
1384 argv[argc++] = "-e";
1385 }
1386
1387 argv[argc++] = cmd;
1388 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1389 va_end(ap);
1390
1391#if 0
1392 int n;
1393 fprintf(stderr,"argc = %d\n",argc);
1394 for(n = 0; n < argc; n++) {
1395 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1396 }
1397#endif
1398
1399 return adb_commandline(argc, argv);
1400}
1401
1402int find_sync_dirs(const char *srcarg,
1403 char **android_srcdir_out, char **data_srcdir_out)
1404{
1405 char *android_srcdir, *data_srcdir;
1406
1407 if(srcarg == NULL) {
1408 android_srcdir = product_file("system");
1409 data_srcdir = product_file("data");
1410 } else {
1411 /* srcarg may be "data", "system" or NULL.
1412 * if srcarg is NULL, then both data and system are synced
1413 */
1414 if(strcmp(srcarg, "system") == 0) {
1415 android_srcdir = product_file("system");
1416 data_srcdir = NULL;
1417 } else if(strcmp(srcarg, "data") == 0) {
1418 android_srcdir = NULL;
1419 data_srcdir = product_file("data");
1420 } else {
1421 /* It's not "system" or "data".
1422 */
1423 return 1;
1424 }
1425 }
1426
1427 if(android_srcdir_out != NULL)
1428 *android_srcdir_out = android_srcdir;
1429 else
1430 free(android_srcdir);
1431
1432 if(data_srcdir_out != NULL)
1433 *data_srcdir_out = data_srcdir;
1434 else
1435 free(data_srcdir);
1436
1437 return 0;
1438}
1439
1440static int pm_command(transport_type transport, char* serial,
1441 int argc, char** argv)
1442{
1443 char buf[4096];
1444
1445 snprintf(buf, sizeof(buf), "shell:pm");
1446
1447 while(argc-- > 0) {
1448 char *quoted;
1449
1450 quoted = dupAndQuote(*argv++);
1451
1452 strncat(buf, " ", sizeof(buf)-1);
1453 strncat(buf, quoted, sizeof(buf)-1);
1454 free(quoted);
1455 }
1456
1457 send_shellcommand(transport, serial, buf);
1458 return 0;
1459}
1460
1461int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1462{
1463 /* if the user choose the -k option, we refuse to do it until devices are
1464 out with the option to uninstall the remaining data somehow (adb/ui) */
1465 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1466 {
1467 printf(
1468 "The -k option uninstalls the application while retaining the data/cache.\n"
1469 "At the moment, there is no way to remove the remaining data.\n"
1470 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1471 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1472 return -1;
1473 }
1474
1475 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1476 return pm_command(transport, serial, argc, argv);
1477}
1478
1479static int delete_file(transport_type transport, char* serial, char* filename)
1480{
1481 char buf[4096];
1482 char* quoted;
1483
1484 snprintf(buf, sizeof(buf), "shell:rm ");
1485 quoted = dupAndQuote(filename);
1486 strncat(buf, quoted, sizeof(buf)-1);
1487 free(quoted);
1488
1489 send_shellcommand(transport, serial, buf);
1490 return 0;
1491}
1492
Kenny Root3802c992011-08-05 11:19:45 -07001493static const char* get_basename(const char* filename)
1494{
1495 const char* basename = adb_dirstop(filename);
1496 if (basename) {
1497 basename++;
1498 return basename;
1499 } else {
1500 return filename;
1501 }
1502}
1503
1504static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001505{
1506 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001507
Kenny Root3802c992011-08-05 11:19:45 -07001508 if (filename == NULL) {
1509 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001510 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001511
Kenny Root3802c992011-08-05 11:19:45 -07001512 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001513 fprintf(stderr, "can't find '%s' to install\n", filename);
1514 return 1;
1515 }
Kenny Root3802c992011-08-05 11:19:45 -07001516
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001517 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001518 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001519 return 1;
1520 }
1521
Kenny Root3802c992011-08-05 11:19:45 -07001522 return 0;
1523}
1524
1525int install_app(transport_type transport, char* serial, int argc, char** argv)
1526{
1527 static const char *const DATA_DEST = "/data/local/tmp/%s";
1528 static const char *const SD_DEST = "/sdcard/tmp/%s";
1529 const char* where = DATA_DEST;
1530 char apk_dest[PATH_MAX];
1531 char verification_dest[PATH_MAX];
1532 char* apk_file;
1533 char* verification_file = NULL;
1534 int file_arg = -1;
1535 int err;
1536 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001537 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001538
1539 for (i = 1; i < argc; i++) {
1540 if (*argv[i] != '-') {
1541 file_arg = i;
1542 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001543 } else if (!strcmp(argv[i], "-i")) {
1544 // Skip the installer package name.
1545 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001546 } else if (!strcmp(argv[i], "-s")) {
1547 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001548 } else if (!strcmp(argv[i], "--algo")) {
1549 verify_apk = 0;
1550 i++;
1551 } else if (!strcmp(argv[i], "--iv")) {
1552 verify_apk = 0;
1553 i++;
1554 } else if (!strcmp(argv[i], "--key")) {
1555 verify_apk = 0;
1556 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001557 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001558 }
1559
Kenny Root3802c992011-08-05 11:19:45 -07001560 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001561 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001562 return 1;
1563 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001564 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001565 return 1;
1566 }
1567
1568 apk_file = argv[file_arg];
1569
1570 if (file_arg != argc - 1) {
1571 verification_file = argv[file_arg + 1];
1572 }
1573
1574 if (check_file(apk_file) || check_file(verification_file)) {
1575 return 1;
1576 }
1577
1578 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1579 if (verification_file != NULL) {
1580 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1581
1582 if (!strcmp(apk_dest, verification_dest)) {
1583 fprintf(stderr, "APK and verification file can't have the same name\n");
1584 return 1;
1585 }
1586 }
1587
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001588 err = do_sync_push(apk_file, apk_dest, verify_apk);
Kenny Root3802c992011-08-05 11:19:45 -07001589 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001590 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001591 } else {
1592 argv[file_arg] = apk_dest; /* destination name, not source location */
1593 }
1594
1595 if (verification_file != NULL) {
1596 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1597 if (err) {
1598 goto cleanup_apk;
1599 } else {
1600 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1601 }
1602 }
1603
1604 pm_command(transport, serial, argc, argv);
1605
Kenny Root58d5f222012-03-26 16:14:02 -07001606cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001607 if (verification_file != NULL) {
1608 delete_file(transport, serial, verification_dest);
1609 }
1610
Kenny Root3802c992011-08-05 11:19:45 -07001611 delete_file(transport, serial, apk_dest);
1612
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001613 return err;
1614}