blob: 5414e5eb53f58be545a7e44a16a35f94ae9e1cc8 [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
40#ifdef SH_HISTORY
41#include "shlist.h"
42#include "history.h"
43#endif
44
45enum {
46 IGNORE_DATA,
47 WIPE_DATA,
48 FLASH_DATA
49};
50
51static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
52
53void get_my_path(char s[PATH_MAX]);
54int find_sync_dirs(const char *srcarg,
55 char **android_srcdir_out, char **data_srcdir_out);
56int install_app(transport_type transport, char* serial, int argc, char** argv);
57int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
58
59static const char *gProductOutPath = NULL;
60
61static char *product_file(const char *extra)
62{
63 int n;
64 char *x;
65
66 if (gProductOutPath == NULL) {
67 fprintf(stderr, "adb: Product directory not specified; "
68 "use -p or define ANDROID_PRODUCT_OUT\n");
69 exit(1);
70 }
71
72 n = strlen(gProductOutPath) + strlen(extra) + 2;
73 x = malloc(n);
74 if (x == 0) {
75 fprintf(stderr, "adb: Out of memory (product_file())\n");
76 exit(1);
77 }
78
79 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
80 return x;
81}
82
83void version(FILE * out) {
84 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
85 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
86}
87
88void help()
89{
90 version(stderr);
91
92 fprintf(stderr,
93 "\n"
94 " -d - directs command to the only connected USB device\n"
95 " returns an error if more than one USB device is present.\n"
96 " -e - directs command to the only running emulator.\n"
97 " returns an error if more than one emulator is running.\n"
98 " -s <serial number> - directs command to the USB device or emulator with\n"
99 " the given serial number\n"
100 " -p <product name or path> - simple product name like 'sooner', or\n"
101 " a relative/absolute path to a product\n"
102 " out directory like 'out/target/product/sooner'.\n"
103 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
104 " environment variable is used, which must\n"
105 " be an absolute path.\n"
106 " devices - list all connected devices\n"
107 "\n"
108 "device commands:\n"
109 " adb push <local> <remote> - copy file/dir to device\n"
110 " adb pull <remote> <local> - copy file/dir from device\n"
111 " adb sync [ <directory> ] - copy host->device only if changed\n"
112 " (see 'adb help all')\n"
113 " adb shell - run remote shell interactively\n"
114 " adb shell <command> - run remote shell command\n"
115 " adb emu <command> - run emulator console command\n"
116 " adb logcat [ <filter-spec> ] - View device log\n"
117 " adb forward <local> <remote> - forward socket connections\n"
118 " forward specs are one of: \n"
119 " tcp:<port>\n"
120 " localabstract:<unix domain socket name>\n"
121 " localreserved:<unix domain socket name>\n"
122 " localfilesystem:<unix domain socket name>\n"
123 " dev:<character device name>\n"
124 " jdwp:<process pid> (remote only)\n"
125 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
126 " adb install [-l] [-r] <file> - push this package file to the device and install it\n"
127 " ('-l' means forward-lock the app)\n"
128 " ('-r' means reinstall the app, keeping its data)\n"
129 " adb uninstall [-k] <package> - remove this app package from the device\n"
130 " ('-k' means keep the data and cache directories)\n"
131 " adb bugreport - return all information from the device\n"
132 " that should be included in a bug report.\n"
133 "\n"
134 " adb help - show this help message\n"
135 " adb version - show version num\n"
136 "\n"
137 "DATAOPTS:\n"
138 " (no option) - don't touch the data partition\n"
139 " -w - wipe the data partition\n"
140 " -d - flash the data partition\n"
141 "\n"
142 "scripting:\n"
143 " adb wait-for-device - block until device is online\n"
144 " adb start-server - ensure that there is a server running\n"
145 " adb kill-server - kill the server if it is running\n"
146 " adb get-state - prints: offline | bootloader | device\n"
147 " adb get-serialno - prints: <serial-number>\n"
148 " adb status-window - continuously print device status for a specified device\n"
149 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood704aa832009-08-04 20:37:51 -0400150 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
The Android Open Source Projecte037fd72009-03-13 13:04:37 -0700151 " adb root - restarts adb with root permissions\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800152 "\n"
153 "networking:\n"
154 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500155 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
157 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
158 "\n"
159 "adb sync notes: adb sync [ <directory> ]\n"
160 " <localdir> can be interpreted in several ways:\n"
161 "\n"
162 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
163 "\n"
164 " - If it is \"system\" or \"data\", only the corresponding partition\n"
165 " is updated.\n"
166 );
167}
168
169int usage()
170{
171 help();
172 return 1;
173}
174
175#ifdef HAVE_TERMIO_H
176static struct termios tio_save;
177
178static void stdin_raw_init(int fd)
179{
180 struct termios tio;
181
182 if(tcgetattr(fd, &tio)) return;
183 if(tcgetattr(fd, &tio_save)) return;
184
185 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
186
187 /* no timeout but request at least one character per read */
188 tio.c_cc[VTIME] = 0;
189 tio.c_cc[VMIN] = 1;
190
191 tcsetattr(fd, TCSANOW, &tio);
192 tcflush(fd, TCIFLUSH);
193}
194
195static void stdin_raw_restore(int fd)
196{
197 tcsetattr(fd, TCSANOW, &tio_save);
198 tcflush(fd, TCIFLUSH);
199}
200#endif
201
202static void read_and_dump(int fd)
203{
204 char buf[4096];
205 int len;
206
207 while(fd >= 0) {
208 len = adb_read(fd, buf, 4096);
209 if(len == 0) {
210 break;
211 }
212
213 if(len < 0) {
214 if(errno == EINTR) continue;
215 break;
216 }
217 /* we want to output to stdout, so no adb_write here !! */
218 unix_write(1, buf, len);
219 }
220}
221
222#ifdef SH_HISTORY
223int shItemCmp( void *val, void *idata )
224{
225 return( (strcmp( val, idata ) == 0) );
226}
227#endif
228
229static void *stdin_read_thread(void *x)
230{
231 int fd, fdi;
232 unsigned char buf[1024];
233#ifdef SH_HISTORY
234 unsigned char realbuf[1024], *buf_ptr;
235 SHLIST history;
236 SHLIST *item = &history;
237 int cmdlen = 0, ins_flag = 0;
238#endif
239 int r, n;
240 int state = 0;
241
242 int *fds = (int*) x;
243 fd = fds[0];
244 fdi = fds[1];
245 free(fds);
246
247#ifdef SH_HISTORY
248 shListInitList( &history );
249#endif
250 for(;;) {
251 /* fdi is really the client's stdin, so use read, not adb_read here */
252 r = unix_read(fdi, buf, 1024);
253 if(r == 0) break;
254 if(r < 0) {
255 if(errno == EINTR) continue;
256 break;
257 }
258#ifdef SH_HISTORY
259 if( (r == 3) && /* Arrow processing */
260 (memcmp( (void *)buf, SH_ARROW_ANY, 2 ) == 0) ) {
261 switch( buf[2] ) {
262 case SH_ARROW_UP:
263 item = shListGetNextItem( &history, item );
264 break;
265 case SH_ARROW_DOWN:
266 item = shListGetPrevItem( &history, item );
267 break;
268 default:
269 item = NULL;
270 break;
271 }
272 memset( buf, SH_DEL_CHAR, cmdlen );
273 if( item != NULL ) {
274 n = snprintf( (char *)(&buf[cmdlen]), sizeof buf - cmdlen, "%s", (char *)(item->data) );
275 memcpy( realbuf, item->data, n );
276 }
277 else { /* Clean buffer */
278 item = &history;
279 n = 0;
280 }
281 r = n + cmdlen;
282 cmdlen = n;
283 ins_flag = 0;
284 if( r == 0 )
285 continue;
286 }
287 else {
288#endif
289 for(n = 0; n < r; n++){
290 switch(buf[n]) {
291 case '\n':
292#ifdef SH_HISTORY
293 if( ins_flag && (SH_BLANK_CHAR <= realbuf[0]) ) {
294 buf_ptr = malloc(cmdlen + 1);
295 if( buf_ptr != NULL ) {
296 memcpy( buf_ptr, realbuf, cmdlen );
297 buf_ptr[cmdlen] = '\0';
298 if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) {
299 shListInsFirstItem( &history, (void *)buf_ptr );
300 item = &history;
301 }
302 }
303 }
304 cmdlen = 0;
305 ins_flag = 0;
306#endif
307 state = 1;
308 break;
309 case '\r':
310 state = 1;
311 break;
312 case '~':
313 if(state == 1) state++;
314 break;
315 case '.':
316 if(state == 2) {
317 fprintf(stderr,"\n* disconnect *\n");
318 #ifdef HAVE_TERMIO_H
319 stdin_raw_restore(fdi);
320 #endif
321 exit(0);
322 }
323 default:
324#ifdef SH_HISTORY
325 if( buf[n] == SH_DEL_CHAR ) {
326 if( cmdlen > 0 )
327 cmdlen--;
328 }
329 else {
330 realbuf[cmdlen] = buf[n];
331 cmdlen++;
332 }
333 ins_flag = 1;
334#endif
335 state = 0;
336 }
337 }
338#ifdef SH_HISTORY
339 }
340#endif
341 r = adb_write(fd, buf, r);
342 if(r <= 0) {
343 break;
344 }
345 }
346#ifdef SH_HISTORY
347 shListDelAllItems( &history, (shListFree)free );
348#endif
349 return 0;
350}
351
352int interactive_shell(void)
353{
354 adb_thread_t thr;
355 int fdi, fd;
356 int *fds;
357
358 fd = adb_connect("shell:");
359 if(fd < 0) {
360 fprintf(stderr,"error: %s\n", adb_error());
361 return 1;
362 }
363 fdi = 0; //dup(0);
364
365 fds = malloc(sizeof(int) * 2);
366 fds[0] = fd;
367 fds[1] = fdi;
368
369#ifdef HAVE_TERMIO_H
370 stdin_raw_init(fdi);
371#endif
372 adb_thread_create(&thr, stdin_read_thread, fds);
373 read_and_dump(fd);
374#ifdef HAVE_TERMIO_H
375 stdin_raw_restore(fdi);
376#endif
377 return 0;
378}
379
380
381static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
382{
383 if (serial) {
384 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
385 } else {
386 const char* prefix = "host";
387 if (ttype == kTransportUsb)
388 prefix = "host-usb";
389 else if (ttype == kTransportLocal)
390 prefix = "host-local";
391
392 snprintf(buffer, buflen, "%s:%s", prefix, command);
393 }
394}
395
396static void status_window(transport_type ttype, const char* serial)
397{
398 char command[4096];
399 char *state = 0;
400 char *laststate = 0;
401
402 /* silence stderr */
403#ifdef _WIN32
404 /* XXX: TODO */
405#else
406 int fd;
407 fd = unix_open("/dev/null", O_WRONLY);
408 dup2(fd, 2);
409 adb_close(fd);
410#endif
411
412 format_host_command(command, sizeof command, "get-state", ttype, serial);
413
414 for(;;) {
415 adb_sleep_ms(250);
416
417 if(state) {
418 free(state);
419 state = 0;
420 }
421
422 state = adb_query(command);
423
424 if(state) {
425 if(laststate && !strcmp(state,laststate)){
426 continue;
427 } else {
428 if(laststate) free(laststate);
429 laststate = strdup(state);
430 }
431 }
432
433 printf("%c[2J%c[2H", 27, 27);
434 printf("Android Debug Bridge\n");
435 printf("State: %s\n", state ? state : "offline");
436 fflush(stdout);
437 }
438}
439
440/** duplicate string and quote all \ " ( ) chars + space character. */
441static char *
442dupAndQuote(const char *s)
443{
444 const char *ts;
445 size_t alloc_len;
446 char *ret;
447 char *dest;
448
449 ts = s;
450
451 alloc_len = 0;
452
453 for( ;*ts != '\0'; ts++) {
454 alloc_len++;
455 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
456 alloc_len++;
457 }
458 }
459
460 ret = (char *)malloc(alloc_len + 1);
461
462 ts = s;
463 dest = ret;
464
465 for ( ;*ts != '\0'; ts++) {
466 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
467 *dest++ = '\\';
468 }
469
470 *dest++ = *ts;
471 }
472
473 *dest++ = '\0';
474
475 return ret;
476}
477
478/**
479 * Run ppp in "notty" mode against a resource listed as the first parameter
480 * eg:
481 *
482 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
483 *
484 */
485int ppp(int argc, char **argv)
486{
487#ifdef HAVE_WIN32_PROC
488 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
489 return -1;
490#else
491 char *adb_service_name;
492 pid_t pid;
493 int fd;
494
495 if (argc < 2) {
496 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
497 argv[0]);
498
499 return 1;
500 }
501
502 adb_service_name = argv[1];
503
504 fd = adb_connect(adb_service_name);
505
506 if(fd < 0) {
507 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
508 adb_service_name, adb_error());
509 return 1;
510 }
511
512 pid = fork();
513
514 if (pid < 0) {
515 perror("from fork()");
516 return 1;
517 } else if (pid == 0) {
518 int err;
519 int i;
520 const char **ppp_args;
521
522 // copy args
523 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
524 ppp_args[0] = "pppd";
525 for (i = 2 ; i < argc ; i++) {
526 //argv[2] and beyond become ppp_args[1] and beyond
527 ppp_args[i - 1] = argv[i];
528 }
529 ppp_args[i-1] = NULL;
530
531 // child side
532
533 dup2(fd, STDIN_FILENO);
534 dup2(fd, STDOUT_FILENO);
535 adb_close(STDERR_FILENO);
536 adb_close(fd);
537
538 err = execvp("pppd", (char * const *)ppp_args);
539
540 if (err < 0) {
541 perror("execing pppd");
542 }
543 exit(-1);
544 } else {
545 // parent side
546
547 adb_close(fd);
548 return 0;
549 }
550#endif /* !HAVE_WIN32_PROC */
551}
552
553static int send_shellcommand(transport_type transport, char* serial, char* buf)
554{
555 int fd, ret;
556
557 for(;;) {
558 fd = adb_connect(buf);
559 if(fd >= 0)
560 break;
561 fprintf(stderr,"- waiting for device -\n");
562 adb_sleep_ms(1000);
563 do_cmd(transport, serial, "wait-for-device", 0);
564 }
565
566 read_and_dump(fd);
567 ret = adb_close(fd);
568 if (ret)
569 perror("close");
570
571 return ret;
572}
573
574static int logcat(transport_type transport, char* serial, int argc, char **argv)
575{
576 char buf[4096];
577
578 char *log_tags;
579 char *quoted_log_tags;
580
581 log_tags = getenv("ANDROID_LOG_TAGS");
582 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
583
584 snprintf(buf, sizeof(buf),
585 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
586 quoted_log_tags);
587
588 free(quoted_log_tags);
589
590 argc -= 1;
591 argv += 1;
592 while(argc-- > 0) {
593 char *quoted;
594
595 quoted = dupAndQuote (*argv++);
596
597 strncat(buf, " ", sizeof(buf)-1);
598 strncat(buf, quoted, sizeof(buf)-1);
599 free(quoted);
600 }
601
602 send_shellcommand(transport, serial, buf);
603 return 0;
604}
605
606#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
607static int top_works(const char *top)
608{
609 if (top != NULL && adb_is_absolute_host_path(top)) {
610 char path_buf[PATH_MAX];
611 snprintf(path_buf, sizeof(path_buf),
612 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
613 return access(path_buf, F_OK) == 0;
614 }
615 return 0;
616}
617
618static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
619{
620 strcpy(path_buf, indir);
621 while (1) {
622 if (top_works(path_buf)) {
623 return path_buf;
624 }
625 char *s = adb_dirstop(path_buf);
626 if (s != NULL) {
627 *s = '\0';
628 } else {
629 path_buf[0] = '\0';
630 return NULL;
631 }
632 }
633}
634
635static char *find_top(char path_buf[PATH_MAX])
636{
637 char *top = getenv("ANDROID_BUILD_TOP");
638 if (top != NULL && top[0] != '\0') {
639 if (!top_works(top)) {
640 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
641 return NULL;
642 }
643 } else {
644 top = getenv("TOP");
645 if (top != NULL && top[0] != '\0') {
646 if (!top_works(top)) {
647 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
648 return NULL;
649 }
650 } else {
651 top = NULL;
652 }
653 }
654
655 if (top != NULL) {
656 /* The environment pointed to a top directory that works.
657 */
658 strcpy(path_buf, top);
659 return path_buf;
660 }
661
662 /* The environment didn't help. Walk up the tree from the CWD
663 * to see if we can find the top.
664 */
665 char dir[PATH_MAX];
666 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
667 if (top == NULL) {
668 /* If the CWD isn't under a good-looking top, see if the
669 * executable is.
670 */
671 get_my_path(dir);
672 top = find_top_from(dir, path_buf);
673 }
674 return top;
675}
676
677/* <hint> may be:
678 * - A simple product name
679 * e.g., "sooner"
680TODO: debug? sooner-debug, sooner:debug?
681 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
682 * e.g., "out/target/product/sooner"
683 * - An absolute path to the PRODUCT_OUT dir
684 * e.g., "/src/device/out/target/product/sooner"
685 *
686 * Given <hint>, try to construct an absolute path to the
687 * ANDROID_PRODUCT_OUT dir.
688 */
689static const char *find_product_out_path(const char *hint)
690{
691 static char path_buf[PATH_MAX];
692
693 if (hint == NULL || hint[0] == '\0') {
694 return NULL;
695 }
696
697 /* If it's already absolute, don't bother doing any work.
698 */
699 if (adb_is_absolute_host_path(hint)) {
700 strcpy(path_buf, hint);
701 return path_buf;
702 }
703
704 /* If there are any slashes in it, assume it's a relative path;
705 * make it absolute.
706 */
707 if (adb_dirstart(hint) != NULL) {
708 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
709 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
710 return NULL;
711 }
712 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
713 fprintf(stderr, "adb: Couldn't assemble path\n");
714 return NULL;
715 }
716 strcat(path_buf, OS_PATH_SEPARATOR_STR);
717 strcat(path_buf, hint);
718 return path_buf;
719 }
720
721 /* It's a string without any slashes. Try to do something with it.
722 *
723 * Try to find the root of the build tree, and build a PRODUCT_OUT
724 * path from there.
725 */
726 char top_buf[PATH_MAX];
727 const char *top = find_top(top_buf);
728 if (top == NULL) {
729 fprintf(stderr, "adb: Couldn't find top of build tree\n");
730 return NULL;
731 }
732//TODO: if we have a way to indicate debug, look in out/debug/target/...
733 snprintf(path_buf, sizeof(path_buf),
734 "%s" OS_PATH_SEPARATOR_STR
735 "out" OS_PATH_SEPARATOR_STR
736 "target" OS_PATH_SEPARATOR_STR
737 "product" OS_PATH_SEPARATOR_STR
738 "%s", top_buf, hint);
739 if (access(path_buf, F_OK) < 0) {
740 fprintf(stderr, "adb: Couldn't find a product dir "
741 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
742 return NULL;
743 }
744 return path_buf;
745}
746
747int adb_commandline(int argc, char **argv)
748{
749 char buf[4096];
750 int no_daemon = 0;
751 int is_daemon = 0;
752 int persist = 0;
753 int r;
754 int quote;
755 transport_type ttype = kTransportAny;
756 char* serial = NULL;
757
758 /* If defined, this should be an absolute path to
759 * the directory containing all of the various system images
760 * for a particular product. If not defined, and the adb
761 * command requires this information, then the user must
762 * specify the path using "-p".
763 */
764 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
765 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
766 gProductOutPath = NULL;
767 }
768 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
769
770 /* modifiers and flags */
771 while(argc > 0) {
772 if(!strcmp(argv[0],"nodaemon")) {
773 no_daemon = 1;
774 } else if (!strcmp(argv[0], "fork-server")) {
775 /* this is a special flag used only when the ADB client launches the ADB Server */
776 is_daemon = 1;
777 } else if(!strcmp(argv[0],"persist")) {
778 persist = 1;
779 } else if(!strncmp(argv[0], "-p", 2)) {
780 const char *product = NULL;
781 if (argv[0][2] == '\0') {
782 if (argc < 2) return usage();
783 product = argv[1];
784 argc--;
785 argv++;
786 } else {
787 product = argv[1] + 2;
788 }
789 gProductOutPath = find_product_out_path(product);
790 if (gProductOutPath == NULL) {
791 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
792 product);
793 return usage();
794 }
795 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
796 if (isdigit(argv[0][2])) {
797 serial = argv[0] + 2;
798 } else {
799 if(argc < 2) return usage();
800 serial = argv[1];
801 argc--;
802 argv++;
803 }
804 } else if (!strcmp(argv[0],"-d")) {
805 ttype = kTransportUsb;
806 } else if (!strcmp(argv[0],"-e")) {
807 ttype = kTransportLocal;
808 } else {
809 /* out of recognized modifiers and flags */
810 break;
811 }
812 argc--;
813 argv++;
814 }
815
816 adb_set_transport(ttype, serial);
817
818 if ((argc > 0) && (!strcmp(argv[0],"server"))) {
819 if (no_daemon || is_daemon) {
820 r = adb_main(is_daemon);
821 } else {
822 r = launch_server();
823 }
824 if(r) {
825 fprintf(stderr,"* could not start server *\n");
826 }
827 return r;
828 }
829
830top:
831 if(argc == 0) {
832 return usage();
833 }
834
835 /* adb_connect() commands */
836
837 if(!strcmp(argv[0], "devices")) {
838 char *tmp;
839 snprintf(buf, sizeof buf, "host:%s", argv[0]);
840 tmp = adb_query(buf);
841 if(tmp) {
842 printf("List of devices attached \n");
843 printf("%s\n", tmp);
844 return 0;
845 } else {
846 return 1;
847 }
848 }
849
850 if (!strcmp(argv[0], "emu")) {
851 return adb_send_emulator_command(argc, argv);
852 }
853
854 if(!strcmp(argv[0], "shell")) {
855 int r;
856 int fd;
857
858 if(argc < 2) {
859 return interactive_shell();
860 }
861
862 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
863 argc -= 2;
864 argv += 2;
865 while(argc-- > 0) {
866 strcat(buf, " ");
867
868 /* quote empty strings and strings with spaces */
869 quote = (**argv == 0 || strchr(*argv, ' '));
870 if (quote)
871 strcat(buf, "\"");
872 strcat(buf, *argv++);
873 if (quote)
874 strcat(buf, "\"");
875 }
876
877 for(;;) {
878 fd = adb_connect(buf);
879 if(fd >= 0) {
880 read_and_dump(fd);
881 adb_close(fd);
882 r = 0;
883 } else {
884 fprintf(stderr,"error: %s\n", adb_error());
885 r = -1;
886 }
887
888 if(persist) {
889 fprintf(stderr,"\n- waiting for device -\n");
890 adb_sleep_ms(1000);
891 do_cmd(ttype, serial, "wait-for-device", 0);
892 } else {
893 return r;
894 }
895 }
896 }
897
898 if(!strcmp(argv[0], "kill-server")) {
899 int fd;
900 fd = _adb_connect("host:kill");
901 if(fd == -1) {
902 fprintf(stderr,"* server not running *\n");
903 return 1;
904 }
905 return 0;
906 }
907
908 if(!strcmp(argv[0], "remount")) {
909 int fd = adb_connect("remount:");
910 if(fd >= 0) {
911 read_and_dump(fd);
912 adb_close(fd);
913 return 0;
914 }
915 fprintf(stderr,"error: %s\n", adb_error());
916 return 1;
917 }
918
Mike Lockwood704aa832009-08-04 20:37:51 -0400919 if(!strcmp(argv[0], "reboot")) {
920 int fd;
921 if (argc > 1)
922 snprintf(buf, sizeof(buf), "reboot:%s", argv[1]);
923 else
924 snprintf(buf, sizeof(buf), "reboot:");
925 fd = adb_connect(buf);
926 if(fd >= 0) {
927 read_and_dump(fd);
928 adb_close(fd);
929 return 0;
930 }
931 fprintf(stderr,"error: %s\n", adb_error());
932 return 1;
933 }
934
The Android Open Source Projecte037fd72009-03-13 13:04:37 -0700935 if(!strcmp(argv[0], "root")) {
936 int fd = adb_connect("root:");
937 if(fd >= 0) {
938 read_and_dump(fd);
939 adb_close(fd);
940 return 0;
941 }
942 fprintf(stderr,"error: %s\n", adb_error());
943 return 1;
944 }
945
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800946 if(!strcmp(argv[0], "bugreport")) {
947 if (argc != 1) {
948 return 1;
949 }
950 do_cmd(ttype, serial, "shell", "dumpstate", "-", 0);
951 return 0;
952 }
953
954 /* adb_command() wrapper commands */
955
956 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
957 char* service = argv[0];
958 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
959 if (ttype == kTransportUsb) {
960 service = "wait-for-usb";
961 } else if (ttype == kTransportLocal) {
962 service = "wait-for-local";
963 } else {
964 service = "wait-for-any";
965 }
966 }
967
968 format_host_command(buf, sizeof buf, service, ttype, serial);
969
970 if (adb_command(buf)) {
971 D("failure: %s *\n",adb_error());
972 fprintf(stderr,"error: %s\n", adb_error());
973 return 1;
974 }
975
976 /* Allow a command to be run after wait-for-device,
977 * e.g. 'adb wait-for-device shell'.
978 */
979 if(argc > 1) {
980 argc--;
981 argv++;
982 goto top;
983 }
984 return 0;
985 }
986
987 if(!strcmp(argv[0], "forward")) {
988 if(argc != 3) return usage();
989 if (serial) {
990 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial,argv[1],argv[2]);
991 } else {
992 snprintf(buf, sizeof buf, "host:forward:%s;%s",argv[1],argv[2]);
993 }
994 if(adb_command(buf)) {
995 fprintf(stderr,"error: %s\n", adb_error());
996 return 1;
997 }
998 return 0;
999 }
1000
1001 /* do_sync_*() commands */
1002
1003 if(!strcmp(argv[0], "ls")) {
1004 if(argc != 2) return usage();
1005 return do_sync_ls(argv[1]);
1006 }
1007
1008 if(!strcmp(argv[0], "push")) {
1009 if(argc != 3) return usage();
1010 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1011 }
1012
1013 if(!strcmp(argv[0], "pull")) {
1014 if(argc != 3) return usage();
1015 return do_sync_pull(argv[1], argv[2]);
1016 }
1017
1018 if(!strcmp(argv[0], "install")) {
1019 if (argc < 2) return usage();
1020 return install_app(ttype, serial, argc, argv);
1021 }
1022
1023 if(!strcmp(argv[0], "uninstall")) {
1024 if (argc < 2) return usage();
1025 return uninstall_app(ttype, serial, argc, argv);
1026 }
1027
1028 if(!strcmp(argv[0], "sync")) {
1029 char *srcarg, *android_srcpath, *data_srcpath;
1030 int ret;
1031 if(argc < 2) {
1032 /* No local path was specified. */
1033 srcarg = NULL;
1034 } else if(argc == 2) {
1035 /* A local path or "android"/"data" arg was specified. */
1036 srcarg = argv[1];
1037 } else {
1038 return usage();
1039 }
1040 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1041 if(ret != 0) return usage();
1042
1043 if(android_srcpath != NULL)
1044 ret = do_sync_sync(android_srcpath, "/system");
1045 if(ret == 0 && data_srcpath != NULL)
1046 ret = do_sync_sync(data_srcpath, "/data");
1047
1048 free(android_srcpath);
1049 free(data_srcpath);
1050 return ret;
1051 }
1052
1053 /* passthrough commands */
1054
1055 if(!strcmp(argv[0],"get-state") ||
1056 !strcmp(argv[0],"get-serialno"))
1057 {
1058 char *tmp;
1059
1060 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1061 tmp = adb_query(buf);
1062 if(tmp) {
1063 printf("%s\n", tmp);
1064 return 0;
1065 } else {
1066 return 1;
1067 }
1068 }
1069
1070 /* other commands */
1071
1072 if(!strcmp(argv[0],"status-window")) {
1073 status_window(ttype, serial);
1074 return 0;
1075 }
1076
1077 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1078 return logcat(ttype, serial, argc, argv);
1079 }
1080
1081 if(!strcmp(argv[0],"ppp")) {
1082 return ppp(argc, argv);
1083 }
1084
1085 if (!strcmp(argv[0], "start-server")) {
1086 return adb_connect("host:start-server");
1087 }
1088
1089 if (!strcmp(argv[0], "jdwp")) {
1090 int fd = adb_connect("jdwp");
1091 if (fd >= 0) {
1092 read_and_dump(fd);
1093 adb_close(fd);
1094 return 0;
1095 } else {
1096 fprintf(stderr, "error: %s\n", adb_error());
1097 return -1;
1098 }
1099 }
1100
1101 /* "adb /?" is a common idiom under Windows */
1102 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1103 help();
1104 return 0;
1105 }
1106
1107 if(!strcmp(argv[0], "version")) {
1108 version(stdout);
1109 return 0;
1110 }
1111
1112 usage();
1113 return 1;
1114}
1115
1116static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1117{
1118 char *argv[16];
1119 int argc;
1120 va_list ap;
1121
1122 va_start(ap, cmd);
1123 argc = 0;
1124
1125 if (serial) {
1126 argv[argc++] = "-s";
1127 argv[argc++] = serial;
1128 } else if (ttype == kTransportUsb) {
1129 argv[argc++] = "-d";
1130 } else if (ttype == kTransportLocal) {
1131 argv[argc++] = "-e";
1132 }
1133
1134 argv[argc++] = cmd;
1135 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1136 va_end(ap);
1137
1138#if 0
1139 int n;
1140 fprintf(stderr,"argc = %d\n",argc);
1141 for(n = 0; n < argc; n++) {
1142 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1143 }
1144#endif
1145
1146 return adb_commandline(argc, argv);
1147}
1148
1149int find_sync_dirs(const char *srcarg,
1150 char **android_srcdir_out, char **data_srcdir_out)
1151{
1152 char *android_srcdir, *data_srcdir;
1153
1154 if(srcarg == NULL) {
1155 android_srcdir = product_file("system");
1156 data_srcdir = product_file("data");
1157 } else {
1158 /* srcarg may be "data", "system" or NULL.
1159 * if srcarg is NULL, then both data and system are synced
1160 */
1161 if(strcmp(srcarg, "system") == 0) {
1162 android_srcdir = product_file("system");
1163 data_srcdir = NULL;
1164 } else if(strcmp(srcarg, "data") == 0) {
1165 android_srcdir = NULL;
1166 data_srcdir = product_file("data");
1167 } else {
1168 /* It's not "system" or "data".
1169 */
1170 return 1;
1171 }
1172 }
1173
1174 if(android_srcdir_out != NULL)
1175 *android_srcdir_out = android_srcdir;
1176 else
1177 free(android_srcdir);
1178
1179 if(data_srcdir_out != NULL)
1180 *data_srcdir_out = data_srcdir;
1181 else
1182 free(data_srcdir);
1183
1184 return 0;
1185}
1186
1187static int pm_command(transport_type transport, char* serial,
1188 int argc, char** argv)
1189{
1190 char buf[4096];
1191
1192 snprintf(buf, sizeof(buf), "shell:pm");
1193
1194 while(argc-- > 0) {
1195 char *quoted;
1196
1197 quoted = dupAndQuote(*argv++);
1198
1199 strncat(buf, " ", sizeof(buf)-1);
1200 strncat(buf, quoted, sizeof(buf)-1);
1201 free(quoted);
1202 }
1203
1204 send_shellcommand(transport, serial, buf);
1205 return 0;
1206}
1207
1208int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1209{
1210 /* if the user choose the -k option, we refuse to do it until devices are
1211 out with the option to uninstall the remaining data somehow (adb/ui) */
1212 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1213 {
1214 printf(
1215 "The -k option uninstalls the application while retaining the data/cache.\n"
1216 "At the moment, there is no way to remove the remaining data.\n"
1217 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1218 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1219 return -1;
1220 }
1221
1222 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1223 return pm_command(transport, serial, argc, argv);
1224}
1225
1226static int delete_file(transport_type transport, char* serial, char* filename)
1227{
1228 char buf[4096];
1229 char* quoted;
1230
1231 snprintf(buf, sizeof(buf), "shell:rm ");
1232 quoted = dupAndQuote(filename);
1233 strncat(buf, quoted, sizeof(buf)-1);
1234 free(quoted);
1235
1236 send_shellcommand(transport, serial, buf);
1237 return 0;
1238}
1239
1240int install_app(transport_type transport, char* serial, int argc, char** argv)
1241{
1242 struct stat st;
1243 int err;
1244 const char *const WHERE = "/data/local/tmp/%s";
1245 char to[PATH_MAX];
1246 char* filename = argv[argc - 1];
1247 const char* p;
1248
1249 p = adb_dirstop(filename);
1250 if (p) {
1251 p++;
1252 snprintf(to, sizeof to, WHERE, p);
1253 } else {
1254 snprintf(to, sizeof to, WHERE, filename);
1255 }
1256 if (p[0] == '\0') {
1257 }
1258
1259 err = stat(filename, &st);
1260 if (err != 0) {
1261 fprintf(stderr, "can't find '%s' to install\n", filename);
1262 return 1;
1263 }
1264 if (!S_ISREG(st.st_mode)) {
1265 fprintf(stderr, "can't install '%s' because it's not a file\n",
1266 filename);
1267 return 1;
1268 }
1269
1270 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1271 /* file in place; tell the Package Manager to install it */
1272 argv[argc - 1] = to; /* destination name, not source location */
1273 pm_command(transport, serial, argc, argv);
1274 delete_file(transport, serial, to);
1275 }
1276
1277 return err;
1278}