blob: a7f681600fde2ad34ed7109f8f0760688f8ddca5 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov31664102009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-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 Pellydb449262009-05-07 12:48:03 -070088 " the given serial number. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Projectdd7bc332009-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 Lockwoodcbbe79a2010-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-Fischer6715a432011-04-26 12:46:05 +0200101 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400102 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 "\n"
104 "device commands:\n"
105 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato00c0eea2010-01-05 13:42:25 -0800106 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600108 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-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 Lockwood0ef3fd02010-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 Projectdd7bc332009-03-03 19:32:55 -0800124 " ('-l' means forward-lock the app)\n"
125 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500126 " ('-s' means install on SD card instead of internal storage)\n"
The Android Open Source Projectdd7bc332009-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 Tate56885092011-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 Tated2f54152011-04-21 12:53:28 -0700136 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700137 " in the archive; the default is noapk.)\n"
Christopher Tated2f54152011-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 Tate56885092011-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 Tated2f54152011-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 Tate56885092011-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 Tated2f54152011-04-21 12:53:28 -0700148 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700149 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700150 "\n"
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-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 Lockwoodee156622009-08-04 20:37:51 -0400162 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800163 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700164 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800165 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700166 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 "\n"
168 "networking:\n"
169 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500170 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-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"
Timcd643152010-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 Projectdd7bc332009-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 Abgrall408fa572011-03-16 15:57:42 -0700229 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700231 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-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 Lockwooddd6b36e2009-09-22 01:18:40 -0400240 fwrite(buf, 1, len, stdout);
241 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800242 }
243}
244
Christopher Tated2f54152011-04-21 12:53:28 -0700245static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700246 const size_t BUFSIZE = 32 * 1024;
247 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700248 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700249 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700250
251 D("copy_to_file(%d -> %d)\n", inFd, outFd);
252 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700253 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700254 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700255 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700256 break;
257 }
258 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700259 if (errno == EINTR) {
260 D("copy_to_file() : EINTR, retrying\n");
261 continue;
262 }
Christopher Tated2f54152011-04-21 12:53:28 -0700263 D("copy_to_file() : error %d\n", errno);
264 break;
265 }
266 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700267 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700268 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700269 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700270 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700271}
272
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-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 Projectdd7bc332009-03-03 19:32:55 -0800285 for(;;) {
286 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700287 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 if(r == 0) break;
291 if(r < 0) {
292 if(errno == EINTR) continue;
293 break;
294 }
Mike Lockwood67d53582010-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 Projectdd7bc332009-03-03 19:32:55 -0800311#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400312 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400314 default:
315 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800316 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800317 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800318 r = adb_write(fd, buf, r);
319 if(r <= 0) {
320 break;
321 }
322 }
The Android Open Source Projectdd7bc332009-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 Tateb1dfffe2011-12-08 19:04:34 -0800580static int mkdirs(char *path)
581{
582 int ret;
583 char *x = path + 1;
584
585 for(;;) {
586 x = adb_dirstart(x);
587 if(x == 0) return 0;
588 *x = 0;
589 ret = adb_mkdir(path, 0775);
590 *x = OS_PATH_SEPARATOR;
591 if((ret < 0) && (errno != EEXIST)) {
592 return ret;
593 }
594 x++;
595 }
596 return 0;
597}
598
Christopher Tated2f54152011-04-21 12:53:28 -0700599static int backup(int argc, char** argv) {
600 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800601 char default_name[32];
602 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700603 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700604 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700605
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700606 /* find, extract, and use any -f argument */
607 for (i = 1; i < argc; i++) {
608 if (!strcmp("-f", argv[i])) {
609 if (i == argc-1) {
610 fprintf(stderr, "adb: -f passed with no filename\n");
611 return usage();
612 }
613 filename = argv[i+1];
614 for (j = i+2; j <= argc; ) {
615 argv[i++] = argv[j++];
616 }
617 argc -= 2;
618 argv[argc] = NULL;
619 }
Christopher Tated2f54152011-04-21 12:53:28 -0700620 }
621
Christopher Tatebb86bc52011-08-22 17:12:08 -0700622 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
623 if (argc < 2) return usage();
624
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800625 adb_unlink(filename);
626 mkdirs((char *)filename);
627 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700628 if (outFd < 0) {
629 fprintf(stderr, "adb: unable to open file %s\n", filename);
630 return -1;
631 }
632
633 snprintf(buf, sizeof(buf), "backup");
634 for (argc--, argv++; argc; argc--, argv++) {
635 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
636 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
637 }
638
639 D("backup. filename=%s buf=%s\n", filename, buf);
640 fd = adb_connect(buf);
641 if (fd < 0) {
642 fprintf(stderr, "adb: unable to connect for backup\n");
643 adb_close(outFd);
644 return -1;
645 }
646
647 copy_to_file(fd, outFd);
648
649 adb_close(fd);
650 adb_close(outFd);
651 return 0;
652}
653
Christopher Tate702967a2011-05-17 15:52:54 -0700654static int restore(int argc, char** argv) {
655 const char* filename;
656 int fd, tarFd;
657
658 if (argc != 2) return usage();
659
660 filename = argv[1];
661 tarFd = adb_open(filename, O_RDONLY);
662 if (tarFd < 0) {
663 fprintf(stderr, "adb: unable to open file %s\n", filename);
664 return -1;
665 }
666
667 fd = adb_connect("restore:");
668 if (fd < 0) {
669 fprintf(stderr, "adb: unable to connect for backup\n");
670 adb_close(tarFd);
671 return -1;
672 }
673
674 copy_to_file(tarFd, fd);
675
676 adb_close(fd);
677 adb_close(tarFd);
678 return 0;
679}
680
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800681#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
682static int top_works(const char *top)
683{
684 if (top != NULL && adb_is_absolute_host_path(top)) {
685 char path_buf[PATH_MAX];
686 snprintf(path_buf, sizeof(path_buf),
687 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
688 return access(path_buf, F_OK) == 0;
689 }
690 return 0;
691}
692
693static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
694{
695 strcpy(path_buf, indir);
696 while (1) {
697 if (top_works(path_buf)) {
698 return path_buf;
699 }
700 char *s = adb_dirstop(path_buf);
701 if (s != NULL) {
702 *s = '\0';
703 } else {
704 path_buf[0] = '\0';
705 return NULL;
706 }
707 }
708}
709
710static char *find_top(char path_buf[PATH_MAX])
711{
712 char *top = getenv("ANDROID_BUILD_TOP");
713 if (top != NULL && top[0] != '\0') {
714 if (!top_works(top)) {
715 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
716 return NULL;
717 }
718 } else {
719 top = getenv("TOP");
720 if (top != NULL && top[0] != '\0') {
721 if (!top_works(top)) {
722 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
723 return NULL;
724 }
725 } else {
726 top = NULL;
727 }
728 }
729
730 if (top != NULL) {
731 /* The environment pointed to a top directory that works.
732 */
733 strcpy(path_buf, top);
734 return path_buf;
735 }
736
737 /* The environment didn't help. Walk up the tree from the CWD
738 * to see if we can find the top.
739 */
740 char dir[PATH_MAX];
741 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
742 if (top == NULL) {
743 /* If the CWD isn't under a good-looking top, see if the
744 * executable is.
745 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100746 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800747 top = find_top_from(dir, path_buf);
748 }
749 return top;
750}
751
752/* <hint> may be:
753 * - A simple product name
754 * e.g., "sooner"
755TODO: debug? sooner-debug, sooner:debug?
756 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
757 * e.g., "out/target/product/sooner"
758 * - An absolute path to the PRODUCT_OUT dir
759 * e.g., "/src/device/out/target/product/sooner"
760 *
761 * Given <hint>, try to construct an absolute path to the
762 * ANDROID_PRODUCT_OUT dir.
763 */
764static const char *find_product_out_path(const char *hint)
765{
766 static char path_buf[PATH_MAX];
767
768 if (hint == NULL || hint[0] == '\0') {
769 return NULL;
770 }
771
772 /* If it's already absolute, don't bother doing any work.
773 */
774 if (adb_is_absolute_host_path(hint)) {
775 strcpy(path_buf, hint);
776 return path_buf;
777 }
778
779 /* If there are any slashes in it, assume it's a relative path;
780 * make it absolute.
781 */
782 if (adb_dirstart(hint) != NULL) {
783 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
784 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
785 return NULL;
786 }
787 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
788 fprintf(stderr, "adb: Couldn't assemble path\n");
789 return NULL;
790 }
791 strcat(path_buf, OS_PATH_SEPARATOR_STR);
792 strcat(path_buf, hint);
793 return path_buf;
794 }
795
796 /* It's a string without any slashes. Try to do something with it.
797 *
798 * Try to find the root of the build tree, and build a PRODUCT_OUT
799 * path from there.
800 */
801 char top_buf[PATH_MAX];
802 const char *top = find_top(top_buf);
803 if (top == NULL) {
804 fprintf(stderr, "adb: Couldn't find top of build tree\n");
805 return NULL;
806 }
807//TODO: if we have a way to indicate debug, look in out/debug/target/...
808 snprintf(path_buf, sizeof(path_buf),
809 "%s" OS_PATH_SEPARATOR_STR
810 "out" OS_PATH_SEPARATOR_STR
811 "target" OS_PATH_SEPARATOR_STR
812 "product" OS_PATH_SEPARATOR_STR
813 "%s", top_buf, hint);
814 if (access(path_buf, F_OK) < 0) {
815 fprintf(stderr, "adb: Couldn't find a product dir "
816 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
817 return NULL;
818 }
819 return path_buf;
820}
821
822int adb_commandline(int argc, char **argv)
823{
824 char buf[4096];
825 int no_daemon = 0;
826 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100827 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800828 int persist = 0;
829 int r;
830 int quote;
831 transport_type ttype = kTransportAny;
832 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100833 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800834
835 /* If defined, this should be an absolute path to
836 * the directory containing all of the various system images
837 * for a particular product. If not defined, and the adb
838 * command requires this information, then the user must
839 * specify the path using "-p".
840 */
841 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
842 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
843 gProductOutPath = NULL;
844 }
845 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
846
Nick Pellydb449262009-05-07 12:48:03 -0700847 serial = getenv("ANDROID_SERIAL");
848
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100849 /* Validate and assign the server port */
850 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
851 int server_port = DEFAULT_ADB_PORT;
852 if (server_port_str && strlen(server_port_str) > 0) {
853 server_port = (int) strtol(server_port_str, NULL, 0);
854 if (server_port <= 0) {
855 fprintf(stderr,
856 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
857 server_port_str);
858 return usage();
859 }
860 }
861
862 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800863 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100864 if(!strcmp(argv[0],"server")) {
865 is_server = 1;
866 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800867 no_daemon = 1;
868 } else if (!strcmp(argv[0], "fork-server")) {
869 /* this is a special flag used only when the ADB client launches the ADB Server */
870 is_daemon = 1;
871 } else if(!strcmp(argv[0],"persist")) {
872 persist = 1;
873 } else if(!strncmp(argv[0], "-p", 2)) {
874 const char *product = NULL;
875 if (argv[0][2] == '\0') {
876 if (argc < 2) return usage();
877 product = argv[1];
878 argc--;
879 argv++;
880 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -0700881 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800882 }
883 gProductOutPath = find_product_out_path(product);
884 if (gProductOutPath == NULL) {
885 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
886 product);
887 return usage();
888 }
889 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
890 if (isdigit(argv[0][2])) {
891 serial = argv[0] + 2;
892 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100893 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800894 serial = argv[1];
895 argc--;
896 argv++;
897 }
898 } else if (!strcmp(argv[0],"-d")) {
899 ttype = kTransportUsb;
900 } else if (!strcmp(argv[0],"-e")) {
901 ttype = kTransportLocal;
902 } else {
903 /* out of recognized modifiers and flags */
904 break;
905 }
906 argc--;
907 argv++;
908 }
909
910 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100911 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800912
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100913 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800914 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100915 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800916 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100917 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800918 }
919 if(r) {
920 fprintf(stderr,"* could not start server *\n");
921 }
922 return r;
923 }
924
925top:
926 if(argc == 0) {
927 return usage();
928 }
929
930 /* adb_connect() commands */
931
932 if(!strcmp(argv[0], "devices")) {
933 char *tmp;
934 snprintf(buf, sizeof buf, "host:%s", argv[0]);
935 tmp = adb_query(buf);
936 if(tmp) {
937 printf("List of devices attached \n");
938 printf("%s\n", tmp);
939 return 0;
940 } else {
941 return 1;
942 }
943 }
944
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400945 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700946 char *tmp;
947 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400948 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -0700949 return 1;
950 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400951 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
952 tmp = adb_query(buf);
953 if(tmp) {
954 printf("%s\n", tmp);
955 return 0;
956 } else {
957 return 1;
958 }
959 }
960
961 if(!strcmp(argv[0], "disconnect")) {
962 char *tmp;
963 if (argc > 2) {
964 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
965 return 1;
966 }
967 if (argc == 2) {
968 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
969 } else {
970 snprintf(buf, sizeof buf, "host:disconnect:");
971 }
Mike Lockwoodff196702009-08-24 15:58:40 -0700972 tmp = adb_query(buf);
973 if(tmp) {
974 printf("%s\n", tmp);
975 return 0;
976 } else {
977 return 1;
978 }
979 }
980
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800981 if (!strcmp(argv[0], "emu")) {
982 return adb_send_emulator_command(argc, argv);
983 }
984
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400985 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800986 int r;
987 int fd;
988
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400989 char h = (argv[0][0] == 'h');
990
991 if (h) {
992 printf("\x1b[41;33m");
993 fflush(stdout);
994 }
995
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -0700997 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400998 r = interactive_shell();
999 if (h) {
1000 printf("\x1b[0m");
1001 fflush(stdout);
1002 }
1003 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001004 }
1005
1006 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1007 argc -= 2;
1008 argv += 2;
1009 while(argc-- > 0) {
1010 strcat(buf, " ");
1011
1012 /* quote empty strings and strings with spaces */
1013 quote = (**argv == 0 || strchr(*argv, ' '));
1014 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001015 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001016 strcat(buf, *argv++);
1017 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001018 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001019 }
1020
1021 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001022 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 fd = adb_connect(buf);
1024 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001025 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001026 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001027 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 adb_close(fd);
1029 r = 0;
1030 } else {
1031 fprintf(stderr,"error: %s\n", adb_error());
1032 r = -1;
1033 }
1034
1035 if(persist) {
1036 fprintf(stderr,"\n- waiting for device -\n");
1037 adb_sleep_ms(1000);
1038 do_cmd(ttype, serial, "wait-for-device", 0);
1039 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001040 if (h) {
1041 printf("\x1b[0m");
1042 fflush(stdout);
1043 }
JP Abgrall408fa572011-03-16 15:57:42 -07001044 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001045 return r;
1046 }
1047 }
1048 }
1049
1050 if(!strcmp(argv[0], "kill-server")) {
1051 int fd;
1052 fd = _adb_connect("host:kill");
1053 if(fd == -1) {
1054 fprintf(stderr,"* server not running *\n");
1055 return 1;
1056 }
1057 return 0;
1058 }
1059
Mike Lockwoodff196702009-08-24 15:58:40 -07001060 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001061 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001062 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001063 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001064 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001065 if (!strcmp(argv[0], "reboot-bootloader"))
1066 snprintf(command, sizeof(command), "reboot:bootloader");
1067 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001068 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001069 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001070 snprintf(command, sizeof(command), "%s:", argv[0]);
1071 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001072 if(fd >= 0) {
1073 read_and_dump(fd);
1074 adb_close(fd);
1075 return 0;
1076 }
1077 fprintf(stderr,"error: %s\n", adb_error());
1078 return 1;
1079 }
1080
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001081 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001082 if (argc != 1) return usage();
1083 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001084 return 0;
1085 }
1086
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001087 /* adb_command() wrapper commands */
1088
1089 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1090 char* service = argv[0];
1091 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1092 if (ttype == kTransportUsb) {
1093 service = "wait-for-usb";
1094 } else if (ttype == kTransportLocal) {
1095 service = "wait-for-local";
1096 } else {
1097 service = "wait-for-any";
1098 }
1099 }
1100
1101 format_host_command(buf, sizeof buf, service, ttype, serial);
1102
1103 if (adb_command(buf)) {
1104 D("failure: %s *\n",adb_error());
1105 fprintf(stderr,"error: %s\n", adb_error());
1106 return 1;
1107 }
1108
1109 /* Allow a command to be run after wait-for-device,
1110 * e.g. 'adb wait-for-device shell'.
1111 */
1112 if(argc > 1) {
1113 argc--;
1114 argv++;
1115 goto top;
1116 }
1117 return 0;
1118 }
1119
1120 if(!strcmp(argv[0], "forward")) {
1121 if(argc != 3) return usage();
1122 if (serial) {
Mike Lockwood64e99542009-11-28 12:46:13 -05001123 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1124 } else if (ttype == kTransportUsb) {
1125 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1126 } else if (ttype == kTransportLocal) {
1127 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001128 } else {
Mike Lockwood64e99542009-11-28 12:46:13 -05001129 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001130 }
1131 if(adb_command(buf)) {
1132 fprintf(stderr,"error: %s\n", adb_error());
1133 return 1;
1134 }
1135 return 0;
1136 }
1137
1138 /* do_sync_*() commands */
1139
1140 if(!strcmp(argv[0], "ls")) {
1141 if(argc != 2) return usage();
1142 return do_sync_ls(argv[1]);
1143 }
1144
1145 if(!strcmp(argv[0], "push")) {
1146 if(argc != 3) return usage();
1147 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1148 }
1149
1150 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001151 if (argc == 2) {
1152 return do_sync_pull(argv[1], ".");
1153 } else if (argc == 3) {
1154 return do_sync_pull(argv[1], argv[2]);
1155 } else {
1156 return usage();
1157 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001158 }
1159
1160 if(!strcmp(argv[0], "install")) {
1161 if (argc < 2) return usage();
1162 return install_app(ttype, serial, argc, argv);
1163 }
1164
1165 if(!strcmp(argv[0], "uninstall")) {
1166 if (argc < 2) return usage();
1167 return uninstall_app(ttype, serial, argc, argv);
1168 }
1169
1170 if(!strcmp(argv[0], "sync")) {
1171 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001172 int listonly = 0;
1173
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001174 int ret;
1175 if(argc < 2) {
1176 /* No local path was specified. */
1177 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001178 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1179 listonly = 1;
1180 if (argc == 3) {
1181 srcarg = argv[2];
1182 } else {
1183 srcarg = NULL;
1184 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001185 } else if(argc == 2) {
1186 /* A local path or "android"/"data" arg was specified. */
1187 srcarg = argv[1];
1188 } else {
1189 return usage();
1190 }
1191 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1192 if(ret != 0) return usage();
1193
1194 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001195 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001196 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001197 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001198
1199 free(android_srcpath);
1200 free(data_srcpath);
1201 return ret;
1202 }
1203
1204 /* passthrough commands */
1205
1206 if(!strcmp(argv[0],"get-state") ||
1207 !strcmp(argv[0],"get-serialno"))
1208 {
1209 char *tmp;
1210
1211 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1212 tmp = adb_query(buf);
1213 if(tmp) {
1214 printf("%s\n", tmp);
1215 return 0;
1216 } else {
1217 return 1;
1218 }
1219 }
1220
1221 /* other commands */
1222
1223 if(!strcmp(argv[0],"status-window")) {
1224 status_window(ttype, serial);
1225 return 0;
1226 }
1227
1228 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1229 return logcat(ttype, serial, argc, argv);
1230 }
1231
1232 if(!strcmp(argv[0],"ppp")) {
1233 return ppp(argc, argv);
1234 }
1235
1236 if (!strcmp(argv[0], "start-server")) {
1237 return adb_connect("host:start-server");
1238 }
1239
Christopher Tated2f54152011-04-21 12:53:28 -07001240 if (!strcmp(argv[0], "backup")) {
1241 return backup(argc, argv);
1242 }
1243
Christopher Tate702967a2011-05-17 15:52:54 -07001244 if (!strcmp(argv[0], "restore")) {
1245 return restore(argc, argv);
1246 }
1247
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001248 if (!strcmp(argv[0], "jdwp")) {
1249 int fd = adb_connect("jdwp");
1250 if (fd >= 0) {
1251 read_and_dump(fd);
1252 adb_close(fd);
1253 return 0;
1254 } else {
1255 fprintf(stderr, "error: %s\n", adb_error());
1256 return -1;
1257 }
1258 }
1259
1260 /* "adb /?" is a common idiom under Windows */
1261 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1262 help();
1263 return 0;
1264 }
1265
1266 if(!strcmp(argv[0], "version")) {
1267 version(stdout);
1268 return 0;
1269 }
1270
1271 usage();
1272 return 1;
1273}
1274
1275static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1276{
1277 char *argv[16];
1278 int argc;
1279 va_list ap;
1280
1281 va_start(ap, cmd);
1282 argc = 0;
1283
1284 if (serial) {
1285 argv[argc++] = "-s";
1286 argv[argc++] = serial;
1287 } else if (ttype == kTransportUsb) {
1288 argv[argc++] = "-d";
1289 } else if (ttype == kTransportLocal) {
1290 argv[argc++] = "-e";
1291 }
1292
1293 argv[argc++] = cmd;
1294 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1295 va_end(ap);
1296
1297#if 0
1298 int n;
1299 fprintf(stderr,"argc = %d\n",argc);
1300 for(n = 0; n < argc; n++) {
1301 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1302 }
1303#endif
1304
1305 return adb_commandline(argc, argv);
1306}
1307
1308int find_sync_dirs(const char *srcarg,
1309 char **android_srcdir_out, char **data_srcdir_out)
1310{
1311 char *android_srcdir, *data_srcdir;
1312
1313 if(srcarg == NULL) {
1314 android_srcdir = product_file("system");
1315 data_srcdir = product_file("data");
1316 } else {
1317 /* srcarg may be "data", "system" or NULL.
1318 * if srcarg is NULL, then both data and system are synced
1319 */
1320 if(strcmp(srcarg, "system") == 0) {
1321 android_srcdir = product_file("system");
1322 data_srcdir = NULL;
1323 } else if(strcmp(srcarg, "data") == 0) {
1324 android_srcdir = NULL;
1325 data_srcdir = product_file("data");
1326 } else {
1327 /* It's not "system" or "data".
1328 */
1329 return 1;
1330 }
1331 }
1332
1333 if(android_srcdir_out != NULL)
1334 *android_srcdir_out = android_srcdir;
1335 else
1336 free(android_srcdir);
1337
1338 if(data_srcdir_out != NULL)
1339 *data_srcdir_out = data_srcdir;
1340 else
1341 free(data_srcdir);
1342
1343 return 0;
1344}
1345
1346static int pm_command(transport_type transport, char* serial,
1347 int argc, char** argv)
1348{
1349 char buf[4096];
1350
1351 snprintf(buf, sizeof(buf), "shell:pm");
1352
1353 while(argc-- > 0) {
1354 char *quoted;
1355
1356 quoted = dupAndQuote(*argv++);
1357
1358 strncat(buf, " ", sizeof(buf)-1);
1359 strncat(buf, quoted, sizeof(buf)-1);
1360 free(quoted);
1361 }
1362
1363 send_shellcommand(transport, serial, buf);
1364 return 0;
1365}
1366
1367int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1368{
1369 /* if the user choose the -k option, we refuse to do it until devices are
1370 out with the option to uninstall the remaining data somehow (adb/ui) */
1371 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1372 {
1373 printf(
1374 "The -k option uninstalls the application while retaining the data/cache.\n"
1375 "At the moment, there is no way to remove the remaining data.\n"
1376 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1377 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1378 return -1;
1379 }
1380
1381 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1382 return pm_command(transport, serial, argc, argv);
1383}
1384
1385static int delete_file(transport_type transport, char* serial, char* filename)
1386{
1387 char buf[4096];
1388 char* quoted;
1389
1390 snprintf(buf, sizeof(buf), "shell:rm ");
1391 quoted = dupAndQuote(filename);
1392 strncat(buf, quoted, sizeof(buf)-1);
1393 free(quoted);
1394
1395 send_shellcommand(transport, serial, buf);
1396 return 0;
1397}
1398
Kenny Root597ea5b2011-08-05 11:19:45 -07001399static const char* get_basename(const char* filename)
1400{
1401 const char* basename = adb_dirstop(filename);
1402 if (basename) {
1403 basename++;
1404 return basename;
1405 } else {
1406 return filename;
1407 }
1408}
1409
1410static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411{
1412 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001413
Kenny Root597ea5b2011-08-05 11:19:45 -07001414 if (filename == NULL) {
1415 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001416 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001417
Kenny Root597ea5b2011-08-05 11:19:45 -07001418 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001419 fprintf(stderr, "can't find '%s' to install\n", filename);
1420 return 1;
1421 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001422
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001424 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425 return 1;
1426 }
1427
Kenny Root597ea5b2011-08-05 11:19:45 -07001428 return 0;
1429}
1430
1431int install_app(transport_type transport, char* serial, int argc, char** argv)
1432{
1433 static const char *const DATA_DEST = "/data/local/tmp/%s";
1434 static const char *const SD_DEST = "/sdcard/tmp/%s";
1435 const char* where = DATA_DEST;
1436 char apk_dest[PATH_MAX];
1437 char verification_dest[PATH_MAX];
1438 char* apk_file;
1439 char* verification_file = NULL;
1440 int file_arg = -1;
1441 int err;
1442 int i;
1443
1444 for (i = 1; i < argc; i++) {
1445 if (*argv[i] != '-') {
1446 file_arg = i;
1447 break;
Kenny Roota031a912011-09-23 12:46:39 -07001448 } else if (!strcmp(argv[i], "-i")) {
1449 // Skip the installer package name.
1450 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001451 } else if (!strcmp(argv[i], "-s")) {
1452 where = SD_DEST;
1453 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001454 }
1455
Kenny Root597ea5b2011-08-05 11:19:45 -07001456 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001457 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001458 return 1;
1459 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001460 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001461 return 1;
1462 }
1463
1464 apk_file = argv[file_arg];
1465
1466 if (file_arg != argc - 1) {
1467 verification_file = argv[file_arg + 1];
1468 }
1469
1470 if (check_file(apk_file) || check_file(verification_file)) {
1471 return 1;
1472 }
1473
1474 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1475 if (verification_file != NULL) {
1476 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1477
1478 if (!strcmp(apk_dest, verification_dest)) {
1479 fprintf(stderr, "APK and verification file can't have the same name\n");
1480 return 1;
1481 }
1482 }
1483
1484 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1485 if (err) {
1486 return err;
1487 } else {
1488 argv[file_arg] = apk_dest; /* destination name, not source location */
1489 }
1490
1491 if (verification_file != NULL) {
1492 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1493 if (err) {
1494 goto cleanup_apk;
1495 } else {
1496 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1497 }
1498 }
1499
1500 pm_command(transport, serial, argc, argv);
1501
1502 if (verification_file != NULL) {
1503 delete_file(transport, serial, verification_dest);
1504 }
1505
1506cleanup_apk:
1507 delete_file(transport, serial, apk_dest);
1508
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001509 return err;
1510}