blob: 4c1523248b3c82386f72a4298fc1e1cff2a84d59 [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
564 argc -= 1;
565 argv += 1;
566 while(argc-- > 0) {
567 char *quoted;
568
569 quoted = dupAndQuote (*argv++);
570
571 strncat(buf, " ", sizeof(buf)-1);
572 strncat(buf, quoted, sizeof(buf)-1);
573 free(quoted);
574 }
575
576 send_shellcommand(transport, serial, buf);
577 return 0;
578}
579
Christopher Tate73779122011-04-21 12:53:28 -0700580static int backup(int argc, char** argv) {
581 char buf[4096];
Christopher Tate24b56162011-08-09 17:05:29 -0700582 const char* filename = "./backup.ab";
Christopher Tate73779122011-04-21 12:53:28 -0700583 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700584 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700585
Christopher Tatefba22972011-06-01 17:56:23 -0700586 /* find, extract, and use any -f argument */
587 for (i = 1; i < argc; i++) {
588 if (!strcmp("-f", argv[i])) {
589 if (i == argc-1) {
590 fprintf(stderr, "adb: -f passed with no filename\n");
591 return usage();
592 }
593 filename = argv[i+1];
594 for (j = i+2; j <= argc; ) {
595 argv[i++] = argv[j++];
596 }
597 argc -= 2;
598 argv[argc] = NULL;
599 }
Christopher Tate73779122011-04-21 12:53:28 -0700600 }
601
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700602 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
603 if (argc < 2) return usage();
604
Christopher Tate73779122011-04-21 12:53:28 -0700605 outFd = adb_open_mode(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
606 if (outFd < 0) {
607 fprintf(stderr, "adb: unable to open file %s\n", filename);
608 return -1;
609 }
610
611 snprintf(buf, sizeof(buf), "backup");
612 for (argc--, argv++; argc; argc--, argv++) {
613 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
614 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
615 }
616
617 D("backup. filename=%s buf=%s\n", filename, buf);
618 fd = adb_connect(buf);
619 if (fd < 0) {
620 fprintf(stderr, "adb: unable to connect for backup\n");
621 adb_close(outFd);
622 return -1;
623 }
624
625 copy_to_file(fd, outFd);
626
627 adb_close(fd);
628 adb_close(outFd);
629 return 0;
630}
631
Christopher Tatecf5379b2011-05-17 15:52:54 -0700632static int restore(int argc, char** argv) {
633 const char* filename;
634 int fd, tarFd;
635
636 if (argc != 2) return usage();
637
638 filename = argv[1];
639 tarFd = adb_open(filename, O_RDONLY);
640 if (tarFd < 0) {
641 fprintf(stderr, "adb: unable to open file %s\n", filename);
642 return -1;
643 }
644
645 fd = adb_connect("restore:");
646 if (fd < 0) {
647 fprintf(stderr, "adb: unable to connect for backup\n");
648 adb_close(tarFd);
649 return -1;
650 }
651
652 copy_to_file(tarFd, fd);
653
654 adb_close(fd);
655 adb_close(tarFd);
656 return 0;
657}
658
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800659#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
660static int top_works(const char *top)
661{
662 if (top != NULL && adb_is_absolute_host_path(top)) {
663 char path_buf[PATH_MAX];
664 snprintf(path_buf, sizeof(path_buf),
665 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
666 return access(path_buf, F_OK) == 0;
667 }
668 return 0;
669}
670
671static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
672{
673 strcpy(path_buf, indir);
674 while (1) {
675 if (top_works(path_buf)) {
676 return path_buf;
677 }
678 char *s = adb_dirstop(path_buf);
679 if (s != NULL) {
680 *s = '\0';
681 } else {
682 path_buf[0] = '\0';
683 return NULL;
684 }
685 }
686}
687
688static char *find_top(char path_buf[PATH_MAX])
689{
690 char *top = getenv("ANDROID_BUILD_TOP");
691 if (top != NULL && top[0] != '\0') {
692 if (!top_works(top)) {
693 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
694 return NULL;
695 }
696 } else {
697 top = getenv("TOP");
698 if (top != NULL && top[0] != '\0') {
699 if (!top_works(top)) {
700 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
701 return NULL;
702 }
703 } else {
704 top = NULL;
705 }
706 }
707
708 if (top != NULL) {
709 /* The environment pointed to a top directory that works.
710 */
711 strcpy(path_buf, top);
712 return path_buf;
713 }
714
715 /* The environment didn't help. Walk up the tree from the CWD
716 * to see if we can find the top.
717 */
718 char dir[PATH_MAX];
719 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
720 if (top == NULL) {
721 /* If the CWD isn't under a good-looking top, see if the
722 * executable is.
723 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100724 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800725 top = find_top_from(dir, path_buf);
726 }
727 return top;
728}
729
730/* <hint> may be:
731 * - A simple product name
732 * e.g., "sooner"
733TODO: debug? sooner-debug, sooner:debug?
734 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
735 * e.g., "out/target/product/sooner"
736 * - An absolute path to the PRODUCT_OUT dir
737 * e.g., "/src/device/out/target/product/sooner"
738 *
739 * Given <hint>, try to construct an absolute path to the
740 * ANDROID_PRODUCT_OUT dir.
741 */
742static const char *find_product_out_path(const char *hint)
743{
744 static char path_buf[PATH_MAX];
745
746 if (hint == NULL || hint[0] == '\0') {
747 return NULL;
748 }
749
750 /* If it's already absolute, don't bother doing any work.
751 */
752 if (adb_is_absolute_host_path(hint)) {
753 strcpy(path_buf, hint);
754 return path_buf;
755 }
756
757 /* If there are any slashes in it, assume it's a relative path;
758 * make it absolute.
759 */
760 if (adb_dirstart(hint) != NULL) {
761 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
762 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
763 return NULL;
764 }
765 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
766 fprintf(stderr, "adb: Couldn't assemble path\n");
767 return NULL;
768 }
769 strcat(path_buf, OS_PATH_SEPARATOR_STR);
770 strcat(path_buf, hint);
771 return path_buf;
772 }
773
774 /* It's a string without any slashes. Try to do something with it.
775 *
776 * Try to find the root of the build tree, and build a PRODUCT_OUT
777 * path from there.
778 */
779 char top_buf[PATH_MAX];
780 const char *top = find_top(top_buf);
781 if (top == NULL) {
782 fprintf(stderr, "adb: Couldn't find top of build tree\n");
783 return NULL;
784 }
785//TODO: if we have a way to indicate debug, look in out/debug/target/...
786 snprintf(path_buf, sizeof(path_buf),
787 "%s" OS_PATH_SEPARATOR_STR
788 "out" OS_PATH_SEPARATOR_STR
789 "target" OS_PATH_SEPARATOR_STR
790 "product" OS_PATH_SEPARATOR_STR
791 "%s", top_buf, hint);
792 if (access(path_buf, F_OK) < 0) {
793 fprintf(stderr, "adb: Couldn't find a product dir "
794 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
795 return NULL;
796 }
797 return path_buf;
798}
799
800int adb_commandline(int argc, char **argv)
801{
802 char buf[4096];
803 int no_daemon = 0;
804 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100805 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800806 int persist = 0;
807 int r;
808 int quote;
809 transport_type ttype = kTransportAny;
810 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100811 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800812
813 /* If defined, this should be an absolute path to
814 * the directory containing all of the various system images
815 * for a particular product. If not defined, and the adb
816 * command requires this information, then the user must
817 * specify the path using "-p".
818 */
819 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
820 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
821 gProductOutPath = NULL;
822 }
823 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
824
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700825 serial = getenv("ANDROID_SERIAL");
826
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100827 /* Validate and assign the server port */
828 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
829 int server_port = DEFAULT_ADB_PORT;
830 if (server_port_str && strlen(server_port_str) > 0) {
831 server_port = (int) strtol(server_port_str, NULL, 0);
832 if (server_port <= 0) {
833 fprintf(stderr,
834 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
835 server_port_str);
836 return usage();
837 }
838 }
839
840 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800841 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100842 if(!strcmp(argv[0],"server")) {
843 is_server = 1;
844 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800845 no_daemon = 1;
846 } else if (!strcmp(argv[0], "fork-server")) {
847 /* this is a special flag used only when the ADB client launches the ADB Server */
848 is_daemon = 1;
849 } else if(!strcmp(argv[0],"persist")) {
850 persist = 1;
851 } else if(!strncmp(argv[0], "-p", 2)) {
852 const char *product = NULL;
853 if (argv[0][2] == '\0') {
854 if (argc < 2) return usage();
855 product = argv[1];
856 argc--;
857 argv++;
858 } else {
859 product = argv[1] + 2;
860 }
861 gProductOutPath = find_product_out_path(product);
862 if (gProductOutPath == NULL) {
863 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
864 product);
865 return usage();
866 }
867 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
868 if (isdigit(argv[0][2])) {
869 serial = argv[0] + 2;
870 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100871 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800872 serial = argv[1];
873 argc--;
874 argv++;
875 }
876 } else if (!strcmp(argv[0],"-d")) {
877 ttype = kTransportUsb;
878 } else if (!strcmp(argv[0],"-e")) {
879 ttype = kTransportLocal;
880 } else {
881 /* out of recognized modifiers and flags */
882 break;
883 }
884 argc--;
885 argv++;
886 }
887
888 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100889 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800890
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100891 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800892 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100893 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800894 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100895 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800896 }
897 if(r) {
898 fprintf(stderr,"* could not start server *\n");
899 }
900 return r;
901 }
902
903top:
904 if(argc == 0) {
905 return usage();
906 }
907
908 /* adb_connect() commands */
909
910 if(!strcmp(argv[0], "devices")) {
911 char *tmp;
912 snprintf(buf, sizeof buf, "host:%s", argv[0]);
913 tmp = adb_query(buf);
914 if(tmp) {
915 printf("List of devices attached \n");
916 printf("%s\n", tmp);
917 return 0;
918 } else {
919 return 1;
920 }
921 }
922
Mike Lockwood01c2c302010-05-24 10:44:35 -0400923 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -0700924 char *tmp;
925 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -0400926 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -0700927 return 1;
928 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400929 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
930 tmp = adb_query(buf);
931 if(tmp) {
932 printf("%s\n", tmp);
933 return 0;
934 } else {
935 return 1;
936 }
937 }
938
939 if(!strcmp(argv[0], "disconnect")) {
940 char *tmp;
941 if (argc > 2) {
942 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
943 return 1;
944 }
945 if (argc == 2) {
946 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
947 } else {
948 snprintf(buf, sizeof buf, "host:disconnect:");
949 }
Mike Lockwood26b88e32009-08-24 15:58:40 -0700950 tmp = adb_query(buf);
951 if(tmp) {
952 printf("%s\n", tmp);
953 return 0;
954 } else {
955 return 1;
956 }
957 }
958
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800959 if (!strcmp(argv[0], "emu")) {
960 return adb_send_emulator_command(argc, argv);
961 }
962
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400963 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800964 int r;
965 int fd;
966
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400967 char h = (argv[0][0] == 'h');
968
969 if (h) {
970 printf("\x1b[41;33m");
971 fflush(stdout);
972 }
973
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800974 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700975 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400976 r = interactive_shell();
977 if (h) {
978 printf("\x1b[0m");
979 fflush(stdout);
980 }
981 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800982 }
983
984 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
985 argc -= 2;
986 argv += 2;
987 while(argc-- > 0) {
988 strcat(buf, " ");
989
990 /* quote empty strings and strings with spaces */
991 quote = (**argv == 0 || strchr(*argv, ' '));
992 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100993 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800994 strcat(buf, *argv++);
995 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100996 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800997 }
998
999 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001000 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001001 fd = adb_connect(buf);
1002 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001003 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001004 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001005 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001006 adb_close(fd);
1007 r = 0;
1008 } else {
1009 fprintf(stderr,"error: %s\n", adb_error());
1010 r = -1;
1011 }
1012
1013 if(persist) {
1014 fprintf(stderr,"\n- waiting for device -\n");
1015 adb_sleep_ms(1000);
1016 do_cmd(ttype, serial, "wait-for-device", 0);
1017 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001018 if (h) {
1019 printf("\x1b[0m");
1020 fflush(stdout);
1021 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001022 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001023 return r;
1024 }
1025 }
1026 }
1027
1028 if(!strcmp(argv[0], "kill-server")) {
1029 int fd;
1030 fd = _adb_connect("host:kill");
1031 if(fd == -1) {
1032 fprintf(stderr,"* server not running *\n");
1033 return 1;
1034 }
1035 return 0;
1036 }
1037
Mike Lockwood26b88e32009-08-24 15:58:40 -07001038 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001039 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001040 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001041 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001042 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001043 if (!strcmp(argv[0], "reboot-bootloader"))
1044 snprintf(command, sizeof(command), "reboot:bootloader");
1045 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001046 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001047 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001048 snprintf(command, sizeof(command), "%s:", argv[0]);
1049 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001050 if(fd >= 0) {
1051 read_and_dump(fd);
1052 adb_close(fd);
1053 return 0;
1054 }
1055 fprintf(stderr,"error: %s\n", adb_error());
1056 return 1;
1057 }
1058
Mike Lockwood78589f32009-09-03 14:54:58 -04001059 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001060 if (argc != 1) return usage();
1061 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001062 return 0;
1063 }
1064
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001065 /* adb_command() wrapper commands */
1066
1067 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1068 char* service = argv[0];
1069 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1070 if (ttype == kTransportUsb) {
1071 service = "wait-for-usb";
1072 } else if (ttype == kTransportLocal) {
1073 service = "wait-for-local";
1074 } else {
1075 service = "wait-for-any";
1076 }
1077 }
1078
1079 format_host_command(buf, sizeof buf, service, ttype, serial);
1080
1081 if (adb_command(buf)) {
1082 D("failure: %s *\n",adb_error());
1083 fprintf(stderr,"error: %s\n", adb_error());
1084 return 1;
1085 }
1086
1087 /* Allow a command to be run after wait-for-device,
1088 * e.g. 'adb wait-for-device shell'.
1089 */
1090 if(argc > 1) {
1091 argc--;
1092 argv++;
1093 goto top;
1094 }
1095 return 0;
1096 }
1097
1098 if(!strcmp(argv[0], "forward")) {
1099 if(argc != 3) return usage();
1100 if (serial) {
Mike Lockwood47b41622009-11-28 12:46:13 -05001101 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1102 } else if (ttype == kTransportUsb) {
1103 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1104 } else if (ttype == kTransportLocal) {
1105 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001106 } else {
Mike Lockwood47b41622009-11-28 12:46:13 -05001107 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001108 }
1109 if(adb_command(buf)) {
1110 fprintf(stderr,"error: %s\n", adb_error());
1111 return 1;
1112 }
1113 return 0;
1114 }
1115
1116 /* do_sync_*() commands */
1117
1118 if(!strcmp(argv[0], "ls")) {
1119 if(argc != 2) return usage();
1120 return do_sync_ls(argv[1]);
1121 }
1122
1123 if(!strcmp(argv[0], "push")) {
1124 if(argc != 3) return usage();
1125 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1126 }
1127
1128 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001129 if (argc == 2) {
1130 return do_sync_pull(argv[1], ".");
1131 } else if (argc == 3) {
1132 return do_sync_pull(argv[1], argv[2]);
1133 } else {
1134 return usage();
1135 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001136 }
1137
1138 if(!strcmp(argv[0], "install")) {
1139 if (argc < 2) return usage();
1140 return install_app(ttype, serial, argc, argv);
1141 }
1142
1143 if(!strcmp(argv[0], "uninstall")) {
1144 if (argc < 2) return usage();
1145 return uninstall_app(ttype, serial, argc, argv);
1146 }
1147
1148 if(!strcmp(argv[0], "sync")) {
1149 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001150 int listonly = 0;
1151
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001152 int ret;
1153 if(argc < 2) {
1154 /* No local path was specified. */
1155 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001156 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1157 listonly = 1;
1158 if (argc == 3) {
1159 srcarg = argv[2];
1160 } else {
1161 srcarg = NULL;
1162 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001163 } else if(argc == 2) {
1164 /* A local path or "android"/"data" arg was specified. */
1165 srcarg = argv[1];
1166 } else {
1167 return usage();
1168 }
1169 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1170 if(ret != 0) return usage();
1171
1172 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001173 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001174 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001175 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001176
1177 free(android_srcpath);
1178 free(data_srcpath);
1179 return ret;
1180 }
1181
1182 /* passthrough commands */
1183
1184 if(!strcmp(argv[0],"get-state") ||
1185 !strcmp(argv[0],"get-serialno"))
1186 {
1187 char *tmp;
1188
1189 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1190 tmp = adb_query(buf);
1191 if(tmp) {
1192 printf("%s\n", tmp);
1193 return 0;
1194 } else {
1195 return 1;
1196 }
1197 }
1198
1199 /* other commands */
1200
1201 if(!strcmp(argv[0],"status-window")) {
1202 status_window(ttype, serial);
1203 return 0;
1204 }
1205
1206 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1207 return logcat(ttype, serial, argc, argv);
1208 }
1209
1210 if(!strcmp(argv[0],"ppp")) {
1211 return ppp(argc, argv);
1212 }
1213
1214 if (!strcmp(argv[0], "start-server")) {
1215 return adb_connect("host:start-server");
1216 }
1217
Christopher Tate73779122011-04-21 12:53:28 -07001218 if (!strcmp(argv[0], "backup")) {
1219 return backup(argc, argv);
1220 }
1221
Christopher Tatecf5379b2011-05-17 15:52:54 -07001222 if (!strcmp(argv[0], "restore")) {
1223 return restore(argc, argv);
1224 }
1225
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001226 if (!strcmp(argv[0], "jdwp")) {
1227 int fd = adb_connect("jdwp");
1228 if (fd >= 0) {
1229 read_and_dump(fd);
1230 adb_close(fd);
1231 return 0;
1232 } else {
1233 fprintf(stderr, "error: %s\n", adb_error());
1234 return -1;
1235 }
1236 }
1237
1238 /* "adb /?" is a common idiom under Windows */
1239 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1240 help();
1241 return 0;
1242 }
1243
1244 if(!strcmp(argv[0], "version")) {
1245 version(stdout);
1246 return 0;
1247 }
1248
1249 usage();
1250 return 1;
1251}
1252
1253static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1254{
1255 char *argv[16];
1256 int argc;
1257 va_list ap;
1258
1259 va_start(ap, cmd);
1260 argc = 0;
1261
1262 if (serial) {
1263 argv[argc++] = "-s";
1264 argv[argc++] = serial;
1265 } else if (ttype == kTransportUsb) {
1266 argv[argc++] = "-d";
1267 } else if (ttype == kTransportLocal) {
1268 argv[argc++] = "-e";
1269 }
1270
1271 argv[argc++] = cmd;
1272 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1273 va_end(ap);
1274
1275#if 0
1276 int n;
1277 fprintf(stderr,"argc = %d\n",argc);
1278 for(n = 0; n < argc; n++) {
1279 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1280 }
1281#endif
1282
1283 return adb_commandline(argc, argv);
1284}
1285
1286int find_sync_dirs(const char *srcarg,
1287 char **android_srcdir_out, char **data_srcdir_out)
1288{
1289 char *android_srcdir, *data_srcdir;
1290
1291 if(srcarg == NULL) {
1292 android_srcdir = product_file("system");
1293 data_srcdir = product_file("data");
1294 } else {
1295 /* srcarg may be "data", "system" or NULL.
1296 * if srcarg is NULL, then both data and system are synced
1297 */
1298 if(strcmp(srcarg, "system") == 0) {
1299 android_srcdir = product_file("system");
1300 data_srcdir = NULL;
1301 } else if(strcmp(srcarg, "data") == 0) {
1302 android_srcdir = NULL;
1303 data_srcdir = product_file("data");
1304 } else {
1305 /* It's not "system" or "data".
1306 */
1307 return 1;
1308 }
1309 }
1310
1311 if(android_srcdir_out != NULL)
1312 *android_srcdir_out = android_srcdir;
1313 else
1314 free(android_srcdir);
1315
1316 if(data_srcdir_out != NULL)
1317 *data_srcdir_out = data_srcdir;
1318 else
1319 free(data_srcdir);
1320
1321 return 0;
1322}
1323
1324static int pm_command(transport_type transport, char* serial,
1325 int argc, char** argv)
1326{
1327 char buf[4096];
1328
1329 snprintf(buf, sizeof(buf), "shell:pm");
1330
1331 while(argc-- > 0) {
1332 char *quoted;
1333
1334 quoted = dupAndQuote(*argv++);
1335
1336 strncat(buf, " ", sizeof(buf)-1);
1337 strncat(buf, quoted, sizeof(buf)-1);
1338 free(quoted);
1339 }
1340
1341 send_shellcommand(transport, serial, buf);
1342 return 0;
1343}
1344
1345int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1346{
1347 /* if the user choose the -k option, we refuse to do it until devices are
1348 out with the option to uninstall the remaining data somehow (adb/ui) */
1349 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1350 {
1351 printf(
1352 "The -k option uninstalls the application while retaining the data/cache.\n"
1353 "At the moment, there is no way to remove the remaining data.\n"
1354 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1355 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1356 return -1;
1357 }
1358
1359 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1360 return pm_command(transport, serial, argc, argv);
1361}
1362
1363static int delete_file(transport_type transport, char* serial, char* filename)
1364{
1365 char buf[4096];
1366 char* quoted;
1367
1368 snprintf(buf, sizeof(buf), "shell:rm ");
1369 quoted = dupAndQuote(filename);
1370 strncat(buf, quoted, sizeof(buf)-1);
1371 free(quoted);
1372
1373 send_shellcommand(transport, serial, buf);
1374 return 0;
1375}
1376
Kenny Root3802c992011-08-05 11:19:45 -07001377static const char* get_basename(const char* filename)
1378{
1379 const char* basename = adb_dirstop(filename);
1380 if (basename) {
1381 basename++;
1382 return basename;
1383 } else {
1384 return filename;
1385 }
1386}
1387
1388static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001389{
1390 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001391
Kenny Root3802c992011-08-05 11:19:45 -07001392 if (filename == NULL) {
1393 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001394 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001395
Kenny Root3802c992011-08-05 11:19:45 -07001396 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001397 fprintf(stderr, "can't find '%s' to install\n", filename);
1398 return 1;
1399 }
Kenny Root3802c992011-08-05 11:19:45 -07001400
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001401 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001402 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001403 return 1;
1404 }
1405
Kenny Root3802c992011-08-05 11:19:45 -07001406 return 0;
1407}
1408
1409int install_app(transport_type transport, char* serial, int argc, char** argv)
1410{
1411 static const char *const DATA_DEST = "/data/local/tmp/%s";
1412 static const char *const SD_DEST = "/sdcard/tmp/%s";
1413 const char* where = DATA_DEST;
1414 char apk_dest[PATH_MAX];
1415 char verification_dest[PATH_MAX];
1416 char* apk_file;
1417 char* verification_file = NULL;
1418 int file_arg = -1;
1419 int err;
1420 int i;
1421
1422 for (i = 1; i < argc; i++) {
1423 if (*argv[i] != '-') {
1424 file_arg = i;
1425 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001426 } else if (!strcmp(argv[i], "-i")) {
1427 // Skip the installer package name.
1428 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001429 } else if (!strcmp(argv[i], "-s")) {
1430 where = SD_DEST;
1431 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001432 }
1433
Kenny Root3802c992011-08-05 11:19:45 -07001434 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001435 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001436 return 1;
1437 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001438 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001439 return 1;
1440 }
1441
1442 apk_file = argv[file_arg];
1443
1444 if (file_arg != argc - 1) {
1445 verification_file = argv[file_arg + 1];
1446 }
1447
1448 if (check_file(apk_file) || check_file(verification_file)) {
1449 return 1;
1450 }
1451
1452 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1453 if (verification_file != NULL) {
1454 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1455
1456 if (!strcmp(apk_dest, verification_dest)) {
1457 fprintf(stderr, "APK and verification file can't have the same name\n");
1458 return 1;
1459 }
1460 }
1461
1462 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1463 if (err) {
1464 return err;
1465 } else {
1466 argv[file_arg] = apk_dest; /* destination name, not source location */
1467 }
1468
1469 if (verification_file != NULL) {
1470 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1471 if (err) {
1472 goto cleanup_apk;
1473 } else {
1474 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1475 }
1476 }
1477
1478 pm_command(transport, serial, argc, argv);
1479
1480 if (verification_file != NULL) {
1481 delete_file(transport, serial, verification_dest);
1482 }
1483
1484cleanup_apk:
1485 delete_file(transport, serial, apk_dest);
1486
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001487 return err;
1488}