blob: 7af8163a866adcded58842f4bf55a354f65e45e0 [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"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500123 " adb install [-l] [-r] [-s] <file> - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800124 " ('-l' means forward-lock the app)\n"
125 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500126 " ('-s' means install on SD card instead of internal storage)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800127 " adb uninstall [-k] <package> - remove this app package from the device\n"
128 " ('-k' means keep the data and cache directories)\n"
129 " adb bugreport - return all information from the device\n"
130 " that should be included in a bug report.\n"
131 "\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700132 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
133 " - write an archive of the device's data to <file>.\n"
134 " If no -f option is supplied then the data is written\n"
135 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700136 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700137 " in the archive; the default is noapk.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700138 " (-shared|-noshared enable/disable backup of the device's\n"
139 " shared storage / SD card contents; the default is noshared.)\n"
140 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700141 " (-system|-nosystem toggles whether -all automatically includes\n"
142 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700143 " (<packages...> is the list of applications to be backed up. If\n"
144 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700145 " list is optional. Applications explicitly given on the\n"
146 " command line will be included even if -nosystem would\n"
147 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700148 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700149 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700150 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800151 " adb help - show this help message\n"
152 " adb version - show version num\n"
153 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800154 "scripting:\n"
155 " adb wait-for-device - block until device is online\n"
156 " adb start-server - ensure that there is a server running\n"
157 " adb kill-server - kill the server if it is running\n"
158 " adb get-state - prints: offline | bootloader | device\n"
159 " adb get-serialno - prints: <serial-number>\n"
160 " adb status-window - continuously print device status for a specified device\n"
161 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400162 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800163 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700164 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800165 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700166 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800167 "\n"
168 "networking:\n"
169 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500170 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800171 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
172 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
173 "\n"
174 "adb sync notes: adb sync [ <directory> ]\n"
175 " <localdir> can be interpreted in several ways:\n"
176 "\n"
177 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
178 "\n"
179 " - If it is \"system\" or \"data\", only the corresponding partition\n"
180 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000181 "\n"
182 "environmental variables:\n"
183 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
184 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
185 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
186 " 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 -0800187 );
188}
189
190int usage()
191{
192 help();
193 return 1;
194}
195
196#ifdef HAVE_TERMIO_H
197static struct termios tio_save;
198
199static void stdin_raw_init(int fd)
200{
201 struct termios tio;
202
203 if(tcgetattr(fd, &tio)) return;
204 if(tcgetattr(fd, &tio_save)) return;
205
206 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
207
208 /* no timeout but request at least one character per read */
209 tio.c_cc[VTIME] = 0;
210 tio.c_cc[VMIN] = 1;
211
212 tcsetattr(fd, TCSANOW, &tio);
213 tcflush(fd, TCIFLUSH);
214}
215
216static void stdin_raw_restore(int fd)
217{
218 tcsetattr(fd, TCSANOW, &tio_save);
219 tcflush(fd, TCIFLUSH);
220}
221#endif
222
223static void read_and_dump(int fd)
224{
225 char buf[4096];
226 int len;
227
228 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700229 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800230 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700231 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800232 if(len == 0) {
233 break;
234 }
235
236 if(len < 0) {
237 if(errno == EINTR) continue;
238 break;
239 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400240 fwrite(buf, 1, len, stdout);
241 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800242 }
243}
244
Christopher Tate73779122011-04-21 12:53:28 -0700245static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700246 const size_t BUFSIZE = 32 * 1024;
247 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700248 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700249 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700250
251 D("copy_to_file(%d -> %d)\n", inFd, outFd);
252 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700253 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700254 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700255 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700256 break;
257 }
258 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700259 if (errno == EINTR) {
260 D("copy_to_file() : EINTR, retrying\n");
261 continue;
262 }
Christopher Tate73779122011-04-21 12:53:28 -0700263 D("copy_to_file() : error %d\n", errno);
264 break;
265 }
266 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700267 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700268 }
Christopher Tatefba22972011-06-01 17:56:23 -0700269 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700270 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700271}
272
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800273static void *stdin_read_thread(void *x)
274{
275 int fd, fdi;
276 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800277 int r, n;
278 int state = 0;
279
280 int *fds = (int*) x;
281 fd = fds[0];
282 fdi = fds[1];
283 free(fds);
284
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800285 for(;;) {
286 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700287 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800288 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700289 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800290 if(r == 0) break;
291 if(r < 0) {
292 if(errno == EINTR) continue;
293 break;
294 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400295 for(n = 0; n < r; n++){
296 switch(buf[n]) {
297 case '\n':
298 state = 1;
299 break;
300 case '\r':
301 state = 1;
302 break;
303 case '~':
304 if(state == 1) state++;
305 break;
306 case '.':
307 if(state == 2) {
308 fprintf(stderr,"\n* disconnect *\n");
309#ifdef HAVE_TERMIO_H
310 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800311#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400312 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400314 default:
315 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800316 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800317 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800318 r = adb_write(fd, buf, r);
319 if(r <= 0) {
320 break;
321 }
322 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800323 return 0;
324}
325
326int interactive_shell(void)
327{
328 adb_thread_t thr;
329 int fdi, fd;
330 int *fds;
331
332 fd = adb_connect("shell:");
333 if(fd < 0) {
334 fprintf(stderr,"error: %s\n", adb_error());
335 return 1;
336 }
337 fdi = 0; //dup(0);
338
339 fds = malloc(sizeof(int) * 2);
340 fds[0] = fd;
341 fds[1] = fdi;
342
343#ifdef HAVE_TERMIO_H
344 stdin_raw_init(fdi);
345#endif
346 adb_thread_create(&thr, stdin_read_thread, fds);
347 read_and_dump(fd);
348#ifdef HAVE_TERMIO_H
349 stdin_raw_restore(fdi);
350#endif
351 return 0;
352}
353
354
355static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
356{
357 if (serial) {
358 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
359 } else {
360 const char* prefix = "host";
361 if (ttype == kTransportUsb)
362 prefix = "host-usb";
363 else if (ttype == kTransportLocal)
364 prefix = "host-local";
365
366 snprintf(buffer, buflen, "%s:%s", prefix, command);
367 }
368}
369
Doug Zongker6b217ed2012-01-09 14:54:53 -0800370int adb_download_buffer(const char *service, const void* data, int sz,
371 unsigned progress)
372{
373 char buf[4096];
374 unsigned total;
375 int fd;
376 const unsigned char *ptr;
377
378 sprintf(buf,"%s:%d", service, sz);
379 fd = adb_connect(buf);
380 if(fd < 0) {
381 fprintf(stderr,"error: %s\n", adb_error());
382 return -1;
383 }
384
385 int opt = CHUNK_SIZE;
386 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
387
388 total = sz;
389 ptr = data;
390
391 if(progress) {
392 char *x = strrchr(service, ':');
393 if(x) service = x + 1;
394 }
395
396 while(sz > 0) {
397 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
398 if(writex(fd, ptr, xfer)) {
399 adb_status(fd);
400 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
401 return -1;
402 }
403 sz -= xfer;
404 ptr += xfer;
405 if(progress) {
406 printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
407 fflush(stdout);
408 }
409 }
410 if(progress) {
411 printf("\n");
412 }
413
414 if(readx(fd, buf, 4)){
415 fprintf(stderr,"* error reading response *\n");
416 adb_close(fd);
417 return -1;
418 }
419 if(memcmp(buf, "OKAY", 4)) {
420 buf[4] = 0;
421 fprintf(stderr,"* error response '%s' *\n", buf);
422 adb_close(fd);
423 return -1;
424 }
425
426 adb_close(fd);
427 return 0;
428}
429
430
431int adb_download(const char *service, const char *fn, unsigned progress)
432{
433 void *data;
434 unsigned sz;
435
436 data = load_file(fn, &sz);
437 if(data == 0) {
438 fprintf(stderr,"* cannot read '%s' *\n", service);
439 return -1;
440 }
441
442 int status = adb_download_buffer(service, data, sz, progress);
443 free(data);
444 return status;
445}
446
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800447static void status_window(transport_type ttype, const char* serial)
448{
449 char command[4096];
450 char *state = 0;
451 char *laststate = 0;
452
453 /* silence stderr */
454#ifdef _WIN32
455 /* XXX: TODO */
456#else
457 int fd;
458 fd = unix_open("/dev/null", O_WRONLY);
459 dup2(fd, 2);
460 adb_close(fd);
461#endif
462
463 format_host_command(command, sizeof command, "get-state", ttype, serial);
464
465 for(;;) {
466 adb_sleep_ms(250);
467
468 if(state) {
469 free(state);
470 state = 0;
471 }
472
473 state = adb_query(command);
474
475 if(state) {
476 if(laststate && !strcmp(state,laststate)){
477 continue;
478 } else {
479 if(laststate) free(laststate);
480 laststate = strdup(state);
481 }
482 }
483
484 printf("%c[2J%c[2H", 27, 27);
485 printf("Android Debug Bridge\n");
486 printf("State: %s\n", state ? state : "offline");
487 fflush(stdout);
488 }
489}
490
491/** duplicate string and quote all \ " ( ) chars + space character. */
492static char *
493dupAndQuote(const char *s)
494{
495 const char *ts;
496 size_t alloc_len;
497 char *ret;
498 char *dest;
499
500 ts = s;
501
502 alloc_len = 0;
503
504 for( ;*ts != '\0'; ts++) {
505 alloc_len++;
506 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
507 alloc_len++;
508 }
509 }
510
511 ret = (char *)malloc(alloc_len + 1);
512
513 ts = s;
514 dest = ret;
515
516 for ( ;*ts != '\0'; ts++) {
517 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
518 *dest++ = '\\';
519 }
520
521 *dest++ = *ts;
522 }
523
524 *dest++ = '\0';
525
526 return ret;
527}
528
529/**
530 * Run ppp in "notty" mode against a resource listed as the first parameter
531 * eg:
532 *
533 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
534 *
535 */
536int ppp(int argc, char **argv)
537{
538#ifdef HAVE_WIN32_PROC
539 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
540 return -1;
541#else
542 char *adb_service_name;
543 pid_t pid;
544 int fd;
545
546 if (argc < 2) {
547 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
548 argv[0]);
549
550 return 1;
551 }
552
553 adb_service_name = argv[1];
554
555 fd = adb_connect(adb_service_name);
556
557 if(fd < 0) {
558 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
559 adb_service_name, adb_error());
560 return 1;
561 }
562
563 pid = fork();
564
565 if (pid < 0) {
566 perror("from fork()");
567 return 1;
568 } else if (pid == 0) {
569 int err;
570 int i;
571 const char **ppp_args;
572
573 // copy args
574 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
575 ppp_args[0] = "pppd";
576 for (i = 2 ; i < argc ; i++) {
577 //argv[2] and beyond become ppp_args[1] and beyond
578 ppp_args[i - 1] = argv[i];
579 }
580 ppp_args[i-1] = NULL;
581
582 // child side
583
584 dup2(fd, STDIN_FILENO);
585 dup2(fd, STDOUT_FILENO);
586 adb_close(STDERR_FILENO);
587 adb_close(fd);
588
589 err = execvp("pppd", (char * const *)ppp_args);
590
591 if (err < 0) {
592 perror("execing pppd");
593 }
594 exit(-1);
595 } else {
596 // parent side
597
598 adb_close(fd);
599 return 0;
600 }
601#endif /* !HAVE_WIN32_PROC */
602}
603
604static int send_shellcommand(transport_type transport, char* serial, char* buf)
605{
606 int fd, ret;
607
608 for(;;) {
609 fd = adb_connect(buf);
610 if(fd >= 0)
611 break;
612 fprintf(stderr,"- waiting for device -\n");
613 adb_sleep_ms(1000);
614 do_cmd(transport, serial, "wait-for-device", 0);
615 }
616
617 read_and_dump(fd);
618 ret = adb_close(fd);
619 if (ret)
620 perror("close");
621
622 return ret;
623}
624
625static int logcat(transport_type transport, char* serial, int argc, char **argv)
626{
627 char buf[4096];
628
629 char *log_tags;
630 char *quoted_log_tags;
631
632 log_tags = getenv("ANDROID_LOG_TAGS");
633 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
634
635 snprintf(buf, sizeof(buf),
636 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
637 quoted_log_tags);
638
639 free(quoted_log_tags);
640
Christopher Tate7b9b5162011-11-30 13:00:33 -0800641 if (!strcmp(argv[0],"longcat")) {
642 strncat(buf, " -v long", sizeof(buf)-1);
643 }
644
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800645 argc -= 1;
646 argv += 1;
647 while(argc-- > 0) {
648 char *quoted;
649
650 quoted = dupAndQuote (*argv++);
651
652 strncat(buf, " ", sizeof(buf)-1);
653 strncat(buf, quoted, sizeof(buf)-1);
654 free(quoted);
655 }
656
657 send_shellcommand(transport, serial, buf);
658 return 0;
659}
660
Christopher Tate1e9f2392011-12-08 19:04:34 -0800661static int mkdirs(char *path)
662{
663 int ret;
664 char *x = path + 1;
665
666 for(;;) {
667 x = adb_dirstart(x);
668 if(x == 0) return 0;
669 *x = 0;
670 ret = adb_mkdir(path, 0775);
671 *x = OS_PATH_SEPARATOR;
672 if((ret < 0) && (errno != EEXIST)) {
673 return ret;
674 }
675 x++;
676 }
677 return 0;
678}
679
Christopher Tate73779122011-04-21 12:53:28 -0700680static int backup(int argc, char** argv) {
681 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800682 char default_name[32];
683 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700684 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700685 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700686
Christopher Tatefba22972011-06-01 17:56:23 -0700687 /* find, extract, and use any -f argument */
688 for (i = 1; i < argc; i++) {
689 if (!strcmp("-f", argv[i])) {
690 if (i == argc-1) {
691 fprintf(stderr, "adb: -f passed with no filename\n");
692 return usage();
693 }
694 filename = argv[i+1];
695 for (j = i+2; j <= argc; ) {
696 argv[i++] = argv[j++];
697 }
698 argc -= 2;
699 argv[argc] = NULL;
700 }
Christopher Tate73779122011-04-21 12:53:28 -0700701 }
702
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700703 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
704 if (argc < 2) return usage();
705
Christopher Tate1e9f2392011-12-08 19:04:34 -0800706 adb_unlink(filename);
707 mkdirs((char *)filename);
708 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700709 if (outFd < 0) {
710 fprintf(stderr, "adb: unable to open file %s\n", filename);
711 return -1;
712 }
713
714 snprintf(buf, sizeof(buf), "backup");
715 for (argc--, argv++; argc; argc--, argv++) {
716 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
717 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
718 }
719
720 D("backup. filename=%s buf=%s\n", filename, buf);
721 fd = adb_connect(buf);
722 if (fd < 0) {
723 fprintf(stderr, "adb: unable to connect for backup\n");
724 adb_close(outFd);
725 return -1;
726 }
727
Christopher Tate9c829102012-01-06 15:43:03 -0800728 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700729 copy_to_file(fd, outFd);
730
731 adb_close(fd);
732 adb_close(outFd);
733 return 0;
734}
735
Christopher Tatecf5379b2011-05-17 15:52:54 -0700736static int restore(int argc, char** argv) {
737 const char* filename;
738 int fd, tarFd;
739
740 if (argc != 2) return usage();
741
742 filename = argv[1];
743 tarFd = adb_open(filename, O_RDONLY);
744 if (tarFd < 0) {
745 fprintf(stderr, "adb: unable to open file %s\n", filename);
746 return -1;
747 }
748
749 fd = adb_connect("restore:");
750 if (fd < 0) {
751 fprintf(stderr, "adb: unable to connect for backup\n");
752 adb_close(tarFd);
753 return -1;
754 }
755
Christopher Tate9c829102012-01-06 15:43:03 -0800756 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700757 copy_to_file(tarFd, fd);
758
759 adb_close(fd);
760 adb_close(tarFd);
761 return 0;
762}
763
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800764#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
765static int top_works(const char *top)
766{
767 if (top != NULL && adb_is_absolute_host_path(top)) {
768 char path_buf[PATH_MAX];
769 snprintf(path_buf, sizeof(path_buf),
770 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
771 return access(path_buf, F_OK) == 0;
772 }
773 return 0;
774}
775
776static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
777{
778 strcpy(path_buf, indir);
779 while (1) {
780 if (top_works(path_buf)) {
781 return path_buf;
782 }
783 char *s = adb_dirstop(path_buf);
784 if (s != NULL) {
785 *s = '\0';
786 } else {
787 path_buf[0] = '\0';
788 return NULL;
789 }
790 }
791}
792
793static char *find_top(char path_buf[PATH_MAX])
794{
795 char *top = getenv("ANDROID_BUILD_TOP");
796 if (top != NULL && top[0] != '\0') {
797 if (!top_works(top)) {
798 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
799 return NULL;
800 }
801 } else {
802 top = getenv("TOP");
803 if (top != NULL && top[0] != '\0') {
804 if (!top_works(top)) {
805 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
806 return NULL;
807 }
808 } else {
809 top = NULL;
810 }
811 }
812
813 if (top != NULL) {
814 /* The environment pointed to a top directory that works.
815 */
816 strcpy(path_buf, top);
817 return path_buf;
818 }
819
820 /* The environment didn't help. Walk up the tree from the CWD
821 * to see if we can find the top.
822 */
823 char dir[PATH_MAX];
824 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
825 if (top == NULL) {
826 /* If the CWD isn't under a good-looking top, see if the
827 * executable is.
828 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100829 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800830 top = find_top_from(dir, path_buf);
831 }
832 return top;
833}
834
835/* <hint> may be:
836 * - A simple product name
837 * e.g., "sooner"
838TODO: debug? sooner-debug, sooner:debug?
839 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
840 * e.g., "out/target/product/sooner"
841 * - An absolute path to the PRODUCT_OUT dir
842 * e.g., "/src/device/out/target/product/sooner"
843 *
844 * Given <hint>, try to construct an absolute path to the
845 * ANDROID_PRODUCT_OUT dir.
846 */
847static const char *find_product_out_path(const char *hint)
848{
849 static char path_buf[PATH_MAX];
850
851 if (hint == NULL || hint[0] == '\0') {
852 return NULL;
853 }
854
855 /* If it's already absolute, don't bother doing any work.
856 */
857 if (adb_is_absolute_host_path(hint)) {
858 strcpy(path_buf, hint);
859 return path_buf;
860 }
861
862 /* If there are any slashes in it, assume it's a relative path;
863 * make it absolute.
864 */
865 if (adb_dirstart(hint) != NULL) {
866 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
867 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
868 return NULL;
869 }
870 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
871 fprintf(stderr, "adb: Couldn't assemble path\n");
872 return NULL;
873 }
874 strcat(path_buf, OS_PATH_SEPARATOR_STR);
875 strcat(path_buf, hint);
876 return path_buf;
877 }
878
879 /* It's a string without any slashes. Try to do something with it.
880 *
881 * Try to find the root of the build tree, and build a PRODUCT_OUT
882 * path from there.
883 */
884 char top_buf[PATH_MAX];
885 const char *top = find_top(top_buf);
886 if (top == NULL) {
887 fprintf(stderr, "adb: Couldn't find top of build tree\n");
888 return NULL;
889 }
890//TODO: if we have a way to indicate debug, look in out/debug/target/...
891 snprintf(path_buf, sizeof(path_buf),
892 "%s" OS_PATH_SEPARATOR_STR
893 "out" OS_PATH_SEPARATOR_STR
894 "target" OS_PATH_SEPARATOR_STR
895 "product" OS_PATH_SEPARATOR_STR
896 "%s", top_buf, hint);
897 if (access(path_buf, F_OK) < 0) {
898 fprintf(stderr, "adb: Couldn't find a product dir "
899 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
900 return NULL;
901 }
902 return path_buf;
903}
904
905int adb_commandline(int argc, char **argv)
906{
907 char buf[4096];
908 int no_daemon = 0;
909 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100910 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800911 int persist = 0;
912 int r;
913 int quote;
914 transport_type ttype = kTransportAny;
915 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100916 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800917
918 /* If defined, this should be an absolute path to
919 * the directory containing all of the various system images
920 * for a particular product. If not defined, and the adb
921 * command requires this information, then the user must
922 * specify the path using "-p".
923 */
924 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
925 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
926 gProductOutPath = NULL;
927 }
928 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
929
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700930 serial = getenv("ANDROID_SERIAL");
931
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100932 /* Validate and assign the server port */
933 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
934 int server_port = DEFAULT_ADB_PORT;
935 if (server_port_str && strlen(server_port_str) > 0) {
936 server_port = (int) strtol(server_port_str, NULL, 0);
937 if (server_port <= 0) {
938 fprintf(stderr,
939 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
940 server_port_str);
941 return usage();
942 }
943 }
944
945 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800946 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100947 if(!strcmp(argv[0],"server")) {
948 is_server = 1;
949 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800950 no_daemon = 1;
951 } else if (!strcmp(argv[0], "fork-server")) {
952 /* this is a special flag used only when the ADB client launches the ADB Server */
953 is_daemon = 1;
954 } else if(!strcmp(argv[0],"persist")) {
955 persist = 1;
956 } else if(!strncmp(argv[0], "-p", 2)) {
957 const char *product = NULL;
958 if (argv[0][2] == '\0') {
959 if (argc < 2) return usage();
960 product = argv[1];
961 argc--;
962 argv++;
963 } else {
964 product = argv[1] + 2;
965 }
966 gProductOutPath = find_product_out_path(product);
967 if (gProductOutPath == NULL) {
968 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
969 product);
970 return usage();
971 }
972 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
973 if (isdigit(argv[0][2])) {
974 serial = argv[0] + 2;
975 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100976 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800977 serial = argv[1];
978 argc--;
979 argv++;
980 }
981 } else if (!strcmp(argv[0],"-d")) {
982 ttype = kTransportUsb;
983 } else if (!strcmp(argv[0],"-e")) {
984 ttype = kTransportLocal;
985 } else {
986 /* out of recognized modifiers and flags */
987 break;
988 }
989 argc--;
990 argv++;
991 }
992
993 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100994 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800995
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100996 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800997 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100998 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800999 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001000 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001001 }
1002 if(r) {
1003 fprintf(stderr,"* could not start server *\n");
1004 }
1005 return r;
1006 }
1007
1008top:
1009 if(argc == 0) {
1010 return usage();
1011 }
1012
1013 /* adb_connect() commands */
1014
1015 if(!strcmp(argv[0], "devices")) {
1016 char *tmp;
1017 snprintf(buf, sizeof buf, "host:%s", argv[0]);
1018 tmp = adb_query(buf);
1019 if(tmp) {
1020 printf("List of devices attached \n");
1021 printf("%s\n", tmp);
1022 return 0;
1023 } else {
1024 return 1;
1025 }
1026 }
1027
Mike Lockwood01c2c302010-05-24 10:44:35 -04001028 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001029 char *tmp;
1030 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001031 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001032 return 1;
1033 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001034 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1035 tmp = adb_query(buf);
1036 if(tmp) {
1037 printf("%s\n", tmp);
1038 return 0;
1039 } else {
1040 return 1;
1041 }
1042 }
1043
1044 if(!strcmp(argv[0], "disconnect")) {
1045 char *tmp;
1046 if (argc > 2) {
1047 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1048 return 1;
1049 }
1050 if (argc == 2) {
1051 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1052 } else {
1053 snprintf(buf, sizeof buf, "host:disconnect:");
1054 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001055 tmp = adb_query(buf);
1056 if(tmp) {
1057 printf("%s\n", tmp);
1058 return 0;
1059 } else {
1060 return 1;
1061 }
1062 }
1063
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001064 if (!strcmp(argv[0], "emu")) {
1065 return adb_send_emulator_command(argc, argv);
1066 }
1067
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001068 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001069 int r;
1070 int fd;
1071
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001072 char h = (argv[0][0] == 'h');
1073
1074 if (h) {
1075 printf("\x1b[41;33m");
1076 fflush(stdout);
1077 }
1078
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001079 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001080 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001081 r = interactive_shell();
1082 if (h) {
1083 printf("\x1b[0m");
1084 fflush(stdout);
1085 }
1086 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001087 }
1088
1089 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1090 argc -= 2;
1091 argv += 2;
1092 while(argc-- > 0) {
1093 strcat(buf, " ");
1094
1095 /* quote empty strings and strings with spaces */
1096 quote = (**argv == 0 || strchr(*argv, ' '));
1097 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001098 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001099 strcat(buf, *argv++);
1100 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001101 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001102 }
1103
1104 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001105 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001106 fd = adb_connect(buf);
1107 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001108 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001109 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001110 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001111 adb_close(fd);
1112 r = 0;
1113 } else {
1114 fprintf(stderr,"error: %s\n", adb_error());
1115 r = -1;
1116 }
1117
1118 if(persist) {
1119 fprintf(stderr,"\n- waiting for device -\n");
1120 adb_sleep_ms(1000);
1121 do_cmd(ttype, serial, "wait-for-device", 0);
1122 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001123 if (h) {
1124 printf("\x1b[0m");
1125 fflush(stdout);
1126 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001127 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001128 return r;
1129 }
1130 }
1131 }
1132
1133 if(!strcmp(argv[0], "kill-server")) {
1134 int fd;
1135 fd = _adb_connect("host:kill");
1136 if(fd == -1) {
1137 fprintf(stderr,"* server not running *\n");
1138 return 1;
1139 }
1140 return 0;
1141 }
1142
Doug Zongker6b217ed2012-01-09 14:54:53 -08001143 if(!strcmp(argv[0], "sideload")) {
1144 if(argc != 2) return usage();
1145 if(adb_download("sideload", argv[1], 1)) {
1146 return 1;
1147 } else {
1148 return 0;
1149 }
1150 }
1151
Mike Lockwood26b88e32009-08-24 15:58:40 -07001152 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001153 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001154 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001155 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001156 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001157 if (!strcmp(argv[0], "reboot-bootloader"))
1158 snprintf(command, sizeof(command), "reboot:bootloader");
1159 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001160 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001161 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001162 snprintf(command, sizeof(command), "%s:", argv[0]);
1163 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001164 if(fd >= 0) {
1165 read_and_dump(fd);
1166 adb_close(fd);
1167 return 0;
1168 }
1169 fprintf(stderr,"error: %s\n", adb_error());
1170 return 1;
1171 }
1172
Mike Lockwood78589f32009-09-03 14:54:58 -04001173 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001174 if (argc != 1) return usage();
1175 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001176 return 0;
1177 }
1178
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001179 /* adb_command() wrapper commands */
1180
1181 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1182 char* service = argv[0];
1183 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1184 if (ttype == kTransportUsb) {
1185 service = "wait-for-usb";
1186 } else if (ttype == kTransportLocal) {
1187 service = "wait-for-local";
1188 } else {
1189 service = "wait-for-any";
1190 }
1191 }
1192
1193 format_host_command(buf, sizeof buf, service, ttype, serial);
1194
1195 if (adb_command(buf)) {
1196 D("failure: %s *\n",adb_error());
1197 fprintf(stderr,"error: %s\n", adb_error());
1198 return 1;
1199 }
1200
1201 /* Allow a command to be run after wait-for-device,
1202 * e.g. 'adb wait-for-device shell'.
1203 */
1204 if(argc > 1) {
1205 argc--;
1206 argv++;
1207 goto top;
1208 }
1209 return 0;
1210 }
1211
1212 if(!strcmp(argv[0], "forward")) {
1213 if(argc != 3) return usage();
1214 if (serial) {
Mike Lockwood47b41622009-11-28 12:46:13 -05001215 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1216 } else if (ttype == kTransportUsb) {
1217 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1218 } else if (ttype == kTransportLocal) {
1219 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001220 } else {
Mike Lockwood47b41622009-11-28 12:46:13 -05001221 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001222 }
1223 if(adb_command(buf)) {
1224 fprintf(stderr,"error: %s\n", adb_error());
1225 return 1;
1226 }
1227 return 0;
1228 }
1229
1230 /* do_sync_*() commands */
1231
1232 if(!strcmp(argv[0], "ls")) {
1233 if(argc != 2) return usage();
1234 return do_sync_ls(argv[1]);
1235 }
1236
1237 if(!strcmp(argv[0], "push")) {
1238 if(argc != 3) return usage();
1239 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1240 }
1241
1242 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001243 if (argc == 2) {
1244 return do_sync_pull(argv[1], ".");
1245 } else if (argc == 3) {
1246 return do_sync_pull(argv[1], argv[2]);
1247 } else {
1248 return usage();
1249 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001250 }
1251
1252 if(!strcmp(argv[0], "install")) {
1253 if (argc < 2) return usage();
1254 return install_app(ttype, serial, argc, argv);
1255 }
1256
1257 if(!strcmp(argv[0], "uninstall")) {
1258 if (argc < 2) return usage();
1259 return uninstall_app(ttype, serial, argc, argv);
1260 }
1261
1262 if(!strcmp(argv[0], "sync")) {
1263 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001264 int listonly = 0;
1265
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001266 int ret;
1267 if(argc < 2) {
1268 /* No local path was specified. */
1269 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001270 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1271 listonly = 1;
1272 if (argc == 3) {
1273 srcarg = argv[2];
1274 } else {
1275 srcarg = NULL;
1276 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001277 } else if(argc == 2) {
1278 /* A local path or "android"/"data" arg was specified. */
1279 srcarg = argv[1];
1280 } else {
1281 return usage();
1282 }
1283 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1284 if(ret != 0) return usage();
1285
1286 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001287 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001288 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001289 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001290
1291 free(android_srcpath);
1292 free(data_srcpath);
1293 return ret;
1294 }
1295
1296 /* passthrough commands */
1297
1298 if(!strcmp(argv[0],"get-state") ||
1299 !strcmp(argv[0],"get-serialno"))
1300 {
1301 char *tmp;
1302
1303 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1304 tmp = adb_query(buf);
1305 if(tmp) {
1306 printf("%s\n", tmp);
1307 return 0;
1308 } else {
1309 return 1;
1310 }
1311 }
1312
1313 /* other commands */
1314
1315 if(!strcmp(argv[0],"status-window")) {
1316 status_window(ttype, serial);
1317 return 0;
1318 }
1319
Christopher Tate7b9b5162011-11-30 13:00:33 -08001320 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001321 return logcat(ttype, serial, argc, argv);
1322 }
1323
1324 if(!strcmp(argv[0],"ppp")) {
1325 return ppp(argc, argv);
1326 }
1327
1328 if (!strcmp(argv[0], "start-server")) {
1329 return adb_connect("host:start-server");
1330 }
1331
Christopher Tate73779122011-04-21 12:53:28 -07001332 if (!strcmp(argv[0], "backup")) {
1333 return backup(argc, argv);
1334 }
1335
Christopher Tatecf5379b2011-05-17 15:52:54 -07001336 if (!strcmp(argv[0], "restore")) {
1337 return restore(argc, argv);
1338 }
1339
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001340 if (!strcmp(argv[0], "jdwp")) {
1341 int fd = adb_connect("jdwp");
1342 if (fd >= 0) {
1343 read_and_dump(fd);
1344 adb_close(fd);
1345 return 0;
1346 } else {
1347 fprintf(stderr, "error: %s\n", adb_error());
1348 return -1;
1349 }
1350 }
1351
1352 /* "adb /?" is a common idiom under Windows */
1353 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1354 help();
1355 return 0;
1356 }
1357
1358 if(!strcmp(argv[0], "version")) {
1359 version(stdout);
1360 return 0;
1361 }
1362
1363 usage();
1364 return 1;
1365}
1366
1367static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1368{
1369 char *argv[16];
1370 int argc;
1371 va_list ap;
1372
1373 va_start(ap, cmd);
1374 argc = 0;
1375
1376 if (serial) {
1377 argv[argc++] = "-s";
1378 argv[argc++] = serial;
1379 } else if (ttype == kTransportUsb) {
1380 argv[argc++] = "-d";
1381 } else if (ttype == kTransportLocal) {
1382 argv[argc++] = "-e";
1383 }
1384
1385 argv[argc++] = cmd;
1386 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1387 va_end(ap);
1388
1389#if 0
1390 int n;
1391 fprintf(stderr,"argc = %d\n",argc);
1392 for(n = 0; n < argc; n++) {
1393 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1394 }
1395#endif
1396
1397 return adb_commandline(argc, argv);
1398}
1399
1400int find_sync_dirs(const char *srcarg,
1401 char **android_srcdir_out, char **data_srcdir_out)
1402{
1403 char *android_srcdir, *data_srcdir;
1404
1405 if(srcarg == NULL) {
1406 android_srcdir = product_file("system");
1407 data_srcdir = product_file("data");
1408 } else {
1409 /* srcarg may be "data", "system" or NULL.
1410 * if srcarg is NULL, then both data and system are synced
1411 */
1412 if(strcmp(srcarg, "system") == 0) {
1413 android_srcdir = product_file("system");
1414 data_srcdir = NULL;
1415 } else if(strcmp(srcarg, "data") == 0) {
1416 android_srcdir = NULL;
1417 data_srcdir = product_file("data");
1418 } else {
1419 /* It's not "system" or "data".
1420 */
1421 return 1;
1422 }
1423 }
1424
1425 if(android_srcdir_out != NULL)
1426 *android_srcdir_out = android_srcdir;
1427 else
1428 free(android_srcdir);
1429
1430 if(data_srcdir_out != NULL)
1431 *data_srcdir_out = data_srcdir;
1432 else
1433 free(data_srcdir);
1434
1435 return 0;
1436}
1437
1438static int pm_command(transport_type transport, char* serial,
1439 int argc, char** argv)
1440{
1441 char buf[4096];
1442
1443 snprintf(buf, sizeof(buf), "shell:pm");
1444
1445 while(argc-- > 0) {
1446 char *quoted;
1447
1448 quoted = dupAndQuote(*argv++);
1449
1450 strncat(buf, " ", sizeof(buf)-1);
1451 strncat(buf, quoted, sizeof(buf)-1);
1452 free(quoted);
1453 }
1454
1455 send_shellcommand(transport, serial, buf);
1456 return 0;
1457}
1458
1459int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1460{
1461 /* if the user choose the -k option, we refuse to do it until devices are
1462 out with the option to uninstall the remaining data somehow (adb/ui) */
1463 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1464 {
1465 printf(
1466 "The -k option uninstalls the application while retaining the data/cache.\n"
1467 "At the moment, there is no way to remove the remaining data.\n"
1468 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1469 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1470 return -1;
1471 }
1472
1473 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1474 return pm_command(transport, serial, argc, argv);
1475}
1476
1477static int delete_file(transport_type transport, char* serial, char* filename)
1478{
1479 char buf[4096];
1480 char* quoted;
1481
1482 snprintf(buf, sizeof(buf), "shell:rm ");
1483 quoted = dupAndQuote(filename);
1484 strncat(buf, quoted, sizeof(buf)-1);
1485 free(quoted);
1486
1487 send_shellcommand(transport, serial, buf);
1488 return 0;
1489}
1490
Kenny Root3802c992011-08-05 11:19:45 -07001491static const char* get_basename(const char* filename)
1492{
1493 const char* basename = adb_dirstop(filename);
1494 if (basename) {
1495 basename++;
1496 return basename;
1497 } else {
1498 return filename;
1499 }
1500}
1501
1502static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001503{
1504 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001505
Kenny Root3802c992011-08-05 11:19:45 -07001506 if (filename == NULL) {
1507 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001508 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001509
Kenny Root3802c992011-08-05 11:19:45 -07001510 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001511 fprintf(stderr, "can't find '%s' to install\n", filename);
1512 return 1;
1513 }
Kenny Root3802c992011-08-05 11:19:45 -07001514
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001515 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001516 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001517 return 1;
1518 }
1519
Kenny Root3802c992011-08-05 11:19:45 -07001520 return 0;
1521}
1522
1523int install_app(transport_type transport, char* serial, int argc, char** argv)
1524{
1525 static const char *const DATA_DEST = "/data/local/tmp/%s";
1526 static const char *const SD_DEST = "/sdcard/tmp/%s";
1527 const char* where = DATA_DEST;
1528 char apk_dest[PATH_MAX];
1529 char verification_dest[PATH_MAX];
1530 char* apk_file;
1531 char* verification_file = NULL;
1532 int file_arg = -1;
1533 int err;
1534 int i;
1535
1536 for (i = 1; i < argc; i++) {
1537 if (*argv[i] != '-') {
1538 file_arg = i;
1539 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001540 } else if (!strcmp(argv[i], "-i")) {
1541 // Skip the installer package name.
1542 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001543 } else if (!strcmp(argv[i], "-s")) {
1544 where = SD_DEST;
1545 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001546 }
1547
Kenny Root3802c992011-08-05 11:19:45 -07001548 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001549 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001550 return 1;
1551 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001552 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001553 return 1;
1554 }
1555
1556 apk_file = argv[file_arg];
1557
1558 if (file_arg != argc - 1) {
1559 verification_file = argv[file_arg + 1];
1560 }
1561
1562 if (check_file(apk_file) || check_file(verification_file)) {
1563 return 1;
1564 }
1565
1566 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1567 if (verification_file != NULL) {
1568 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1569
1570 if (!strcmp(apk_dest, verification_dest)) {
1571 fprintf(stderr, "APK and verification file can't have the same name\n");
1572 return 1;
1573 }
1574 }
1575
1576 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1577 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001578 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001579 } else {
1580 argv[file_arg] = apk_dest; /* destination name, not source location */
1581 }
1582
1583 if (verification_file != NULL) {
1584 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1585 if (err) {
1586 goto cleanup_apk;
1587 } else {
1588 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1589 }
1590 }
1591
1592 pm_command(transport, serial, argc, argv);
1593
Kenny Root58d5f222012-03-26 16:14:02 -07001594cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001595 if (verification_file != NULL) {
1596 delete_file(transport, serial, verification_dest);
1597 }
1598
Kenny Root3802c992011-08-05 11:19:45 -07001599 delete_file(transport, serial, apk_dest);
1600
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001601 return err;
1602}