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