blob: 9f4ae97b154079bb7ff7f55fe3bdf03d62a589af [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov857f17a2009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
44 char **android_srcdir_out, char **data_srcdir_out);
45int install_app(transport_type transport, char* serial, int argc, char** argv);
46int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47
48static const char *gProductOutPath = NULL;
49
50static char *product_file(const char *extra)
51{
52 int n;
53 char *x;
54
55 if (gProductOutPath == NULL) {
56 fprintf(stderr, "adb: Product directory not specified; "
57 "use -p or define ANDROID_PRODUCT_OUT\n");
58 exit(1);
59 }
60
61 n = strlen(gProductOutPath) + strlen(extra) + 2;
62 x = malloc(n);
63 if (x == 0) {
64 fprintf(stderr, "adb: Out of memory (product_file())\n");
65 exit(1);
66 }
67
68 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
69 return x;
70}
71
72void version(FILE * out) {
73 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
74 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
75}
76
77void help()
78{
79 version(stderr);
80
81 fprintf(stderr,
82 "\n"
83 " -d - directs command to the only connected USB device\n"
84 " returns an error if more than one USB device is present.\n"
85 " -e - directs command to the only running emulator.\n"
86 " returns an error if more than one emulator is running.\n"
87 " -s <serial number> - directs command to the USB device or emulator with\n"
Nick Pellyaf2fe9b2009-05-07 12:48:03 -070088 " the given serial number. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080090 " -p <product name or path> - simple product name like 'sooner', or\n"
91 " a relative/absolute path to a product\n"
92 " out directory like 'out/target/product/sooner'.\n"
93 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94 " environment variable is used, which must\n"
95 " be an absolute path.\n"
96 " devices - list all connected devices\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -040097 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
98 " Port 5555 is used by default if no port number is specified.\n"
99 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
100 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischerc3e82b82011-04-26 12:46:05 +0200101 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400102 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800103 "\n"
104 "device commands:\n"
105 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato23595b02010-01-05 13:42:25 -0800106 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800107 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600108 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800109 " (see 'adb help all')\n"
110 " adb shell - run remote shell interactively\n"
111 " adb shell <command> - run remote shell command\n"
112 " adb emu <command> - run emulator console command\n"
113 " adb logcat [ <filter-spec> ] - View device log\n"
114 " adb forward <local> <remote> - forward socket connections\n"
115 " forward specs are one of: \n"
116 " tcp:<port>\n"
117 " localabstract:<unix domain socket name>\n"
118 " localreserved:<unix domain socket name>\n"
119 " localfilesystem:<unix domain socket name>\n"
120 " dev:<character device name>\n"
121 " jdwp:<process pid> (remote only)\n"
122 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500123 " adb install [-l] [-r] [-s] <file> - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800124 " ('-l' means forward-lock the app)\n"
125 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500126 " ('-s' means install on SD card instead of internal storage)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800127 " adb uninstall [-k] <package> - remove this app package from the device\n"
128 " ('-k' means keep the data and cache directories)\n"
129 " adb bugreport - return all information from the device\n"
130 " that should be included in a bug report.\n"
131 "\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700132 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
133 " - write an archive of the device's data to <file>.\n"
134 " If no -f option is supplied then the data is written\n"
135 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700136 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700137 " in the archive; the default is noapk.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700138 " (-shared|-noshared enable/disable backup of the device's\n"
139 " shared storage / SD card contents; the default is noshared.)\n"
140 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700141 " (-system|-nosystem toggles whether -all automatically includes\n"
142 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700143 " (<packages...> is the list of applications to be backed up. If\n"
144 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700145 " list is optional. Applications explicitly given on the\n"
146 " command line will be included even if -nosystem would\n"
147 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700148 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700149 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700150 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800151 " adb help - show this help message\n"
152 " adb version - show version num\n"
153 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800154 "scripting:\n"
155 " adb wait-for-device - block until device is online\n"
156 " adb start-server - ensure that there is a server running\n"
157 " adb kill-server - kill the server if it is running\n"
158 " adb get-state - prints: offline | bootloader | device\n"
159 " adb get-serialno - prints: <serial-number>\n"
160 " adb status-window - continuously print device status for a specified device\n"
161 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400162 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800163 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700164 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800165 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700166 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800167 "\n"
168 "networking:\n"
169 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500170 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800171 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
172 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
173 "\n"
174 "adb sync notes: adb sync [ <directory> ]\n"
175 " <localdir> can be interpreted in several ways:\n"
176 "\n"
177 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
178 "\n"
179 " - If it is \"system\" or \"data\", only the corresponding partition\n"
180 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000181 "\n"
182 "environmental variables:\n"
183 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
184 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
185 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
186 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800187 );
188}
189
190int usage()
191{
192 help();
193 return 1;
194}
195
196#ifdef HAVE_TERMIO_H
197static struct termios tio_save;
198
199static void stdin_raw_init(int fd)
200{
201 struct termios tio;
202
203 if(tcgetattr(fd, &tio)) return;
204 if(tcgetattr(fd, &tio_save)) return;
205
206 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
207
208 /* no timeout but request at least one character per read */
209 tio.c_cc[VTIME] = 0;
210 tio.c_cc[VMIN] = 1;
211
212 tcsetattr(fd, TCSANOW, &tio);
213 tcflush(fd, TCIFLUSH);
214}
215
216static void stdin_raw_restore(int fd)
217{
218 tcsetattr(fd, TCSANOW, &tio_save);
219 tcflush(fd, TCIFLUSH);
220}
221#endif
222
223static void read_and_dump(int fd)
224{
225 char buf[4096];
226 int len;
227
228 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700229 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800230 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700231 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800232 if(len == 0) {
233 break;
234 }
235
236 if(len < 0) {
237 if(errno == EINTR) continue;
238 break;
239 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400240 fwrite(buf, 1, len, stdout);
241 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800242 }
243}
244
Christopher Tate73779122011-04-21 12:53:28 -0700245static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700246 const size_t BUFSIZE = 32 * 1024;
247 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700248 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700249 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700250
251 D("copy_to_file(%d -> %d)\n", inFd, outFd);
252 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700253 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700254 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700255 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700256 break;
257 }
258 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700259 if (errno == EINTR) {
260 D("copy_to_file() : EINTR, retrying\n");
261 continue;
262 }
Christopher Tate73779122011-04-21 12:53:28 -0700263 D("copy_to_file() : error %d\n", errno);
264 break;
265 }
266 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700267 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700268 }
Christopher Tatefba22972011-06-01 17:56:23 -0700269 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700270 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700271}
272
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800273static void *stdin_read_thread(void *x)
274{
275 int fd, fdi;
276 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800277 int r, n;
278 int state = 0;
279
280 int *fds = (int*) x;
281 fd = fds[0];
282 fdi = fds[1];
283 free(fds);
284
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800285 for(;;) {
286 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700287 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800288 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700289 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800290 if(r == 0) break;
291 if(r < 0) {
292 if(errno == EINTR) continue;
293 break;
294 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400295 for(n = 0; n < r; n++){
296 switch(buf[n]) {
297 case '\n':
298 state = 1;
299 break;
300 case '\r':
301 state = 1;
302 break;
303 case '~':
304 if(state == 1) state++;
305 break;
306 case '.':
307 if(state == 2) {
308 fprintf(stderr,"\n* disconnect *\n");
309#ifdef HAVE_TERMIO_H
310 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800311#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400312 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400314 default:
315 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800316 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800317 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800318 r = adb_write(fd, buf, r);
319 if(r <= 0) {
320 break;
321 }
322 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800323 return 0;
324}
325
326int interactive_shell(void)
327{
328 adb_thread_t thr;
329 int fdi, fd;
330 int *fds;
331
332 fd = adb_connect("shell:");
333 if(fd < 0) {
334 fprintf(stderr,"error: %s\n", adb_error());
335 return 1;
336 }
337 fdi = 0; //dup(0);
338
339 fds = malloc(sizeof(int) * 2);
340 fds[0] = fd;
341 fds[1] = fdi;
342
343#ifdef HAVE_TERMIO_H
344 stdin_raw_init(fdi);
345#endif
346 adb_thread_create(&thr, stdin_read_thread, fds);
347 read_and_dump(fd);
348#ifdef HAVE_TERMIO_H
349 stdin_raw_restore(fdi);
350#endif
351 return 0;
352}
353
354
355static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
356{
357 if (serial) {
358 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
359 } else {
360 const char* prefix = "host";
361 if (ttype == kTransportUsb)
362 prefix = "host-usb";
363 else if (ttype == kTransportLocal)
364 prefix = "host-local";
365
366 snprintf(buffer, buflen, "%s:%s", prefix, command);
367 }
368}
369
370static void status_window(transport_type ttype, const char* serial)
371{
372 char command[4096];
373 char *state = 0;
374 char *laststate = 0;
375
376 /* silence stderr */
377#ifdef _WIN32
378 /* XXX: TODO */
379#else
380 int fd;
381 fd = unix_open("/dev/null", O_WRONLY);
382 dup2(fd, 2);
383 adb_close(fd);
384#endif
385
386 format_host_command(command, sizeof command, "get-state", ttype, serial);
387
388 for(;;) {
389 adb_sleep_ms(250);
390
391 if(state) {
392 free(state);
393 state = 0;
394 }
395
396 state = adb_query(command);
397
398 if(state) {
399 if(laststate && !strcmp(state,laststate)){
400 continue;
401 } else {
402 if(laststate) free(laststate);
403 laststate = strdup(state);
404 }
405 }
406
407 printf("%c[2J%c[2H", 27, 27);
408 printf("Android Debug Bridge\n");
409 printf("State: %s\n", state ? state : "offline");
410 fflush(stdout);
411 }
412}
413
414/** duplicate string and quote all \ " ( ) chars + space character. */
415static char *
416dupAndQuote(const char *s)
417{
418 const char *ts;
419 size_t alloc_len;
420 char *ret;
421 char *dest;
422
423 ts = s;
424
425 alloc_len = 0;
426
427 for( ;*ts != '\0'; ts++) {
428 alloc_len++;
429 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
430 alloc_len++;
431 }
432 }
433
434 ret = (char *)malloc(alloc_len + 1);
435
436 ts = s;
437 dest = ret;
438
439 for ( ;*ts != '\0'; ts++) {
440 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
441 *dest++ = '\\';
442 }
443
444 *dest++ = *ts;
445 }
446
447 *dest++ = '\0';
448
449 return ret;
450}
451
452/**
453 * Run ppp in "notty" mode against a resource listed as the first parameter
454 * eg:
455 *
456 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
457 *
458 */
459int ppp(int argc, char **argv)
460{
461#ifdef HAVE_WIN32_PROC
462 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
463 return -1;
464#else
465 char *adb_service_name;
466 pid_t pid;
467 int fd;
468
469 if (argc < 2) {
470 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
471 argv[0]);
472
473 return 1;
474 }
475
476 adb_service_name = argv[1];
477
478 fd = adb_connect(adb_service_name);
479
480 if(fd < 0) {
481 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
482 adb_service_name, adb_error());
483 return 1;
484 }
485
486 pid = fork();
487
488 if (pid < 0) {
489 perror("from fork()");
490 return 1;
491 } else if (pid == 0) {
492 int err;
493 int i;
494 const char **ppp_args;
495
496 // copy args
497 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
498 ppp_args[0] = "pppd";
499 for (i = 2 ; i < argc ; i++) {
500 //argv[2] and beyond become ppp_args[1] and beyond
501 ppp_args[i - 1] = argv[i];
502 }
503 ppp_args[i-1] = NULL;
504
505 // child side
506
507 dup2(fd, STDIN_FILENO);
508 dup2(fd, STDOUT_FILENO);
509 adb_close(STDERR_FILENO);
510 adb_close(fd);
511
512 err = execvp("pppd", (char * const *)ppp_args);
513
514 if (err < 0) {
515 perror("execing pppd");
516 }
517 exit(-1);
518 } else {
519 // parent side
520
521 adb_close(fd);
522 return 0;
523 }
524#endif /* !HAVE_WIN32_PROC */
525}
526
527static int send_shellcommand(transport_type transport, char* serial, char* buf)
528{
529 int fd, ret;
530
531 for(;;) {
532 fd = adb_connect(buf);
533 if(fd >= 0)
534 break;
535 fprintf(stderr,"- waiting for device -\n");
536 adb_sleep_ms(1000);
537 do_cmd(transport, serial, "wait-for-device", 0);
538 }
539
540 read_and_dump(fd);
541 ret = adb_close(fd);
542 if (ret)
543 perror("close");
544
545 return ret;
546}
547
548static int logcat(transport_type transport, char* serial, int argc, char **argv)
549{
550 char buf[4096];
551
552 char *log_tags;
553 char *quoted_log_tags;
554
555 log_tags = getenv("ANDROID_LOG_TAGS");
556 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
557
558 snprintf(buf, sizeof(buf),
559 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
560 quoted_log_tags);
561
562 free(quoted_log_tags);
563
Christopher Tate7b9b5162011-11-30 13:00:33 -0800564 if (!strcmp(argv[0],"longcat")) {
565 strncat(buf, " -v long", sizeof(buf)-1);
566 }
567
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800568 argc -= 1;
569 argv += 1;
570 while(argc-- > 0) {
571 char *quoted;
572
573 quoted = dupAndQuote (*argv++);
574
575 strncat(buf, " ", sizeof(buf)-1);
576 strncat(buf, quoted, sizeof(buf)-1);
577 free(quoted);
578 }
579
580 send_shellcommand(transport, serial, buf);
581 return 0;
582}
583
Christopher Tate73779122011-04-21 12:53:28 -0700584static int backup(int argc, char** argv) {
585 char buf[4096];
Christopher Tate24b56162011-08-09 17:05:29 -0700586 const char* filename = "./backup.ab";
Christopher Tate73779122011-04-21 12:53:28 -0700587 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700588 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700589
Christopher Tatefba22972011-06-01 17:56:23 -0700590 /* find, extract, and use any -f argument */
591 for (i = 1; i < argc; i++) {
592 if (!strcmp("-f", argv[i])) {
593 if (i == argc-1) {
594 fprintf(stderr, "adb: -f passed with no filename\n");
595 return usage();
596 }
597 filename = argv[i+1];
598 for (j = i+2; j <= argc; ) {
599 argv[i++] = argv[j++];
600 }
601 argc -= 2;
602 argv[argc] = NULL;
603 }
Christopher Tate73779122011-04-21 12:53:28 -0700604 }
605
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700606 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
607 if (argc < 2) return usage();
608
Christopher Tate73779122011-04-21 12:53:28 -0700609 outFd = adb_open_mode(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
610 if (outFd < 0) {
611 fprintf(stderr, "adb: unable to open file %s\n", filename);
612 return -1;
613 }
614
615 snprintf(buf, sizeof(buf), "backup");
616 for (argc--, argv++; argc; argc--, argv++) {
617 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
618 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
619 }
620
621 D("backup. filename=%s buf=%s\n", filename, buf);
622 fd = adb_connect(buf);
623 if (fd < 0) {
624 fprintf(stderr, "adb: unable to connect for backup\n");
625 adb_close(outFd);
626 return -1;
627 }
628
629 copy_to_file(fd, outFd);
630
631 adb_close(fd);
632 adb_close(outFd);
633 return 0;
634}
635
Christopher Tatecf5379b2011-05-17 15:52:54 -0700636static int restore(int argc, char** argv) {
637 const char* filename;
638 int fd, tarFd;
639
640 if (argc != 2) return usage();
641
642 filename = argv[1];
643 tarFd = adb_open(filename, O_RDONLY);
644 if (tarFd < 0) {
645 fprintf(stderr, "adb: unable to open file %s\n", filename);
646 return -1;
647 }
648
649 fd = adb_connect("restore:");
650 if (fd < 0) {
651 fprintf(stderr, "adb: unable to connect for backup\n");
652 adb_close(tarFd);
653 return -1;
654 }
655
656 copy_to_file(tarFd, fd);
657
658 adb_close(fd);
659 adb_close(tarFd);
660 return 0;
661}
662
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800663#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
664static int top_works(const char *top)
665{
666 if (top != NULL && adb_is_absolute_host_path(top)) {
667 char path_buf[PATH_MAX];
668 snprintf(path_buf, sizeof(path_buf),
669 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
670 return access(path_buf, F_OK) == 0;
671 }
672 return 0;
673}
674
675static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
676{
677 strcpy(path_buf, indir);
678 while (1) {
679 if (top_works(path_buf)) {
680 return path_buf;
681 }
682 char *s = adb_dirstop(path_buf);
683 if (s != NULL) {
684 *s = '\0';
685 } else {
686 path_buf[0] = '\0';
687 return NULL;
688 }
689 }
690}
691
692static char *find_top(char path_buf[PATH_MAX])
693{
694 char *top = getenv("ANDROID_BUILD_TOP");
695 if (top != NULL && top[0] != '\0') {
696 if (!top_works(top)) {
697 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
698 return NULL;
699 }
700 } else {
701 top = getenv("TOP");
702 if (top != NULL && top[0] != '\0') {
703 if (!top_works(top)) {
704 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
705 return NULL;
706 }
707 } else {
708 top = NULL;
709 }
710 }
711
712 if (top != NULL) {
713 /* The environment pointed to a top directory that works.
714 */
715 strcpy(path_buf, top);
716 return path_buf;
717 }
718
719 /* The environment didn't help. Walk up the tree from the CWD
720 * to see if we can find the top.
721 */
722 char dir[PATH_MAX];
723 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
724 if (top == NULL) {
725 /* If the CWD isn't under a good-looking top, see if the
726 * executable is.
727 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100728 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800729 top = find_top_from(dir, path_buf);
730 }
731 return top;
732}
733
734/* <hint> may be:
735 * - A simple product name
736 * e.g., "sooner"
737TODO: debug? sooner-debug, sooner:debug?
738 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
739 * e.g., "out/target/product/sooner"
740 * - An absolute path to the PRODUCT_OUT dir
741 * e.g., "/src/device/out/target/product/sooner"
742 *
743 * Given <hint>, try to construct an absolute path to the
744 * ANDROID_PRODUCT_OUT dir.
745 */
746static const char *find_product_out_path(const char *hint)
747{
748 static char path_buf[PATH_MAX];
749
750 if (hint == NULL || hint[0] == '\0') {
751 return NULL;
752 }
753
754 /* If it's already absolute, don't bother doing any work.
755 */
756 if (adb_is_absolute_host_path(hint)) {
757 strcpy(path_buf, hint);
758 return path_buf;
759 }
760
761 /* If there are any slashes in it, assume it's a relative path;
762 * make it absolute.
763 */
764 if (adb_dirstart(hint) != NULL) {
765 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
766 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
767 return NULL;
768 }
769 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
770 fprintf(stderr, "adb: Couldn't assemble path\n");
771 return NULL;
772 }
773 strcat(path_buf, OS_PATH_SEPARATOR_STR);
774 strcat(path_buf, hint);
775 return path_buf;
776 }
777
778 /* It's a string without any slashes. Try to do something with it.
779 *
780 * Try to find the root of the build tree, and build a PRODUCT_OUT
781 * path from there.
782 */
783 char top_buf[PATH_MAX];
784 const char *top = find_top(top_buf);
785 if (top == NULL) {
786 fprintf(stderr, "adb: Couldn't find top of build tree\n");
787 return NULL;
788 }
789//TODO: if we have a way to indicate debug, look in out/debug/target/...
790 snprintf(path_buf, sizeof(path_buf),
791 "%s" OS_PATH_SEPARATOR_STR
792 "out" OS_PATH_SEPARATOR_STR
793 "target" OS_PATH_SEPARATOR_STR
794 "product" OS_PATH_SEPARATOR_STR
795 "%s", top_buf, hint);
796 if (access(path_buf, F_OK) < 0) {
797 fprintf(stderr, "adb: Couldn't find a product dir "
798 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
799 return NULL;
800 }
801 return path_buf;
802}
803
804int adb_commandline(int argc, char **argv)
805{
806 char buf[4096];
807 int no_daemon = 0;
808 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100809 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800810 int persist = 0;
811 int r;
812 int quote;
813 transport_type ttype = kTransportAny;
814 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100815 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800816
817 /* If defined, this should be an absolute path to
818 * the directory containing all of the various system images
819 * for a particular product. If not defined, and the adb
820 * command requires this information, then the user must
821 * specify the path using "-p".
822 */
823 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
824 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
825 gProductOutPath = NULL;
826 }
827 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
828
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700829 serial = getenv("ANDROID_SERIAL");
830
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100831 /* Validate and assign the server port */
832 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
833 int server_port = DEFAULT_ADB_PORT;
834 if (server_port_str && strlen(server_port_str) > 0) {
835 server_port = (int) strtol(server_port_str, NULL, 0);
836 if (server_port <= 0) {
837 fprintf(stderr,
838 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
839 server_port_str);
840 return usage();
841 }
842 }
843
844 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800845 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100846 if(!strcmp(argv[0],"server")) {
847 is_server = 1;
848 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800849 no_daemon = 1;
850 } else if (!strcmp(argv[0], "fork-server")) {
851 /* this is a special flag used only when the ADB client launches the ADB Server */
852 is_daemon = 1;
853 } else if(!strcmp(argv[0],"persist")) {
854 persist = 1;
855 } else if(!strncmp(argv[0], "-p", 2)) {
856 const char *product = NULL;
857 if (argv[0][2] == '\0') {
858 if (argc < 2) return usage();
859 product = argv[1];
860 argc--;
861 argv++;
862 } else {
863 product = argv[1] + 2;
864 }
865 gProductOutPath = find_product_out_path(product);
866 if (gProductOutPath == NULL) {
867 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
868 product);
869 return usage();
870 }
871 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
872 if (isdigit(argv[0][2])) {
873 serial = argv[0] + 2;
874 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100875 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800876 serial = argv[1];
877 argc--;
878 argv++;
879 }
880 } else if (!strcmp(argv[0],"-d")) {
881 ttype = kTransportUsb;
882 } else if (!strcmp(argv[0],"-e")) {
883 ttype = kTransportLocal;
884 } else {
885 /* out of recognized modifiers and flags */
886 break;
887 }
888 argc--;
889 argv++;
890 }
891
892 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100893 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800894
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100895 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800896 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100897 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800898 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100899 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800900 }
901 if(r) {
902 fprintf(stderr,"* could not start server *\n");
903 }
904 return r;
905 }
906
907top:
908 if(argc == 0) {
909 return usage();
910 }
911
912 /* adb_connect() commands */
913
914 if(!strcmp(argv[0], "devices")) {
915 char *tmp;
916 snprintf(buf, sizeof buf, "host:%s", argv[0]);
917 tmp = adb_query(buf);
918 if(tmp) {
919 printf("List of devices attached \n");
920 printf("%s\n", tmp);
921 return 0;
922 } else {
923 return 1;
924 }
925 }
926
Mike Lockwood01c2c302010-05-24 10:44:35 -0400927 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -0700928 char *tmp;
929 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -0400930 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -0700931 return 1;
932 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400933 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
934 tmp = adb_query(buf);
935 if(tmp) {
936 printf("%s\n", tmp);
937 return 0;
938 } else {
939 return 1;
940 }
941 }
942
943 if(!strcmp(argv[0], "disconnect")) {
944 char *tmp;
945 if (argc > 2) {
946 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
947 return 1;
948 }
949 if (argc == 2) {
950 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
951 } else {
952 snprintf(buf, sizeof buf, "host:disconnect:");
953 }
Mike Lockwood26b88e32009-08-24 15:58:40 -0700954 tmp = adb_query(buf);
955 if(tmp) {
956 printf("%s\n", tmp);
957 return 0;
958 } else {
959 return 1;
960 }
961 }
962
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800963 if (!strcmp(argv[0], "emu")) {
964 return adb_send_emulator_command(argc, argv);
965 }
966
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400967 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800968 int r;
969 int fd;
970
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400971 char h = (argv[0][0] == 'h');
972
973 if (h) {
974 printf("\x1b[41;33m");
975 fflush(stdout);
976 }
977
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800978 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700979 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400980 r = interactive_shell();
981 if (h) {
982 printf("\x1b[0m");
983 fflush(stdout);
984 }
985 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800986 }
987
988 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
989 argc -= 2;
990 argv += 2;
991 while(argc-- > 0) {
992 strcat(buf, " ");
993
994 /* quote empty strings and strings with spaces */
995 quote = (**argv == 0 || strchr(*argv, ' '));
996 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100997 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800998 strcat(buf, *argv++);
999 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001000 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001001 }
1002
1003 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001004 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001005 fd = adb_connect(buf);
1006 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001007 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001008 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001009 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001010 adb_close(fd);
1011 r = 0;
1012 } else {
1013 fprintf(stderr,"error: %s\n", adb_error());
1014 r = -1;
1015 }
1016
1017 if(persist) {
1018 fprintf(stderr,"\n- waiting for device -\n");
1019 adb_sleep_ms(1000);
1020 do_cmd(ttype, serial, "wait-for-device", 0);
1021 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001022 if (h) {
1023 printf("\x1b[0m");
1024 fflush(stdout);
1025 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001026 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001027 return r;
1028 }
1029 }
1030 }
1031
1032 if(!strcmp(argv[0], "kill-server")) {
1033 int fd;
1034 fd = _adb_connect("host:kill");
1035 if(fd == -1) {
1036 fprintf(stderr,"* server not running *\n");
1037 return 1;
1038 }
1039 return 0;
1040 }
1041
Mike Lockwood26b88e32009-08-24 15:58:40 -07001042 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001043 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001044 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001045 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001046 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001047 if (!strcmp(argv[0], "reboot-bootloader"))
1048 snprintf(command, sizeof(command), "reboot:bootloader");
1049 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001050 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001051 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001052 snprintf(command, sizeof(command), "%s:", argv[0]);
1053 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001054 if(fd >= 0) {
1055 read_and_dump(fd);
1056 adb_close(fd);
1057 return 0;
1058 }
1059 fprintf(stderr,"error: %s\n", adb_error());
1060 return 1;
1061 }
1062
Mike Lockwood78589f32009-09-03 14:54:58 -04001063 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001064 if (argc != 1) return usage();
1065 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001066 return 0;
1067 }
1068
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001069 /* adb_command() wrapper commands */
1070
1071 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1072 char* service = argv[0];
1073 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1074 if (ttype == kTransportUsb) {
1075 service = "wait-for-usb";
1076 } else if (ttype == kTransportLocal) {
1077 service = "wait-for-local";
1078 } else {
1079 service = "wait-for-any";
1080 }
1081 }
1082
1083 format_host_command(buf, sizeof buf, service, ttype, serial);
1084
1085 if (adb_command(buf)) {
1086 D("failure: %s *\n",adb_error());
1087 fprintf(stderr,"error: %s\n", adb_error());
1088 return 1;
1089 }
1090
1091 /* Allow a command to be run after wait-for-device,
1092 * e.g. 'adb wait-for-device shell'.
1093 */
1094 if(argc > 1) {
1095 argc--;
1096 argv++;
1097 goto top;
1098 }
1099 return 0;
1100 }
1101
1102 if(!strcmp(argv[0], "forward")) {
1103 if(argc != 3) return usage();
1104 if (serial) {
Mike Lockwood47b41622009-11-28 12:46:13 -05001105 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1106 } else if (ttype == kTransportUsb) {
1107 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1108 } else if (ttype == kTransportLocal) {
1109 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001110 } else {
Mike Lockwood47b41622009-11-28 12:46:13 -05001111 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001112 }
1113 if(adb_command(buf)) {
1114 fprintf(stderr,"error: %s\n", adb_error());
1115 return 1;
1116 }
1117 return 0;
1118 }
1119
1120 /* do_sync_*() commands */
1121
1122 if(!strcmp(argv[0], "ls")) {
1123 if(argc != 2) return usage();
1124 return do_sync_ls(argv[1]);
1125 }
1126
1127 if(!strcmp(argv[0], "push")) {
1128 if(argc != 3) return usage();
1129 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1130 }
1131
1132 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001133 if (argc == 2) {
1134 return do_sync_pull(argv[1], ".");
1135 } else if (argc == 3) {
1136 return do_sync_pull(argv[1], argv[2]);
1137 } else {
1138 return usage();
1139 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001140 }
1141
1142 if(!strcmp(argv[0], "install")) {
1143 if (argc < 2) return usage();
1144 return install_app(ttype, serial, argc, argv);
1145 }
1146
1147 if(!strcmp(argv[0], "uninstall")) {
1148 if (argc < 2) return usage();
1149 return uninstall_app(ttype, serial, argc, argv);
1150 }
1151
1152 if(!strcmp(argv[0], "sync")) {
1153 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001154 int listonly = 0;
1155
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001156 int ret;
1157 if(argc < 2) {
1158 /* No local path was specified. */
1159 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001160 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1161 listonly = 1;
1162 if (argc == 3) {
1163 srcarg = argv[2];
1164 } else {
1165 srcarg = NULL;
1166 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001167 } else if(argc == 2) {
1168 /* A local path or "android"/"data" arg was specified. */
1169 srcarg = argv[1];
1170 } else {
1171 return usage();
1172 }
1173 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1174 if(ret != 0) return usage();
1175
1176 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001177 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001178 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001179 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001180
1181 free(android_srcpath);
1182 free(data_srcpath);
1183 return ret;
1184 }
1185
1186 /* passthrough commands */
1187
1188 if(!strcmp(argv[0],"get-state") ||
1189 !strcmp(argv[0],"get-serialno"))
1190 {
1191 char *tmp;
1192
1193 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1194 tmp = adb_query(buf);
1195 if(tmp) {
1196 printf("%s\n", tmp);
1197 return 0;
1198 } else {
1199 return 1;
1200 }
1201 }
1202
1203 /* other commands */
1204
1205 if(!strcmp(argv[0],"status-window")) {
1206 status_window(ttype, serial);
1207 return 0;
1208 }
1209
Christopher Tate7b9b5162011-11-30 13:00:33 -08001210 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001211 return logcat(ttype, serial, argc, argv);
1212 }
1213
1214 if(!strcmp(argv[0],"ppp")) {
1215 return ppp(argc, argv);
1216 }
1217
1218 if (!strcmp(argv[0], "start-server")) {
1219 return adb_connect("host:start-server");
1220 }
1221
Christopher Tate73779122011-04-21 12:53:28 -07001222 if (!strcmp(argv[0], "backup")) {
1223 return backup(argc, argv);
1224 }
1225
Christopher Tatecf5379b2011-05-17 15:52:54 -07001226 if (!strcmp(argv[0], "restore")) {
1227 return restore(argc, argv);
1228 }
1229
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001230 if (!strcmp(argv[0], "jdwp")) {
1231 int fd = adb_connect("jdwp");
1232 if (fd >= 0) {
1233 read_and_dump(fd);
1234 adb_close(fd);
1235 return 0;
1236 } else {
1237 fprintf(stderr, "error: %s\n", adb_error());
1238 return -1;
1239 }
1240 }
1241
1242 /* "adb /?" is a common idiom under Windows */
1243 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1244 help();
1245 return 0;
1246 }
1247
1248 if(!strcmp(argv[0], "version")) {
1249 version(stdout);
1250 return 0;
1251 }
1252
1253 usage();
1254 return 1;
1255}
1256
1257static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1258{
1259 char *argv[16];
1260 int argc;
1261 va_list ap;
1262
1263 va_start(ap, cmd);
1264 argc = 0;
1265
1266 if (serial) {
1267 argv[argc++] = "-s";
1268 argv[argc++] = serial;
1269 } else if (ttype == kTransportUsb) {
1270 argv[argc++] = "-d";
1271 } else if (ttype == kTransportLocal) {
1272 argv[argc++] = "-e";
1273 }
1274
1275 argv[argc++] = cmd;
1276 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1277 va_end(ap);
1278
1279#if 0
1280 int n;
1281 fprintf(stderr,"argc = %d\n",argc);
1282 for(n = 0; n < argc; n++) {
1283 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1284 }
1285#endif
1286
1287 return adb_commandline(argc, argv);
1288}
1289
1290int find_sync_dirs(const char *srcarg,
1291 char **android_srcdir_out, char **data_srcdir_out)
1292{
1293 char *android_srcdir, *data_srcdir;
1294
1295 if(srcarg == NULL) {
1296 android_srcdir = product_file("system");
1297 data_srcdir = product_file("data");
1298 } else {
1299 /* srcarg may be "data", "system" or NULL.
1300 * if srcarg is NULL, then both data and system are synced
1301 */
1302 if(strcmp(srcarg, "system") == 0) {
1303 android_srcdir = product_file("system");
1304 data_srcdir = NULL;
1305 } else if(strcmp(srcarg, "data") == 0) {
1306 android_srcdir = NULL;
1307 data_srcdir = product_file("data");
1308 } else {
1309 /* It's not "system" or "data".
1310 */
1311 return 1;
1312 }
1313 }
1314
1315 if(android_srcdir_out != NULL)
1316 *android_srcdir_out = android_srcdir;
1317 else
1318 free(android_srcdir);
1319
1320 if(data_srcdir_out != NULL)
1321 *data_srcdir_out = data_srcdir;
1322 else
1323 free(data_srcdir);
1324
1325 return 0;
1326}
1327
1328static int pm_command(transport_type transport, char* serial,
1329 int argc, char** argv)
1330{
1331 char buf[4096];
1332
1333 snprintf(buf, sizeof(buf), "shell:pm");
1334
1335 while(argc-- > 0) {
1336 char *quoted;
1337
1338 quoted = dupAndQuote(*argv++);
1339
1340 strncat(buf, " ", sizeof(buf)-1);
1341 strncat(buf, quoted, sizeof(buf)-1);
1342 free(quoted);
1343 }
1344
1345 send_shellcommand(transport, serial, buf);
1346 return 0;
1347}
1348
1349int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1350{
1351 /* if the user choose the -k option, we refuse to do it until devices are
1352 out with the option to uninstall the remaining data somehow (adb/ui) */
1353 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1354 {
1355 printf(
1356 "The -k option uninstalls the application while retaining the data/cache.\n"
1357 "At the moment, there is no way to remove the remaining data.\n"
1358 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1359 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1360 return -1;
1361 }
1362
1363 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1364 return pm_command(transport, serial, argc, argv);
1365}
1366
1367static int delete_file(transport_type transport, char* serial, char* filename)
1368{
1369 char buf[4096];
1370 char* quoted;
1371
1372 snprintf(buf, sizeof(buf), "shell:rm ");
1373 quoted = dupAndQuote(filename);
1374 strncat(buf, quoted, sizeof(buf)-1);
1375 free(quoted);
1376
1377 send_shellcommand(transport, serial, buf);
1378 return 0;
1379}
1380
Kenny Root3802c992011-08-05 11:19:45 -07001381static const char* get_basename(const char* filename)
1382{
1383 const char* basename = adb_dirstop(filename);
1384 if (basename) {
1385 basename++;
1386 return basename;
1387 } else {
1388 return filename;
1389 }
1390}
1391
1392static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001393{
1394 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001395
Kenny Root3802c992011-08-05 11:19:45 -07001396 if (filename == NULL) {
1397 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001398 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001399
Kenny Root3802c992011-08-05 11:19:45 -07001400 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001401 fprintf(stderr, "can't find '%s' to install\n", filename);
1402 return 1;
1403 }
Kenny Root3802c992011-08-05 11:19:45 -07001404
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001405 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001406 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001407 return 1;
1408 }
1409
Kenny Root3802c992011-08-05 11:19:45 -07001410 return 0;
1411}
1412
1413int install_app(transport_type transport, char* serial, int argc, char** argv)
1414{
1415 static const char *const DATA_DEST = "/data/local/tmp/%s";
1416 static const char *const SD_DEST = "/sdcard/tmp/%s";
1417 const char* where = DATA_DEST;
1418 char apk_dest[PATH_MAX];
1419 char verification_dest[PATH_MAX];
1420 char* apk_file;
1421 char* verification_file = NULL;
1422 int file_arg = -1;
1423 int err;
1424 int i;
1425
1426 for (i = 1; i < argc; i++) {
1427 if (*argv[i] != '-') {
1428 file_arg = i;
1429 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001430 } else if (!strcmp(argv[i], "-i")) {
1431 // Skip the installer package name.
1432 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001433 } else if (!strcmp(argv[i], "-s")) {
1434 where = SD_DEST;
1435 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001436 }
1437
Kenny Root3802c992011-08-05 11:19:45 -07001438 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001439 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001440 return 1;
1441 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001442 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001443 return 1;
1444 }
1445
1446 apk_file = argv[file_arg];
1447
1448 if (file_arg != argc - 1) {
1449 verification_file = argv[file_arg + 1];
1450 }
1451
1452 if (check_file(apk_file) || check_file(verification_file)) {
1453 return 1;
1454 }
1455
1456 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1457 if (verification_file != NULL) {
1458 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1459
1460 if (!strcmp(apk_dest, verification_dest)) {
1461 fprintf(stderr, "APK and verification file can't have the same name\n");
1462 return 1;
1463 }
1464 }
1465
1466 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1467 if (err) {
1468 return err;
1469 } else {
1470 argv[file_arg] = apk_dest; /* destination name, not source location */
1471 }
1472
1473 if (verification_file != NULL) {
1474 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1475 if (err) {
1476 goto cleanup_apk;
1477 } else {
1478 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1479 }
1480 }
1481
1482 pm_command(transport, serial, argc, argv);
1483
1484 if (verification_file != NULL) {
1485 delete_file(transport, serial, verification_dest);
1486 }
1487
1488cleanup_apk:
1489 delete_file(transport, serial, apk_dest);
1490
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001491 return err;
1492}