blob: 2dc86f2762b3d4fc7b7ade220fed6ba5fba6ea33 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov31664102009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-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 Pellydb449262009-05-07 12:48:03 -070088 " the given serial number. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Projectdd7bc332009-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 Lockwoodcbbe79a2010-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-Fischer6715a432011-04-26 12:46:05 +0200101 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400102 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 "\n"
104 "device commands:\n"
105 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato00c0eea2010-01-05 13:42:25 -0800106 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600108 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-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 Lockwood0ef3fd02010-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 Projectdd7bc332009-03-03 19:32:55 -0800124 " ('-l' means forward-lock the app)\n"
125 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500126 " ('-s' means install on SD card instead of internal storage)\n"
The Android Open Source Projectdd7bc332009-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 Tated2f54152011-04-21 12:53:28 -0700132 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [<packages...>]\n"
133 " - Write a tarfile backup of the device's data to <file>.\n"
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700134 " If a -f option is not supplied then the data is\n"
135 " written to \"backup.tar\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700136 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
137 " in the tarfile; the default is noapk.)\n"
138 " (-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"
141 " (<packages...> is the list of applications to be backed up. If\n"
142 " the -all or -shared flags are passed, then the package\n"
143 " list is optional.)\n"
144 "\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700145 " adb restore <file> - restore device contents from the <file> backup tarfile\n"
146 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800147 " adb help - show this help message\n"
148 " adb version - show version num\n"
149 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 "scripting:\n"
151 " adb wait-for-device - block until device is online\n"
152 " adb start-server - ensure that there is a server running\n"
153 " adb kill-server - kill the server if it is running\n"
154 " adb get-state - prints: offline | bootloader | device\n"
155 " adb get-serialno - prints: <serial-number>\n"
156 " adb status-window - continuously print device status for a specified device\n"
157 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400158 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800159 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700160 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800161 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700162 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800163 "\n"
164 "networking:\n"
165 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500166 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
168 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
169 "\n"
170 "adb sync notes: adb sync [ <directory> ]\n"
171 " <localdir> can be interpreted in several ways:\n"
172 "\n"
173 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
174 "\n"
175 " - If it is \"system\" or \"data\", only the corresponding partition\n"
176 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000177 "\n"
178 "environmental variables:\n"
179 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
180 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
181 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
182 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800183 );
184}
185
186int usage()
187{
188 help();
189 return 1;
190}
191
192#ifdef HAVE_TERMIO_H
193static struct termios tio_save;
194
195static void stdin_raw_init(int fd)
196{
197 struct termios tio;
198
199 if(tcgetattr(fd, &tio)) return;
200 if(tcgetattr(fd, &tio_save)) return;
201
202 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
203
204 /* no timeout but request at least one character per read */
205 tio.c_cc[VTIME] = 0;
206 tio.c_cc[VMIN] = 1;
207
208 tcsetattr(fd, TCSANOW, &tio);
209 tcflush(fd, TCIFLUSH);
210}
211
212static void stdin_raw_restore(int fd)
213{
214 tcsetattr(fd, TCSANOW, &tio_save);
215 tcflush(fd, TCIFLUSH);
216}
217#endif
218
219static void read_and_dump(int fd)
220{
221 char buf[4096];
222 int len;
223
224 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700225 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700227 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 if(len == 0) {
229 break;
230 }
231
232 if(len < 0) {
233 if(errno == EINTR) continue;
234 break;
235 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400236 fwrite(buf, 1, len, stdout);
237 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238 }
239}
240
Christopher Tated2f54152011-04-21 12:53:28 -0700241static void copy_to_file(int inFd, int outFd) {
242 char buf[4096];
243 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700244 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700245
246 D("copy_to_file(%d -> %d)\n", inFd, outFd);
247 for (;;) {
248 len = adb_read(inFd, buf, sizeof(buf));
249 if (len == 0) {
250 break;
251 }
252 if (len < 0) {
253 if (errno == EINTR) continue;
254 D("copy_to_file() : error %d\n", errno);
255 break;
256 }
257 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700258 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700259 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700260 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tated2f54152011-04-21 12:53:28 -0700261}
262
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263static void *stdin_read_thread(void *x)
264{
265 int fd, fdi;
266 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 int r, n;
268 int state = 0;
269
270 int *fds = (int*) x;
271 fd = fds[0];
272 fdi = fds[1];
273 free(fds);
274
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800275 for(;;) {
276 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700277 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700279 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800280 if(r == 0) break;
281 if(r < 0) {
282 if(errno == EINTR) continue;
283 break;
284 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400285 for(n = 0; n < r; n++){
286 switch(buf[n]) {
287 case '\n':
288 state = 1;
289 break;
290 case '\r':
291 state = 1;
292 break;
293 case '~':
294 if(state == 1) state++;
295 break;
296 case '.':
297 if(state == 2) {
298 fprintf(stderr,"\n* disconnect *\n");
299#ifdef HAVE_TERMIO_H
300 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400302 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800303 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400304 default:
305 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800306 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800308 r = adb_write(fd, buf, r);
309 if(r <= 0) {
310 break;
311 }
312 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313 return 0;
314}
315
316int interactive_shell(void)
317{
318 adb_thread_t thr;
319 int fdi, fd;
320 int *fds;
321
322 fd = adb_connect("shell:");
323 if(fd < 0) {
324 fprintf(stderr,"error: %s\n", adb_error());
325 return 1;
326 }
327 fdi = 0; //dup(0);
328
329 fds = malloc(sizeof(int) * 2);
330 fds[0] = fd;
331 fds[1] = fdi;
332
333#ifdef HAVE_TERMIO_H
334 stdin_raw_init(fdi);
335#endif
336 adb_thread_create(&thr, stdin_read_thread, fds);
337 read_and_dump(fd);
338#ifdef HAVE_TERMIO_H
339 stdin_raw_restore(fdi);
340#endif
341 return 0;
342}
343
344
345static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
346{
347 if (serial) {
348 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
349 } else {
350 const char* prefix = "host";
351 if (ttype == kTransportUsb)
352 prefix = "host-usb";
353 else if (ttype == kTransportLocal)
354 prefix = "host-local";
355
356 snprintf(buffer, buflen, "%s:%s", prefix, command);
357 }
358}
359
360static void status_window(transport_type ttype, const char* serial)
361{
362 char command[4096];
363 char *state = 0;
364 char *laststate = 0;
365
366 /* silence stderr */
367#ifdef _WIN32
368 /* XXX: TODO */
369#else
370 int fd;
371 fd = unix_open("/dev/null", O_WRONLY);
372 dup2(fd, 2);
373 adb_close(fd);
374#endif
375
376 format_host_command(command, sizeof command, "get-state", ttype, serial);
377
378 for(;;) {
379 adb_sleep_ms(250);
380
381 if(state) {
382 free(state);
383 state = 0;
384 }
385
386 state = adb_query(command);
387
388 if(state) {
389 if(laststate && !strcmp(state,laststate)){
390 continue;
391 } else {
392 if(laststate) free(laststate);
393 laststate = strdup(state);
394 }
395 }
396
397 printf("%c[2J%c[2H", 27, 27);
398 printf("Android Debug Bridge\n");
399 printf("State: %s\n", state ? state : "offline");
400 fflush(stdout);
401 }
402}
403
404/** duplicate string and quote all \ " ( ) chars + space character. */
405static char *
406dupAndQuote(const char *s)
407{
408 const char *ts;
409 size_t alloc_len;
410 char *ret;
411 char *dest;
412
413 ts = s;
414
415 alloc_len = 0;
416
417 for( ;*ts != '\0'; ts++) {
418 alloc_len++;
419 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
420 alloc_len++;
421 }
422 }
423
424 ret = (char *)malloc(alloc_len + 1);
425
426 ts = s;
427 dest = ret;
428
429 for ( ;*ts != '\0'; ts++) {
430 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
431 *dest++ = '\\';
432 }
433
434 *dest++ = *ts;
435 }
436
437 *dest++ = '\0';
438
439 return ret;
440}
441
442/**
443 * Run ppp in "notty" mode against a resource listed as the first parameter
444 * eg:
445 *
446 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
447 *
448 */
449int ppp(int argc, char **argv)
450{
451#ifdef HAVE_WIN32_PROC
452 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
453 return -1;
454#else
455 char *adb_service_name;
456 pid_t pid;
457 int fd;
458
459 if (argc < 2) {
460 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
461 argv[0]);
462
463 return 1;
464 }
465
466 adb_service_name = argv[1];
467
468 fd = adb_connect(adb_service_name);
469
470 if(fd < 0) {
471 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
472 adb_service_name, adb_error());
473 return 1;
474 }
475
476 pid = fork();
477
478 if (pid < 0) {
479 perror("from fork()");
480 return 1;
481 } else if (pid == 0) {
482 int err;
483 int i;
484 const char **ppp_args;
485
486 // copy args
487 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
488 ppp_args[0] = "pppd";
489 for (i = 2 ; i < argc ; i++) {
490 //argv[2] and beyond become ppp_args[1] and beyond
491 ppp_args[i - 1] = argv[i];
492 }
493 ppp_args[i-1] = NULL;
494
495 // child side
496
497 dup2(fd, STDIN_FILENO);
498 dup2(fd, STDOUT_FILENO);
499 adb_close(STDERR_FILENO);
500 adb_close(fd);
501
502 err = execvp("pppd", (char * const *)ppp_args);
503
504 if (err < 0) {
505 perror("execing pppd");
506 }
507 exit(-1);
508 } else {
509 // parent side
510
511 adb_close(fd);
512 return 0;
513 }
514#endif /* !HAVE_WIN32_PROC */
515}
516
517static int send_shellcommand(transport_type transport, char* serial, char* buf)
518{
519 int fd, ret;
520
521 for(;;) {
522 fd = adb_connect(buf);
523 if(fd >= 0)
524 break;
525 fprintf(stderr,"- waiting for device -\n");
526 adb_sleep_ms(1000);
527 do_cmd(transport, serial, "wait-for-device", 0);
528 }
529
530 read_and_dump(fd);
531 ret = adb_close(fd);
532 if (ret)
533 perror("close");
534
535 return ret;
536}
537
538static int logcat(transport_type transport, char* serial, int argc, char **argv)
539{
540 char buf[4096];
541
542 char *log_tags;
543 char *quoted_log_tags;
544
545 log_tags = getenv("ANDROID_LOG_TAGS");
546 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
547
548 snprintf(buf, sizeof(buf),
549 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
550 quoted_log_tags);
551
552 free(quoted_log_tags);
553
554 argc -= 1;
555 argv += 1;
556 while(argc-- > 0) {
557 char *quoted;
558
559 quoted = dupAndQuote (*argv++);
560
561 strncat(buf, " ", sizeof(buf)-1);
562 strncat(buf, quoted, sizeof(buf)-1);
563 free(quoted);
564 }
565
566 send_shellcommand(transport, serial, buf);
567 return 0;
568}
569
Christopher Tated2f54152011-04-21 12:53:28 -0700570static int backup(int argc, char** argv) {
571 char buf[4096];
572 const char* filename = "./backup.tar";
573 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700574 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700575
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700576 /* bare "adb backup" is not a valid command */
577 if (argc < 2) return usage();
578
579 /* find, extract, and use any -f argument */
580 for (i = 1; i < argc; i++) {
581 if (!strcmp("-f", argv[i])) {
582 if (i == argc-1) {
583 fprintf(stderr, "adb: -f passed with no filename\n");
584 return usage();
585 }
586 filename = argv[i+1];
587 for (j = i+2; j <= argc; ) {
588 argv[i++] = argv[j++];
589 }
590 argc -= 2;
591 argv[argc] = NULL;
592 }
Christopher Tated2f54152011-04-21 12:53:28 -0700593 }
594
595 outFd = adb_open_mode(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
596 if (outFd < 0) {
597 fprintf(stderr, "adb: unable to open file %s\n", filename);
598 return -1;
599 }
600
601 snprintf(buf, sizeof(buf), "backup");
602 for (argc--, argv++; argc; argc--, argv++) {
603 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
604 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
605 }
606
607 D("backup. filename=%s buf=%s\n", filename, buf);
608 fd = adb_connect(buf);
609 if (fd < 0) {
610 fprintf(stderr, "adb: unable to connect for backup\n");
611 adb_close(outFd);
612 return -1;
613 }
614
615 copy_to_file(fd, outFd);
616
617 adb_close(fd);
618 adb_close(outFd);
619 return 0;
620}
621
Christopher Tate702967a2011-05-17 15:52:54 -0700622static int restore(int argc, char** argv) {
623 const char* filename;
624 int fd, tarFd;
625
626 if (argc != 2) return usage();
627
628 filename = argv[1];
629 tarFd = adb_open(filename, O_RDONLY);
630 if (tarFd < 0) {
631 fprintf(stderr, "adb: unable to open file %s\n", filename);
632 return -1;
633 }
634
635 fd = adb_connect("restore:");
636 if (fd < 0) {
637 fprintf(stderr, "adb: unable to connect for backup\n");
638 adb_close(tarFd);
639 return -1;
640 }
641
642 copy_to_file(tarFd, fd);
643
644 adb_close(fd);
645 adb_close(tarFd);
646 return 0;
647}
648
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800649#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
650static int top_works(const char *top)
651{
652 if (top != NULL && adb_is_absolute_host_path(top)) {
653 char path_buf[PATH_MAX];
654 snprintf(path_buf, sizeof(path_buf),
655 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
656 return access(path_buf, F_OK) == 0;
657 }
658 return 0;
659}
660
661static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
662{
663 strcpy(path_buf, indir);
664 while (1) {
665 if (top_works(path_buf)) {
666 return path_buf;
667 }
668 char *s = adb_dirstop(path_buf);
669 if (s != NULL) {
670 *s = '\0';
671 } else {
672 path_buf[0] = '\0';
673 return NULL;
674 }
675 }
676}
677
678static char *find_top(char path_buf[PATH_MAX])
679{
680 char *top = getenv("ANDROID_BUILD_TOP");
681 if (top != NULL && top[0] != '\0') {
682 if (!top_works(top)) {
683 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
684 return NULL;
685 }
686 } else {
687 top = getenv("TOP");
688 if (top != NULL && top[0] != '\0') {
689 if (!top_works(top)) {
690 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
691 return NULL;
692 }
693 } else {
694 top = NULL;
695 }
696 }
697
698 if (top != NULL) {
699 /* The environment pointed to a top directory that works.
700 */
701 strcpy(path_buf, top);
702 return path_buf;
703 }
704
705 /* The environment didn't help. Walk up the tree from the CWD
706 * to see if we can find the top.
707 */
708 char dir[PATH_MAX];
709 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
710 if (top == NULL) {
711 /* If the CWD isn't under a good-looking top, see if the
712 * executable is.
713 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100714 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715 top = find_top_from(dir, path_buf);
716 }
717 return top;
718}
719
720/* <hint> may be:
721 * - A simple product name
722 * e.g., "sooner"
723TODO: debug? sooner-debug, sooner:debug?
724 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
725 * e.g., "out/target/product/sooner"
726 * - An absolute path to the PRODUCT_OUT dir
727 * e.g., "/src/device/out/target/product/sooner"
728 *
729 * Given <hint>, try to construct an absolute path to the
730 * ANDROID_PRODUCT_OUT dir.
731 */
732static const char *find_product_out_path(const char *hint)
733{
734 static char path_buf[PATH_MAX];
735
736 if (hint == NULL || hint[0] == '\0') {
737 return NULL;
738 }
739
740 /* If it's already absolute, don't bother doing any work.
741 */
742 if (adb_is_absolute_host_path(hint)) {
743 strcpy(path_buf, hint);
744 return path_buf;
745 }
746
747 /* If there are any slashes in it, assume it's a relative path;
748 * make it absolute.
749 */
750 if (adb_dirstart(hint) != NULL) {
751 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
752 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
753 return NULL;
754 }
755 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
756 fprintf(stderr, "adb: Couldn't assemble path\n");
757 return NULL;
758 }
759 strcat(path_buf, OS_PATH_SEPARATOR_STR);
760 strcat(path_buf, hint);
761 return path_buf;
762 }
763
764 /* It's a string without any slashes. Try to do something with it.
765 *
766 * Try to find the root of the build tree, and build a PRODUCT_OUT
767 * path from there.
768 */
769 char top_buf[PATH_MAX];
770 const char *top = find_top(top_buf);
771 if (top == NULL) {
772 fprintf(stderr, "adb: Couldn't find top of build tree\n");
773 return NULL;
774 }
775//TODO: if we have a way to indicate debug, look in out/debug/target/...
776 snprintf(path_buf, sizeof(path_buf),
777 "%s" OS_PATH_SEPARATOR_STR
778 "out" OS_PATH_SEPARATOR_STR
779 "target" OS_PATH_SEPARATOR_STR
780 "product" OS_PATH_SEPARATOR_STR
781 "%s", top_buf, hint);
782 if (access(path_buf, F_OK) < 0) {
783 fprintf(stderr, "adb: Couldn't find a product dir "
784 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
785 return NULL;
786 }
787 return path_buf;
788}
789
790int adb_commandline(int argc, char **argv)
791{
792 char buf[4096];
793 int no_daemon = 0;
794 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100795 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800796 int persist = 0;
797 int r;
798 int quote;
799 transport_type ttype = kTransportAny;
800 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100801 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800802
803 /* If defined, this should be an absolute path to
804 * the directory containing all of the various system images
805 * for a particular product. If not defined, and the adb
806 * command requires this information, then the user must
807 * specify the path using "-p".
808 */
809 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
810 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
811 gProductOutPath = NULL;
812 }
813 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
814
Nick Pellydb449262009-05-07 12:48:03 -0700815 serial = getenv("ANDROID_SERIAL");
816
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100817 /* Validate and assign the server port */
818 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
819 int server_port = DEFAULT_ADB_PORT;
820 if (server_port_str && strlen(server_port_str) > 0) {
821 server_port = (int) strtol(server_port_str, NULL, 0);
822 if (server_port <= 0) {
823 fprintf(stderr,
824 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
825 server_port_str);
826 return usage();
827 }
828 }
829
830 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800831 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100832 if(!strcmp(argv[0],"server")) {
833 is_server = 1;
834 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835 no_daemon = 1;
836 } else if (!strcmp(argv[0], "fork-server")) {
837 /* this is a special flag used only when the ADB client launches the ADB Server */
838 is_daemon = 1;
839 } else if(!strcmp(argv[0],"persist")) {
840 persist = 1;
841 } else if(!strncmp(argv[0], "-p", 2)) {
842 const char *product = NULL;
843 if (argv[0][2] == '\0') {
844 if (argc < 2) return usage();
845 product = argv[1];
846 argc--;
847 argv++;
848 } else {
849 product = argv[1] + 2;
850 }
851 gProductOutPath = find_product_out_path(product);
852 if (gProductOutPath == NULL) {
853 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
854 product);
855 return usage();
856 }
857 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
858 if (isdigit(argv[0][2])) {
859 serial = argv[0] + 2;
860 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100861 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800862 serial = argv[1];
863 argc--;
864 argv++;
865 }
866 } else if (!strcmp(argv[0],"-d")) {
867 ttype = kTransportUsb;
868 } else if (!strcmp(argv[0],"-e")) {
869 ttype = kTransportLocal;
870 } else {
871 /* out of recognized modifiers and flags */
872 break;
873 }
874 argc--;
875 argv++;
876 }
877
878 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100879 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800880
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100881 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800882 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100883 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800884 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100885 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800886 }
887 if(r) {
888 fprintf(stderr,"* could not start server *\n");
889 }
890 return r;
891 }
892
893top:
894 if(argc == 0) {
895 return usage();
896 }
897
898 /* adb_connect() commands */
899
900 if(!strcmp(argv[0], "devices")) {
901 char *tmp;
902 snprintf(buf, sizeof buf, "host:%s", argv[0]);
903 tmp = adb_query(buf);
904 if(tmp) {
905 printf("List of devices attached \n");
906 printf("%s\n", tmp);
907 return 0;
908 } else {
909 return 1;
910 }
911 }
912
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400913 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700914 char *tmp;
915 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400916 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -0700917 return 1;
918 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400919 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
920 tmp = adb_query(buf);
921 if(tmp) {
922 printf("%s\n", tmp);
923 return 0;
924 } else {
925 return 1;
926 }
927 }
928
929 if(!strcmp(argv[0], "disconnect")) {
930 char *tmp;
931 if (argc > 2) {
932 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
933 return 1;
934 }
935 if (argc == 2) {
936 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
937 } else {
938 snprintf(buf, sizeof buf, "host:disconnect:");
939 }
Mike Lockwoodff196702009-08-24 15:58:40 -0700940 tmp = adb_query(buf);
941 if(tmp) {
942 printf("%s\n", tmp);
943 return 0;
944 } else {
945 return 1;
946 }
947 }
948
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800949 if (!strcmp(argv[0], "emu")) {
950 return adb_send_emulator_command(argc, argv);
951 }
952
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400953 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800954 int r;
955 int fd;
956
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400957 char h = (argv[0][0] == 'h');
958
959 if (h) {
960 printf("\x1b[41;33m");
961 fflush(stdout);
962 }
963
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -0700965 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400966 r = interactive_shell();
967 if (h) {
968 printf("\x1b[0m");
969 fflush(stdout);
970 }
971 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800972 }
973
974 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
975 argc -= 2;
976 argv += 2;
977 while(argc-- > 0) {
978 strcat(buf, " ");
979
980 /* quote empty strings and strings with spaces */
981 quote = (**argv == 0 || strchr(*argv, ' '));
982 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100983 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800984 strcat(buf, *argv++);
985 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100986 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800987 }
988
989 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -0700990 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800991 fd = adb_connect(buf);
992 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700993 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800994 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -0700995 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 adb_close(fd);
997 r = 0;
998 } else {
999 fprintf(stderr,"error: %s\n", adb_error());
1000 r = -1;
1001 }
1002
1003 if(persist) {
1004 fprintf(stderr,"\n- waiting for device -\n");
1005 adb_sleep_ms(1000);
1006 do_cmd(ttype, serial, "wait-for-device", 0);
1007 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001008 if (h) {
1009 printf("\x1b[0m");
1010 fflush(stdout);
1011 }
JP Abgrall408fa572011-03-16 15:57:42 -07001012 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001013 return r;
1014 }
1015 }
1016 }
1017
1018 if(!strcmp(argv[0], "kill-server")) {
1019 int fd;
1020 fd = _adb_connect("host:kill");
1021 if(fd == -1) {
1022 fprintf(stderr,"* server not running *\n");
1023 return 1;
1024 }
1025 return 0;
1026 }
1027
Mike Lockwoodff196702009-08-24 15:58:40 -07001028 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001029 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001030 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001031 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001032 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001033 if (!strcmp(argv[0], "reboot-bootloader"))
1034 snprintf(command, sizeof(command), "reboot:bootloader");
1035 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001036 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001037 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001038 snprintf(command, sizeof(command), "%s:", argv[0]);
1039 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001040 if(fd >= 0) {
1041 read_and_dump(fd);
1042 adb_close(fd);
1043 return 0;
1044 }
1045 fprintf(stderr,"error: %s\n", adb_error());
1046 return 1;
1047 }
1048
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001049 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001050 if (argc != 1) return usage();
1051 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001052 return 0;
1053 }
1054
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001055 /* adb_command() wrapper commands */
1056
1057 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1058 char* service = argv[0];
1059 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1060 if (ttype == kTransportUsb) {
1061 service = "wait-for-usb";
1062 } else if (ttype == kTransportLocal) {
1063 service = "wait-for-local";
1064 } else {
1065 service = "wait-for-any";
1066 }
1067 }
1068
1069 format_host_command(buf, sizeof buf, service, ttype, serial);
1070
1071 if (adb_command(buf)) {
1072 D("failure: %s *\n",adb_error());
1073 fprintf(stderr,"error: %s\n", adb_error());
1074 return 1;
1075 }
1076
1077 /* Allow a command to be run after wait-for-device,
1078 * e.g. 'adb wait-for-device shell'.
1079 */
1080 if(argc > 1) {
1081 argc--;
1082 argv++;
1083 goto top;
1084 }
1085 return 0;
1086 }
1087
1088 if(!strcmp(argv[0], "forward")) {
1089 if(argc != 3) return usage();
1090 if (serial) {
Mike Lockwood64e99542009-11-28 12:46:13 -05001091 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1092 } else if (ttype == kTransportUsb) {
1093 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1094 } else if (ttype == kTransportLocal) {
1095 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001096 } else {
Mike Lockwood64e99542009-11-28 12:46:13 -05001097 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001098 }
1099 if(adb_command(buf)) {
1100 fprintf(stderr,"error: %s\n", adb_error());
1101 return 1;
1102 }
1103 return 0;
1104 }
1105
1106 /* do_sync_*() commands */
1107
1108 if(!strcmp(argv[0], "ls")) {
1109 if(argc != 2) return usage();
1110 return do_sync_ls(argv[1]);
1111 }
1112
1113 if(!strcmp(argv[0], "push")) {
1114 if(argc != 3) return usage();
1115 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1116 }
1117
1118 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001119 if (argc == 2) {
1120 return do_sync_pull(argv[1], ".");
1121 } else if (argc == 3) {
1122 return do_sync_pull(argv[1], argv[2]);
1123 } else {
1124 return usage();
1125 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001126 }
1127
1128 if(!strcmp(argv[0], "install")) {
1129 if (argc < 2) return usage();
1130 return install_app(ttype, serial, argc, argv);
1131 }
1132
1133 if(!strcmp(argv[0], "uninstall")) {
1134 if (argc < 2) return usage();
1135 return uninstall_app(ttype, serial, argc, argv);
1136 }
1137
1138 if(!strcmp(argv[0], "sync")) {
1139 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001140 int listonly = 0;
1141
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001142 int ret;
1143 if(argc < 2) {
1144 /* No local path was specified. */
1145 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001146 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1147 listonly = 1;
1148 if (argc == 3) {
1149 srcarg = argv[2];
1150 } else {
1151 srcarg = NULL;
1152 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001153 } else if(argc == 2) {
1154 /* A local path or "android"/"data" arg was specified. */
1155 srcarg = argv[1];
1156 } else {
1157 return usage();
1158 }
1159 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1160 if(ret != 0) return usage();
1161
1162 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001163 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001164 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001165 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001166
1167 free(android_srcpath);
1168 free(data_srcpath);
1169 return ret;
1170 }
1171
1172 /* passthrough commands */
1173
1174 if(!strcmp(argv[0],"get-state") ||
1175 !strcmp(argv[0],"get-serialno"))
1176 {
1177 char *tmp;
1178
1179 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1180 tmp = adb_query(buf);
1181 if(tmp) {
1182 printf("%s\n", tmp);
1183 return 0;
1184 } else {
1185 return 1;
1186 }
1187 }
1188
1189 /* other commands */
1190
1191 if(!strcmp(argv[0],"status-window")) {
1192 status_window(ttype, serial);
1193 return 0;
1194 }
1195
1196 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1197 return logcat(ttype, serial, argc, argv);
1198 }
1199
1200 if(!strcmp(argv[0],"ppp")) {
1201 return ppp(argc, argv);
1202 }
1203
1204 if (!strcmp(argv[0], "start-server")) {
1205 return adb_connect("host:start-server");
1206 }
1207
Christopher Tated2f54152011-04-21 12:53:28 -07001208 if (!strcmp(argv[0], "backup")) {
1209 return backup(argc, argv);
1210 }
1211
Christopher Tate702967a2011-05-17 15:52:54 -07001212 if (!strcmp(argv[0], "restore")) {
1213 return restore(argc, argv);
1214 }
1215
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001216 if (!strcmp(argv[0], "jdwp")) {
1217 int fd = adb_connect("jdwp");
1218 if (fd >= 0) {
1219 read_and_dump(fd);
1220 adb_close(fd);
1221 return 0;
1222 } else {
1223 fprintf(stderr, "error: %s\n", adb_error());
1224 return -1;
1225 }
1226 }
1227
1228 /* "adb /?" is a common idiom under Windows */
1229 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1230 help();
1231 return 0;
1232 }
1233
1234 if(!strcmp(argv[0], "version")) {
1235 version(stdout);
1236 return 0;
1237 }
1238
1239 usage();
1240 return 1;
1241}
1242
1243static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1244{
1245 char *argv[16];
1246 int argc;
1247 va_list ap;
1248
1249 va_start(ap, cmd);
1250 argc = 0;
1251
1252 if (serial) {
1253 argv[argc++] = "-s";
1254 argv[argc++] = serial;
1255 } else if (ttype == kTransportUsb) {
1256 argv[argc++] = "-d";
1257 } else if (ttype == kTransportLocal) {
1258 argv[argc++] = "-e";
1259 }
1260
1261 argv[argc++] = cmd;
1262 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1263 va_end(ap);
1264
1265#if 0
1266 int n;
1267 fprintf(stderr,"argc = %d\n",argc);
1268 for(n = 0; n < argc; n++) {
1269 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1270 }
1271#endif
1272
1273 return adb_commandline(argc, argv);
1274}
1275
1276int find_sync_dirs(const char *srcarg,
1277 char **android_srcdir_out, char **data_srcdir_out)
1278{
1279 char *android_srcdir, *data_srcdir;
1280
1281 if(srcarg == NULL) {
1282 android_srcdir = product_file("system");
1283 data_srcdir = product_file("data");
1284 } else {
1285 /* srcarg may be "data", "system" or NULL.
1286 * if srcarg is NULL, then both data and system are synced
1287 */
1288 if(strcmp(srcarg, "system") == 0) {
1289 android_srcdir = product_file("system");
1290 data_srcdir = NULL;
1291 } else if(strcmp(srcarg, "data") == 0) {
1292 android_srcdir = NULL;
1293 data_srcdir = product_file("data");
1294 } else {
1295 /* It's not "system" or "data".
1296 */
1297 return 1;
1298 }
1299 }
1300
1301 if(android_srcdir_out != NULL)
1302 *android_srcdir_out = android_srcdir;
1303 else
1304 free(android_srcdir);
1305
1306 if(data_srcdir_out != NULL)
1307 *data_srcdir_out = data_srcdir;
1308 else
1309 free(data_srcdir);
1310
1311 return 0;
1312}
1313
1314static int pm_command(transport_type transport, char* serial,
1315 int argc, char** argv)
1316{
1317 char buf[4096];
1318
1319 snprintf(buf, sizeof(buf), "shell:pm");
1320
1321 while(argc-- > 0) {
1322 char *quoted;
1323
1324 quoted = dupAndQuote(*argv++);
1325
1326 strncat(buf, " ", sizeof(buf)-1);
1327 strncat(buf, quoted, sizeof(buf)-1);
1328 free(quoted);
1329 }
1330
1331 send_shellcommand(transport, serial, buf);
1332 return 0;
1333}
1334
1335int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1336{
1337 /* if the user choose the -k option, we refuse to do it until devices are
1338 out with the option to uninstall the remaining data somehow (adb/ui) */
1339 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1340 {
1341 printf(
1342 "The -k option uninstalls the application while retaining the data/cache.\n"
1343 "At the moment, there is no way to remove the remaining data.\n"
1344 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1345 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1346 return -1;
1347 }
1348
1349 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1350 return pm_command(transport, serial, argc, argv);
1351}
1352
1353static int delete_file(transport_type transport, char* serial, char* filename)
1354{
1355 char buf[4096];
1356 char* quoted;
1357
1358 snprintf(buf, sizeof(buf), "shell:rm ");
1359 quoted = dupAndQuote(filename);
1360 strncat(buf, quoted, sizeof(buf)-1);
1361 free(quoted);
1362
1363 send_shellcommand(transport, serial, buf);
1364 return 0;
1365}
1366
1367int install_app(transport_type transport, char* serial, int argc, char** argv)
1368{
1369 struct stat st;
1370 int err;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001371 const char *const DATA_DEST = "/data/local/tmp/%s";
1372 const char *const SD_DEST = "/sdcard/tmp/%s";
1373 const char* where = DATA_DEST;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001374 char to[PATH_MAX];
1375 char* filename = argv[argc - 1];
1376 const char* p;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001377 int i;
1378
1379 for (i = 0; i < argc; i++) {
1380 if (!strcmp(argv[i], "-s"))
1381 where = SD_DEST;
1382 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001383
1384 p = adb_dirstop(filename);
1385 if (p) {
1386 p++;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001387 snprintf(to, sizeof to, where, p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001388 } else {
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001389 snprintf(to, sizeof to, where, filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 }
1391 if (p[0] == '\0') {
1392 }
1393
1394 err = stat(filename, &st);
1395 if (err != 0) {
1396 fprintf(stderr, "can't find '%s' to install\n", filename);
1397 return 1;
1398 }
1399 if (!S_ISREG(st.st_mode)) {
1400 fprintf(stderr, "can't install '%s' because it's not a file\n",
1401 filename);
1402 return 1;
1403 }
1404
1405 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1406 /* file in place; tell the Package Manager to install it */
1407 argv[argc - 1] = to; /* destination name, not source location */
1408 pm_command(transport, serial, argc, argv);
1409 delete_file(transport, serial, to);
1410 }
1411
1412 return err;
1413}