blob: ad1021ca36808ad4d5a66bfa2bffc9fbc3fc8ed5 [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"
Nick Pelly22048ef2009-05-07 12:48:03 -070099 " the given serial number. Overrides ANDROID_SERIAL\n"
100 " envivornment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800101 " -p <product name or path> - simple product name like 'sooner', or\n"
102 " a relative/absolute path to a product\n"
103 " out directory like 'out/target/product/sooner'.\n"
104 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
105 " environment variable is used, which must\n"
106 " be an absolute path.\n"
107 " devices - list all connected devices\n"
108 "\n"
109 "device commands:\n"
110 " adb push <local> <remote> - copy file/dir to device\n"
111 " adb pull <remote> <local> - copy file/dir from device\n"
112 " adb sync [ <directory> ] - copy host->device only if changed\n"
113 " (see 'adb help all')\n"
114 " adb shell - run remote shell interactively\n"
115 " adb shell <command> - run remote shell command\n"
116 " adb emu <command> - run emulator console command\n"
117 " adb logcat [ <filter-spec> ] - View device log\n"
118 " adb forward <local> <remote> - forward socket connections\n"
119 " forward specs are one of: \n"
120 " tcp:<port>\n"
121 " localabstract:<unix domain socket name>\n"
122 " localreserved:<unix domain socket name>\n"
123 " localfilesystem:<unix domain socket name>\n"
124 " dev:<character device name>\n"
125 " jdwp:<process pid> (remote only)\n"
126 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
127 " adb install [-l] [-r] <file> - push this package file to the device and install it\n"
128 " ('-l' means forward-lock the app)\n"
129 " ('-r' means reinstall the app, keeping its data)\n"
130 " adb uninstall [-k] <package> - remove this app package from the device\n"
131 " ('-k' means keep the data and cache directories)\n"
132 " adb bugreport - return all information from the device\n"
133 " that should be included in a bug report.\n"
134 "\n"
135 " adb help - show this help message\n"
136 " adb version - show version num\n"
137 "\n"
138 "DATAOPTS:\n"
139 " (no option) - don't touch the data partition\n"
140 " -w - wipe the data partition\n"
141 " -d - flash the data partition\n"
142 "\n"
143 "scripting:\n"
144 " adb wait-for-device - block until device is online\n"
145 " adb start-server - ensure that there is a server running\n"
146 " adb kill-server - kill the server if it is running\n"
147 " adb get-state - prints: offline | bootloader | device\n"
148 " adb get-serialno - prints: <serial-number>\n"
149 " adb status-window - continuously print device status for a specified device\n"
150 " adb remount - remounts the /system partition on the device read-write\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 Root417a3232009-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
Nick Pelly22048ef2009-05-07 12:48:03 -0700770 serial = getenv("ANDROID_SERIAL");
771
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800772 /* modifiers and flags */
773 while(argc > 0) {
774 if(!strcmp(argv[0],"nodaemon")) {
775 no_daemon = 1;
776 } else if (!strcmp(argv[0], "fork-server")) {
777 /* this is a special flag used only when the ADB client launches the ADB Server */
778 is_daemon = 1;
779 } else if(!strcmp(argv[0],"persist")) {
780 persist = 1;
781 } else if(!strncmp(argv[0], "-p", 2)) {
782 const char *product = NULL;
783 if (argv[0][2] == '\0') {
784 if (argc < 2) return usage();
785 product = argv[1];
786 argc--;
787 argv++;
788 } else {
789 product = argv[1] + 2;
790 }
791 gProductOutPath = find_product_out_path(product);
792 if (gProductOutPath == NULL) {
793 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
794 product);
795 return usage();
796 }
797 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
798 if (isdigit(argv[0][2])) {
799 serial = argv[0] + 2;
800 } else {
801 if(argc < 2) return usage();
802 serial = argv[1];
803 argc--;
804 argv++;
805 }
806 } else if (!strcmp(argv[0],"-d")) {
807 ttype = kTransportUsb;
808 } else if (!strcmp(argv[0],"-e")) {
809 ttype = kTransportLocal;
810 } else {
811 /* out of recognized modifiers and flags */
812 break;
813 }
814 argc--;
815 argv++;
816 }
817
818 adb_set_transport(ttype, serial);
819
820 if ((argc > 0) && (!strcmp(argv[0],"server"))) {
821 if (no_daemon || is_daemon) {
822 r = adb_main(is_daemon);
823 } else {
824 r = launch_server();
825 }
826 if(r) {
827 fprintf(stderr,"* could not start server *\n");
828 }
829 return r;
830 }
831
832top:
833 if(argc == 0) {
834 return usage();
835 }
836
837 /* adb_connect() commands */
838
839 if(!strcmp(argv[0], "devices")) {
840 char *tmp;
841 snprintf(buf, sizeof buf, "host:%s", argv[0]);
842 tmp = adb_query(buf);
843 if(tmp) {
844 printf("List of devices attached \n");
845 printf("%s\n", tmp);
846 return 0;
847 } else {
848 return 1;
849 }
850 }
851
852 if (!strcmp(argv[0], "emu")) {
853 return adb_send_emulator_command(argc, argv);
854 }
855
856 if(!strcmp(argv[0], "shell")) {
857 int r;
858 int fd;
859
860 if(argc < 2) {
861 return interactive_shell();
862 }
863
864 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
865 argc -= 2;
866 argv += 2;
867 while(argc-- > 0) {
868 strcat(buf, " ");
869
870 /* quote empty strings and strings with spaces */
871 quote = (**argv == 0 || strchr(*argv, ' '));
872 if (quote)
873 strcat(buf, "\"");
874 strcat(buf, *argv++);
875 if (quote)
876 strcat(buf, "\"");
877 }
878
879 for(;;) {
880 fd = adb_connect(buf);
881 if(fd >= 0) {
882 read_and_dump(fd);
883 adb_close(fd);
884 r = 0;
885 } else {
886 fprintf(stderr,"error: %s\n", adb_error());
887 r = -1;
888 }
889
890 if(persist) {
891 fprintf(stderr,"\n- waiting for device -\n");
892 adb_sleep_ms(1000);
893 do_cmd(ttype, serial, "wait-for-device", 0);
894 } else {
895 return r;
896 }
897 }
898 }
899
900 if(!strcmp(argv[0], "kill-server")) {
901 int fd;
902 fd = _adb_connect("host:kill");
903 if(fd == -1) {
904 fprintf(stderr,"* server not running *\n");
905 return 1;
906 }
907 return 0;
908 }
909
910 if(!strcmp(argv[0], "remount")) {
911 int fd = adb_connect("remount:");
912 if(fd >= 0) {
913 read_and_dump(fd);
914 adb_close(fd);
915 return 0;
916 }
917 fprintf(stderr,"error: %s\n", adb_error());
918 return 1;
919 }
920
The Android Open Source Projecte037fd72009-03-13 13:04:37 -0700921 if(!strcmp(argv[0], "root")) {
922 int fd = adb_connect("root:");
923 if(fd >= 0) {
924 read_and_dump(fd);
925 adb_close(fd);
926 return 0;
927 }
928 fprintf(stderr,"error: %s\n", adb_error());
929 return 1;
930 }
931
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800932 if(!strcmp(argv[0], "bugreport")) {
933 if (argc != 1) {
934 return 1;
935 }
936 do_cmd(ttype, serial, "shell", "dumpstate", "-", 0);
937 return 0;
938 }
939
940 /* adb_command() wrapper commands */
941
942 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
943 char* service = argv[0];
944 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
945 if (ttype == kTransportUsb) {
946 service = "wait-for-usb";
947 } else if (ttype == kTransportLocal) {
948 service = "wait-for-local";
949 } else {
950 service = "wait-for-any";
951 }
952 }
953
954 format_host_command(buf, sizeof buf, service, ttype, serial);
955
956 if (adb_command(buf)) {
957 D("failure: %s *\n",adb_error());
958 fprintf(stderr,"error: %s\n", adb_error());
959 return 1;
960 }
961
962 /* Allow a command to be run after wait-for-device,
963 * e.g. 'adb wait-for-device shell'.
964 */
965 if(argc > 1) {
966 argc--;
967 argv++;
968 goto top;
969 }
970 return 0;
971 }
972
973 if(!strcmp(argv[0], "forward")) {
974 if(argc != 3) return usage();
975 if (serial) {
976 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial,argv[1],argv[2]);
977 } else {
978 snprintf(buf, sizeof buf, "host:forward:%s;%s",argv[1],argv[2]);
979 }
980 if(adb_command(buf)) {
981 fprintf(stderr,"error: %s\n", adb_error());
982 return 1;
983 }
984 return 0;
985 }
986
987 /* do_sync_*() commands */
988
989 if(!strcmp(argv[0], "ls")) {
990 if(argc != 2) return usage();
991 return do_sync_ls(argv[1]);
992 }
993
994 if(!strcmp(argv[0], "push")) {
995 if(argc != 3) return usage();
996 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
997 }
998
999 if(!strcmp(argv[0], "pull")) {
1000 if(argc != 3) return usage();
1001 return do_sync_pull(argv[1], argv[2]);
1002 }
1003
1004 if(!strcmp(argv[0], "install")) {
1005 if (argc < 2) return usage();
1006 return install_app(ttype, serial, argc, argv);
1007 }
1008
1009 if(!strcmp(argv[0], "uninstall")) {
1010 if (argc < 2) return usage();
1011 return uninstall_app(ttype, serial, argc, argv);
1012 }
1013
1014 if(!strcmp(argv[0], "sync")) {
1015 char *srcarg, *android_srcpath, *data_srcpath;
1016 int ret;
1017 if(argc < 2) {
1018 /* No local path was specified. */
1019 srcarg = NULL;
1020 } else if(argc == 2) {
1021 /* A local path or "android"/"data" arg was specified. */
1022 srcarg = argv[1];
1023 } else {
1024 return usage();
1025 }
1026 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1027 if(ret != 0) return usage();
1028
1029 if(android_srcpath != NULL)
1030 ret = do_sync_sync(android_srcpath, "/system");
1031 if(ret == 0 && data_srcpath != NULL)
1032 ret = do_sync_sync(data_srcpath, "/data");
1033
1034 free(android_srcpath);
1035 free(data_srcpath);
1036 return ret;
1037 }
1038
1039 /* passthrough commands */
1040
1041 if(!strcmp(argv[0],"get-state") ||
1042 !strcmp(argv[0],"get-serialno"))
1043 {
1044 char *tmp;
1045
1046 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1047 tmp = adb_query(buf);
1048 if(tmp) {
1049 printf("%s\n", tmp);
1050 return 0;
1051 } else {
1052 return 1;
1053 }
1054 }
1055
1056 /* other commands */
1057
1058 if(!strcmp(argv[0],"status-window")) {
1059 status_window(ttype, serial);
1060 return 0;
1061 }
1062
1063 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1064 return logcat(ttype, serial, argc, argv);
1065 }
1066
1067 if(!strcmp(argv[0],"ppp")) {
1068 return ppp(argc, argv);
1069 }
1070
1071 if (!strcmp(argv[0], "start-server")) {
1072 return adb_connect("host:start-server");
1073 }
1074
1075 if (!strcmp(argv[0], "jdwp")) {
1076 int fd = adb_connect("jdwp");
1077 if (fd >= 0) {
1078 read_and_dump(fd);
1079 adb_close(fd);
1080 return 0;
1081 } else {
1082 fprintf(stderr, "error: %s\n", adb_error());
1083 return -1;
1084 }
1085 }
1086
1087 /* "adb /?" is a common idiom under Windows */
1088 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1089 help();
1090 return 0;
1091 }
1092
1093 if(!strcmp(argv[0], "version")) {
1094 version(stdout);
1095 return 0;
1096 }
1097
1098 usage();
1099 return 1;
1100}
1101
1102static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1103{
1104 char *argv[16];
1105 int argc;
1106 va_list ap;
1107
1108 va_start(ap, cmd);
1109 argc = 0;
1110
1111 if (serial) {
1112 argv[argc++] = "-s";
1113 argv[argc++] = serial;
1114 } else if (ttype == kTransportUsb) {
1115 argv[argc++] = "-d";
1116 } else if (ttype == kTransportLocal) {
1117 argv[argc++] = "-e";
1118 }
1119
1120 argv[argc++] = cmd;
1121 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1122 va_end(ap);
1123
1124#if 0
1125 int n;
1126 fprintf(stderr,"argc = %d\n",argc);
1127 for(n = 0; n < argc; n++) {
1128 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1129 }
1130#endif
1131
1132 return adb_commandline(argc, argv);
1133}
1134
1135int find_sync_dirs(const char *srcarg,
1136 char **android_srcdir_out, char **data_srcdir_out)
1137{
1138 char *android_srcdir, *data_srcdir;
1139
1140 if(srcarg == NULL) {
1141 android_srcdir = product_file("system");
1142 data_srcdir = product_file("data");
1143 } else {
1144 /* srcarg may be "data", "system" or NULL.
1145 * if srcarg is NULL, then both data and system are synced
1146 */
1147 if(strcmp(srcarg, "system") == 0) {
1148 android_srcdir = product_file("system");
1149 data_srcdir = NULL;
1150 } else if(strcmp(srcarg, "data") == 0) {
1151 android_srcdir = NULL;
1152 data_srcdir = product_file("data");
1153 } else {
1154 /* It's not "system" or "data".
1155 */
1156 return 1;
1157 }
1158 }
1159
1160 if(android_srcdir_out != NULL)
1161 *android_srcdir_out = android_srcdir;
1162 else
1163 free(android_srcdir);
1164
1165 if(data_srcdir_out != NULL)
1166 *data_srcdir_out = data_srcdir;
1167 else
1168 free(data_srcdir);
1169
1170 return 0;
1171}
1172
1173static int pm_command(transport_type transport, char* serial,
1174 int argc, char** argv)
1175{
1176 char buf[4096];
1177
1178 snprintf(buf, sizeof(buf), "shell:pm");
1179
1180 while(argc-- > 0) {
1181 char *quoted;
1182
1183 quoted = dupAndQuote(*argv++);
1184
1185 strncat(buf, " ", sizeof(buf)-1);
1186 strncat(buf, quoted, sizeof(buf)-1);
1187 free(quoted);
1188 }
1189
1190 send_shellcommand(transport, serial, buf);
1191 return 0;
1192}
1193
1194int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1195{
1196 /* if the user choose the -k option, we refuse to do it until devices are
1197 out with the option to uninstall the remaining data somehow (adb/ui) */
1198 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1199 {
1200 printf(
1201 "The -k option uninstalls the application while retaining the data/cache.\n"
1202 "At the moment, there is no way to remove the remaining data.\n"
1203 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1204 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1205 return -1;
1206 }
1207
1208 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1209 return pm_command(transport, serial, argc, argv);
1210}
1211
1212static int delete_file(transport_type transport, char* serial, char* filename)
1213{
1214 char buf[4096];
1215 char* quoted;
1216
1217 snprintf(buf, sizeof(buf), "shell:rm ");
1218 quoted = dupAndQuote(filename);
1219 strncat(buf, quoted, sizeof(buf)-1);
1220 free(quoted);
1221
1222 send_shellcommand(transport, serial, buf);
1223 return 0;
1224}
1225
1226int install_app(transport_type transport, char* serial, int argc, char** argv)
1227{
1228 struct stat st;
1229 int err;
1230 const char *const WHERE = "/data/local/tmp/%s";
1231 char to[PATH_MAX];
1232 char* filename = argv[argc - 1];
1233 const char* p;
1234
1235 p = adb_dirstop(filename);
1236 if (p) {
1237 p++;
1238 snprintf(to, sizeof to, WHERE, p);
1239 } else {
1240 snprintf(to, sizeof to, WHERE, filename);
1241 }
1242 if (p[0] == '\0') {
1243 }
1244
1245 err = stat(filename, &st);
1246 if (err != 0) {
1247 fprintf(stderr, "can't find '%s' to install\n", filename);
1248 return 1;
1249 }
1250 if (!S_ISREG(st.st_mode)) {
1251 fprintf(stderr, "can't install '%s' because it's not a file\n",
1252 filename);
1253 return 1;
1254 }
1255
1256 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1257 /* file in place; tell the Package Manager to install it */
1258 argv[argc - 1] = to; /* destination name, not source location */
1259 pm_command(transport, serial, argc, argv);
1260 delete_file(transport, serial, to);
1261 }
1262
1263 return err;
1264}