blob: ffce883ccd033b3ba4bb4180d2d0fdf139ab6c41 [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 Tate1e9f2392011-12-08 19:04:34 -0800584static int mkdirs(char *path)
585{
586 int ret;
587 char *x = path + 1;
588
589 for(;;) {
590 x = adb_dirstart(x);
591 if(x == 0) return 0;
592 *x = 0;
593 ret = adb_mkdir(path, 0775);
594 *x = OS_PATH_SEPARATOR;
595 if((ret < 0) && (errno != EEXIST)) {
596 return ret;
597 }
598 x++;
599 }
600 return 0;
601}
602
Christopher Tate73779122011-04-21 12:53:28 -0700603static int backup(int argc, char** argv) {
604 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800605 char default_name[32];
606 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700607 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700608 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700609
Christopher Tatefba22972011-06-01 17:56:23 -0700610 /* find, extract, and use any -f argument */
611 for (i = 1; i < argc; i++) {
612 if (!strcmp("-f", argv[i])) {
613 if (i == argc-1) {
614 fprintf(stderr, "adb: -f passed with no filename\n");
615 return usage();
616 }
617 filename = argv[i+1];
618 for (j = i+2; j <= argc; ) {
619 argv[i++] = argv[j++];
620 }
621 argc -= 2;
622 argv[argc] = NULL;
623 }
Christopher Tate73779122011-04-21 12:53:28 -0700624 }
625
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700626 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
627 if (argc < 2) return usage();
628
Christopher Tate1e9f2392011-12-08 19:04:34 -0800629 adb_unlink(filename);
630 mkdirs((char *)filename);
631 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700632 if (outFd < 0) {
633 fprintf(stderr, "adb: unable to open file %s\n", filename);
634 return -1;
635 }
636
637 snprintf(buf, sizeof(buf), "backup");
638 for (argc--, argv++; argc; argc--, argv++) {
639 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
640 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
641 }
642
643 D("backup. filename=%s buf=%s\n", filename, buf);
644 fd = adb_connect(buf);
645 if (fd < 0) {
646 fprintf(stderr, "adb: unable to connect for backup\n");
647 adb_close(outFd);
648 return -1;
649 }
650
Christopher Tate9c829102012-01-06 15:43:03 -0800651 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700652 copy_to_file(fd, outFd);
653
654 adb_close(fd);
655 adb_close(outFd);
656 return 0;
657}
658
Christopher Tatecf5379b2011-05-17 15:52:54 -0700659static int restore(int argc, char** argv) {
660 const char* filename;
661 int fd, tarFd;
662
663 if (argc != 2) return usage();
664
665 filename = argv[1];
666 tarFd = adb_open(filename, O_RDONLY);
667 if (tarFd < 0) {
668 fprintf(stderr, "adb: unable to open file %s\n", filename);
669 return -1;
670 }
671
672 fd = adb_connect("restore:");
673 if (fd < 0) {
674 fprintf(stderr, "adb: unable to connect for backup\n");
675 adb_close(tarFd);
676 return -1;
677 }
678
Christopher Tate9c829102012-01-06 15:43:03 -0800679 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700680 copy_to_file(tarFd, fd);
681
682 adb_close(fd);
683 adb_close(tarFd);
684 return 0;
685}
686
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800687#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
688static int top_works(const char *top)
689{
690 if (top != NULL && adb_is_absolute_host_path(top)) {
691 char path_buf[PATH_MAX];
692 snprintf(path_buf, sizeof(path_buf),
693 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
694 return access(path_buf, F_OK) == 0;
695 }
696 return 0;
697}
698
699static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
700{
701 strcpy(path_buf, indir);
702 while (1) {
703 if (top_works(path_buf)) {
704 return path_buf;
705 }
706 char *s = adb_dirstop(path_buf);
707 if (s != NULL) {
708 *s = '\0';
709 } else {
710 path_buf[0] = '\0';
711 return NULL;
712 }
713 }
714}
715
716static char *find_top(char path_buf[PATH_MAX])
717{
718 char *top = getenv("ANDROID_BUILD_TOP");
719 if (top != NULL && top[0] != '\0') {
720 if (!top_works(top)) {
721 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
722 return NULL;
723 }
724 } else {
725 top = getenv("TOP");
726 if (top != NULL && top[0] != '\0') {
727 if (!top_works(top)) {
728 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
729 return NULL;
730 }
731 } else {
732 top = NULL;
733 }
734 }
735
736 if (top != NULL) {
737 /* The environment pointed to a top directory that works.
738 */
739 strcpy(path_buf, top);
740 return path_buf;
741 }
742
743 /* The environment didn't help. Walk up the tree from the CWD
744 * to see if we can find the top.
745 */
746 char dir[PATH_MAX];
747 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
748 if (top == NULL) {
749 /* If the CWD isn't under a good-looking top, see if the
750 * executable is.
751 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100752 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800753 top = find_top_from(dir, path_buf);
754 }
755 return top;
756}
757
758/* <hint> may be:
759 * - A simple product name
760 * e.g., "sooner"
761TODO: debug? sooner-debug, sooner:debug?
762 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
763 * e.g., "out/target/product/sooner"
764 * - An absolute path to the PRODUCT_OUT dir
765 * e.g., "/src/device/out/target/product/sooner"
766 *
767 * Given <hint>, try to construct an absolute path to the
768 * ANDROID_PRODUCT_OUT dir.
769 */
770static const char *find_product_out_path(const char *hint)
771{
772 static char path_buf[PATH_MAX];
773
774 if (hint == NULL || hint[0] == '\0') {
775 return NULL;
776 }
777
778 /* If it's already absolute, don't bother doing any work.
779 */
780 if (adb_is_absolute_host_path(hint)) {
781 strcpy(path_buf, hint);
782 return path_buf;
783 }
784
785 /* If there are any slashes in it, assume it's a relative path;
786 * make it absolute.
787 */
788 if (adb_dirstart(hint) != NULL) {
789 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
790 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
791 return NULL;
792 }
793 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
794 fprintf(stderr, "adb: Couldn't assemble path\n");
795 return NULL;
796 }
797 strcat(path_buf, OS_PATH_SEPARATOR_STR);
798 strcat(path_buf, hint);
799 return path_buf;
800 }
801
802 /* It's a string without any slashes. Try to do something with it.
803 *
804 * Try to find the root of the build tree, and build a PRODUCT_OUT
805 * path from there.
806 */
807 char top_buf[PATH_MAX];
808 const char *top = find_top(top_buf);
809 if (top == NULL) {
810 fprintf(stderr, "adb: Couldn't find top of build tree\n");
811 return NULL;
812 }
813//TODO: if we have a way to indicate debug, look in out/debug/target/...
814 snprintf(path_buf, sizeof(path_buf),
815 "%s" OS_PATH_SEPARATOR_STR
816 "out" OS_PATH_SEPARATOR_STR
817 "target" OS_PATH_SEPARATOR_STR
818 "product" OS_PATH_SEPARATOR_STR
819 "%s", top_buf, hint);
820 if (access(path_buf, F_OK) < 0) {
821 fprintf(stderr, "adb: Couldn't find a product dir "
822 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
823 return NULL;
824 }
825 return path_buf;
826}
827
828int adb_commandline(int argc, char **argv)
829{
830 char buf[4096];
831 int no_daemon = 0;
832 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100833 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800834 int persist = 0;
835 int r;
836 int quote;
837 transport_type ttype = kTransportAny;
838 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100839 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800840
841 /* If defined, this should be an absolute path to
842 * the directory containing all of the various system images
843 * for a particular product. If not defined, and the adb
844 * command requires this information, then the user must
845 * specify the path using "-p".
846 */
847 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
848 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
849 gProductOutPath = NULL;
850 }
851 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
852
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700853 serial = getenv("ANDROID_SERIAL");
854
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100855 /* Validate and assign the server port */
856 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
857 int server_port = DEFAULT_ADB_PORT;
858 if (server_port_str && strlen(server_port_str) > 0) {
859 server_port = (int) strtol(server_port_str, NULL, 0);
860 if (server_port <= 0) {
861 fprintf(stderr,
862 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
863 server_port_str);
864 return usage();
865 }
866 }
867
868 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800869 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100870 if(!strcmp(argv[0],"server")) {
871 is_server = 1;
872 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800873 no_daemon = 1;
874 } else if (!strcmp(argv[0], "fork-server")) {
875 /* this is a special flag used only when the ADB client launches the ADB Server */
876 is_daemon = 1;
877 } else if(!strcmp(argv[0],"persist")) {
878 persist = 1;
879 } else if(!strncmp(argv[0], "-p", 2)) {
880 const char *product = NULL;
881 if (argv[0][2] == '\0') {
882 if (argc < 2) return usage();
883 product = argv[1];
884 argc--;
885 argv++;
886 } else {
887 product = argv[1] + 2;
888 }
889 gProductOutPath = find_product_out_path(product);
890 if (gProductOutPath == NULL) {
891 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
892 product);
893 return usage();
894 }
895 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
896 if (isdigit(argv[0][2])) {
897 serial = argv[0] + 2;
898 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100899 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800900 serial = argv[1];
901 argc--;
902 argv++;
903 }
904 } else if (!strcmp(argv[0],"-d")) {
905 ttype = kTransportUsb;
906 } else if (!strcmp(argv[0],"-e")) {
907 ttype = kTransportLocal;
908 } else {
909 /* out of recognized modifiers and flags */
910 break;
911 }
912 argc--;
913 argv++;
914 }
915
916 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100917 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800918
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100919 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800920 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100921 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800922 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100923 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800924 }
925 if(r) {
926 fprintf(stderr,"* could not start server *\n");
927 }
928 return r;
929 }
930
931top:
932 if(argc == 0) {
933 return usage();
934 }
935
936 /* adb_connect() commands */
937
938 if(!strcmp(argv[0], "devices")) {
939 char *tmp;
940 snprintf(buf, sizeof buf, "host:%s", argv[0]);
941 tmp = adb_query(buf);
942 if(tmp) {
943 printf("List of devices attached \n");
944 printf("%s\n", tmp);
945 return 0;
946 } else {
947 return 1;
948 }
949 }
950
Mike Lockwood01c2c302010-05-24 10:44:35 -0400951 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -0700952 char *tmp;
953 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -0400954 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -0700955 return 1;
956 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400957 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
958 tmp = adb_query(buf);
959 if(tmp) {
960 printf("%s\n", tmp);
961 return 0;
962 } else {
963 return 1;
964 }
965 }
966
967 if(!strcmp(argv[0], "disconnect")) {
968 char *tmp;
969 if (argc > 2) {
970 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
971 return 1;
972 }
973 if (argc == 2) {
974 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
975 } else {
976 snprintf(buf, sizeof buf, "host:disconnect:");
977 }
Mike Lockwood26b88e32009-08-24 15:58:40 -0700978 tmp = adb_query(buf);
979 if(tmp) {
980 printf("%s\n", tmp);
981 return 0;
982 } else {
983 return 1;
984 }
985 }
986
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800987 if (!strcmp(argv[0], "emu")) {
988 return adb_send_emulator_command(argc, argv);
989 }
990
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400991 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800992 int r;
993 int fd;
994
Daniel Sandlerd9bc2372010-08-19 01:10:18 -0400995 char h = (argv[0][0] == 'h');
996
997 if (h) {
998 printf("\x1b[41;33m");
999 fflush(stdout);
1000 }
1001
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001002 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001003 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001004 r = interactive_shell();
1005 if (h) {
1006 printf("\x1b[0m");
1007 fflush(stdout);
1008 }
1009 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001010 }
1011
1012 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1013 argc -= 2;
1014 argv += 2;
1015 while(argc-- > 0) {
1016 strcat(buf, " ");
1017
1018 /* quote empty strings and strings with spaces */
1019 quote = (**argv == 0 || strchr(*argv, ' '));
1020 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001021 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001022 strcat(buf, *argv++);
1023 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001024 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001025 }
1026
1027 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001028 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001029 fd = adb_connect(buf);
1030 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001031 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001032 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001033 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001034 adb_close(fd);
1035 r = 0;
1036 } else {
1037 fprintf(stderr,"error: %s\n", adb_error());
1038 r = -1;
1039 }
1040
1041 if(persist) {
1042 fprintf(stderr,"\n- waiting for device -\n");
1043 adb_sleep_ms(1000);
1044 do_cmd(ttype, serial, "wait-for-device", 0);
1045 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001046 if (h) {
1047 printf("\x1b[0m");
1048 fflush(stdout);
1049 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001050 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001051 return r;
1052 }
1053 }
1054 }
1055
1056 if(!strcmp(argv[0], "kill-server")) {
1057 int fd;
1058 fd = _adb_connect("host:kill");
1059 if(fd == -1) {
1060 fprintf(stderr,"* server not running *\n");
1061 return 1;
1062 }
1063 return 0;
1064 }
1065
Mike Lockwood26b88e32009-08-24 15:58:40 -07001066 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001067 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001068 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001069 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001070 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001071 if (!strcmp(argv[0], "reboot-bootloader"))
1072 snprintf(command, sizeof(command), "reboot:bootloader");
1073 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001074 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001075 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001076 snprintf(command, sizeof(command), "%s:", argv[0]);
1077 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001078 if(fd >= 0) {
1079 read_and_dump(fd);
1080 adb_close(fd);
1081 return 0;
1082 }
1083 fprintf(stderr,"error: %s\n", adb_error());
1084 return 1;
1085 }
1086
Mike Lockwood78589f32009-09-03 14:54:58 -04001087 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001088 if (argc != 1) return usage();
1089 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001090 return 0;
1091 }
1092
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001093 /* adb_command() wrapper commands */
1094
1095 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1096 char* service = argv[0];
1097 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1098 if (ttype == kTransportUsb) {
1099 service = "wait-for-usb";
1100 } else if (ttype == kTransportLocal) {
1101 service = "wait-for-local";
1102 } else {
1103 service = "wait-for-any";
1104 }
1105 }
1106
1107 format_host_command(buf, sizeof buf, service, ttype, serial);
1108
1109 if (adb_command(buf)) {
1110 D("failure: %s *\n",adb_error());
1111 fprintf(stderr,"error: %s\n", adb_error());
1112 return 1;
1113 }
1114
1115 /* Allow a command to be run after wait-for-device,
1116 * e.g. 'adb wait-for-device shell'.
1117 */
1118 if(argc > 1) {
1119 argc--;
1120 argv++;
1121 goto top;
1122 }
1123 return 0;
1124 }
1125
1126 if(!strcmp(argv[0], "forward")) {
1127 if(argc != 3) return usage();
1128 if (serial) {
Mike Lockwood47b41622009-11-28 12:46:13 -05001129 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1130 } else if (ttype == kTransportUsb) {
1131 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1132 } else if (ttype == kTransportLocal) {
1133 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001134 } else {
Mike Lockwood47b41622009-11-28 12:46:13 -05001135 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001136 }
1137 if(adb_command(buf)) {
1138 fprintf(stderr,"error: %s\n", adb_error());
1139 return 1;
1140 }
1141 return 0;
1142 }
1143
1144 /* do_sync_*() commands */
1145
1146 if(!strcmp(argv[0], "ls")) {
1147 if(argc != 2) return usage();
1148 return do_sync_ls(argv[1]);
1149 }
1150
1151 if(!strcmp(argv[0], "push")) {
1152 if(argc != 3) return usage();
1153 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1154 }
1155
1156 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001157 if (argc == 2) {
1158 return do_sync_pull(argv[1], ".");
1159 } else if (argc == 3) {
1160 return do_sync_pull(argv[1], argv[2]);
1161 } else {
1162 return usage();
1163 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001164 }
1165
1166 if(!strcmp(argv[0], "install")) {
1167 if (argc < 2) return usage();
1168 return install_app(ttype, serial, argc, argv);
1169 }
1170
1171 if(!strcmp(argv[0], "uninstall")) {
1172 if (argc < 2) return usage();
1173 return uninstall_app(ttype, serial, argc, argv);
1174 }
1175
1176 if(!strcmp(argv[0], "sync")) {
1177 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001178 int listonly = 0;
1179
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001180 int ret;
1181 if(argc < 2) {
1182 /* No local path was specified. */
1183 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001184 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1185 listonly = 1;
1186 if (argc == 3) {
1187 srcarg = argv[2];
1188 } else {
1189 srcarg = NULL;
1190 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001191 } else if(argc == 2) {
1192 /* A local path or "android"/"data" arg was specified. */
1193 srcarg = argv[1];
1194 } else {
1195 return usage();
1196 }
1197 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1198 if(ret != 0) return usage();
1199
1200 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001201 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001202 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001203 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001204
1205 free(android_srcpath);
1206 free(data_srcpath);
1207 return ret;
1208 }
1209
1210 /* passthrough commands */
1211
1212 if(!strcmp(argv[0],"get-state") ||
1213 !strcmp(argv[0],"get-serialno"))
1214 {
1215 char *tmp;
1216
1217 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1218 tmp = adb_query(buf);
1219 if(tmp) {
1220 printf("%s\n", tmp);
1221 return 0;
1222 } else {
1223 return 1;
1224 }
1225 }
1226
1227 /* other commands */
1228
1229 if(!strcmp(argv[0],"status-window")) {
1230 status_window(ttype, serial);
1231 return 0;
1232 }
1233
Christopher Tate7b9b5162011-11-30 13:00:33 -08001234 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001235 return logcat(ttype, serial, argc, argv);
1236 }
1237
1238 if(!strcmp(argv[0],"ppp")) {
1239 return ppp(argc, argv);
1240 }
1241
1242 if (!strcmp(argv[0], "start-server")) {
1243 return adb_connect("host:start-server");
1244 }
1245
Christopher Tate73779122011-04-21 12:53:28 -07001246 if (!strcmp(argv[0], "backup")) {
1247 return backup(argc, argv);
1248 }
1249
Christopher Tatecf5379b2011-05-17 15:52:54 -07001250 if (!strcmp(argv[0], "restore")) {
1251 return restore(argc, argv);
1252 }
1253
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001254 if (!strcmp(argv[0], "jdwp")) {
1255 int fd = adb_connect("jdwp");
1256 if (fd >= 0) {
1257 read_and_dump(fd);
1258 adb_close(fd);
1259 return 0;
1260 } else {
1261 fprintf(stderr, "error: %s\n", adb_error());
1262 return -1;
1263 }
1264 }
1265
1266 /* "adb /?" is a common idiom under Windows */
1267 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1268 help();
1269 return 0;
1270 }
1271
1272 if(!strcmp(argv[0], "version")) {
1273 version(stdout);
1274 return 0;
1275 }
1276
1277 usage();
1278 return 1;
1279}
1280
1281static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1282{
1283 char *argv[16];
1284 int argc;
1285 va_list ap;
1286
1287 va_start(ap, cmd);
1288 argc = 0;
1289
1290 if (serial) {
1291 argv[argc++] = "-s";
1292 argv[argc++] = serial;
1293 } else if (ttype == kTransportUsb) {
1294 argv[argc++] = "-d";
1295 } else if (ttype == kTransportLocal) {
1296 argv[argc++] = "-e";
1297 }
1298
1299 argv[argc++] = cmd;
1300 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1301 va_end(ap);
1302
1303#if 0
1304 int n;
1305 fprintf(stderr,"argc = %d\n",argc);
1306 for(n = 0; n < argc; n++) {
1307 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1308 }
1309#endif
1310
1311 return adb_commandline(argc, argv);
1312}
1313
1314int find_sync_dirs(const char *srcarg,
1315 char **android_srcdir_out, char **data_srcdir_out)
1316{
1317 char *android_srcdir, *data_srcdir;
1318
1319 if(srcarg == NULL) {
1320 android_srcdir = product_file("system");
1321 data_srcdir = product_file("data");
1322 } else {
1323 /* srcarg may be "data", "system" or NULL.
1324 * if srcarg is NULL, then both data and system are synced
1325 */
1326 if(strcmp(srcarg, "system") == 0) {
1327 android_srcdir = product_file("system");
1328 data_srcdir = NULL;
1329 } else if(strcmp(srcarg, "data") == 0) {
1330 android_srcdir = NULL;
1331 data_srcdir = product_file("data");
1332 } else {
1333 /* It's not "system" or "data".
1334 */
1335 return 1;
1336 }
1337 }
1338
1339 if(android_srcdir_out != NULL)
1340 *android_srcdir_out = android_srcdir;
1341 else
1342 free(android_srcdir);
1343
1344 if(data_srcdir_out != NULL)
1345 *data_srcdir_out = data_srcdir;
1346 else
1347 free(data_srcdir);
1348
1349 return 0;
1350}
1351
1352static int pm_command(transport_type transport, char* serial,
1353 int argc, char** argv)
1354{
1355 char buf[4096];
1356
1357 snprintf(buf, sizeof(buf), "shell:pm");
1358
1359 while(argc-- > 0) {
1360 char *quoted;
1361
1362 quoted = dupAndQuote(*argv++);
1363
1364 strncat(buf, " ", sizeof(buf)-1);
1365 strncat(buf, quoted, sizeof(buf)-1);
1366 free(quoted);
1367 }
1368
1369 send_shellcommand(transport, serial, buf);
1370 return 0;
1371}
1372
1373int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1374{
1375 /* if the user choose the -k option, we refuse to do it until devices are
1376 out with the option to uninstall the remaining data somehow (adb/ui) */
1377 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1378 {
1379 printf(
1380 "The -k option uninstalls the application while retaining the data/cache.\n"
1381 "At the moment, there is no way to remove the remaining data.\n"
1382 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1383 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1384 return -1;
1385 }
1386
1387 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1388 return pm_command(transport, serial, argc, argv);
1389}
1390
1391static int delete_file(transport_type transport, char* serial, char* filename)
1392{
1393 char buf[4096];
1394 char* quoted;
1395
1396 snprintf(buf, sizeof(buf), "shell:rm ");
1397 quoted = dupAndQuote(filename);
1398 strncat(buf, quoted, sizeof(buf)-1);
1399 free(quoted);
1400
1401 send_shellcommand(transport, serial, buf);
1402 return 0;
1403}
1404
Kenny Root3802c992011-08-05 11:19:45 -07001405static const char* get_basename(const char* filename)
1406{
1407 const char* basename = adb_dirstop(filename);
1408 if (basename) {
1409 basename++;
1410 return basename;
1411 } else {
1412 return filename;
1413 }
1414}
1415
1416static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001417{
1418 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001419
Kenny Root3802c992011-08-05 11:19:45 -07001420 if (filename == NULL) {
1421 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001422 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001423
Kenny Root3802c992011-08-05 11:19:45 -07001424 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001425 fprintf(stderr, "can't find '%s' to install\n", filename);
1426 return 1;
1427 }
Kenny Root3802c992011-08-05 11:19:45 -07001428
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001429 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001430 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001431 return 1;
1432 }
1433
Kenny Root3802c992011-08-05 11:19:45 -07001434 return 0;
1435}
1436
1437int install_app(transport_type transport, char* serial, int argc, char** argv)
1438{
1439 static const char *const DATA_DEST = "/data/local/tmp/%s";
1440 static const char *const SD_DEST = "/sdcard/tmp/%s";
1441 const char* where = DATA_DEST;
1442 char apk_dest[PATH_MAX];
1443 char verification_dest[PATH_MAX];
1444 char* apk_file;
1445 char* verification_file = NULL;
1446 int file_arg = -1;
1447 int err;
1448 int i;
1449
1450 for (i = 1; i < argc; i++) {
1451 if (*argv[i] != '-') {
1452 file_arg = i;
1453 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001454 } else if (!strcmp(argv[i], "-i")) {
1455 // Skip the installer package name.
1456 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001457 } else if (!strcmp(argv[i], "-s")) {
1458 where = SD_DEST;
1459 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001460 }
1461
Kenny Root3802c992011-08-05 11:19:45 -07001462 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001463 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001464 return 1;
1465 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001466 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001467 return 1;
1468 }
1469
1470 apk_file = argv[file_arg];
1471
1472 if (file_arg != argc - 1) {
1473 verification_file = argv[file_arg + 1];
1474 }
1475
1476 if (check_file(apk_file) || check_file(verification_file)) {
1477 return 1;
1478 }
1479
1480 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1481 if (verification_file != NULL) {
1482 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1483
1484 if (!strcmp(apk_dest, verification_dest)) {
1485 fprintf(stderr, "APK and verification file can't have the same name\n");
1486 return 1;
1487 }
1488 }
1489
1490 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1491 if (err) {
1492 return err;
1493 } else {
1494 argv[file_arg] = apk_dest; /* destination name, not source location */
1495 }
1496
1497 if (verification_file != NULL) {
1498 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1499 if (err) {
1500 goto cleanup_apk;
1501 } else {
1502 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1503 }
1504 }
1505
1506 pm_command(transport, serial, argc, argv);
1507
1508 if (verification_file != NULL) {
1509 delete_file(transport, serial, verification_dest);
1510 }
1511
1512cleanup_apk:
1513 delete_file(transport, serial, apk_dest);
1514
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001515 return err;
1516}