blob: 2de0516269c9d447c39bcded7308a3917b70b587 [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"
Scott Andersone109d262012-04-20 11:21:14 -070087 " -s <specific device> - directs command to the device or emulator with the given\n"
88 " serial number or device path. 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"
Scott Andersone109d262012-04-20 11:21:14 -070096 " devices [-l] - list all connected devices\n"
97 " ('-l' means list device paths)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040098 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
99 " Port 5555 is used by default if no port number is specified.\n"
100 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
101 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200102 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400103 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800104 "\n"
105 "device commands:\n"
106 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato00c0eea2010-01-05 13:42:25 -0800107 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800108 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600109 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800110 " (see 'adb help all')\n"
111 " adb shell - run remote shell interactively\n"
112 " adb shell <command> - run remote shell command\n"
113 " adb emu <command> - run emulator console command\n"
114 " adb logcat [ <filter-spec> ] - View device log\n"
115 " adb forward <local> <remote> - forward socket connections\n"
116 " forward specs are one of: \n"
117 " tcp:<port>\n"
118 " localabstract:<unix domain socket name>\n"
119 " localreserved:<unix domain socket name>\n"
120 " localfilesystem:<unix domain socket name>\n"
121 " dev:<character device name>\n"
122 " jdwp:<process pid> (remote only)\n"
123 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500124 " 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 -0800125 " ('-l' means forward-lock the app)\n"
126 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500127 " ('-s' means install on SD card instead of internal storage)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800128 " adb uninstall [-k] <package> - remove this app package from the device\n"
129 " ('-k' means keep the data and cache directories)\n"
130 " adb bugreport - return all information from the device\n"
131 " that should be included in a bug report.\n"
132 "\n"
Christopher Tate56885092011-10-03 18:27:01 -0700133 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
134 " - write an archive of the device's data to <file>.\n"
135 " If no -f option is supplied then the data is written\n"
136 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700137 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700138 " in the archive; the default is noapk.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700139 " (-shared|-noshared enable/disable backup of the device's\n"
140 " shared storage / SD card contents; the default is noshared.)\n"
141 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700142 " (-system|-nosystem toggles whether -all automatically includes\n"
143 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700144 " (<packages...> is the list of applications to be backed up. If\n"
145 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700146 " list is optional. Applications explicitly given on the\n"
147 " command line will be included even if -nosystem would\n"
148 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700149 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700150 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700151 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800152 " adb help - show this help message\n"
153 " adb version - show version num\n"
154 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800155 "scripting:\n"
156 " adb wait-for-device - block until device is online\n"
157 " adb start-server - ensure that there is a server running\n"
158 " adb kill-server - kill the server if it is running\n"
159 " adb get-state - prints: offline | bootloader | device\n"
160 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700161 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 " adb status-window - continuously print device status for a specified device\n"
163 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400164 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800165 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700166 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800167 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700168 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 "\n"
170 "networking:\n"
171 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500172 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800173 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
174 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
175 "\n"
176 "adb sync notes: adb sync [ <directory> ]\n"
177 " <localdir> can be interpreted in several ways:\n"
178 "\n"
179 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
180 "\n"
181 " - If it is \"system\" or \"data\", only the corresponding partition\n"
182 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000183 "\n"
184 "environmental variables:\n"
185 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
186 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
187 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
188 " 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 -0800189 );
190}
191
192int usage()
193{
194 help();
195 return 1;
196}
197
198#ifdef HAVE_TERMIO_H
199static struct termios tio_save;
200
201static void stdin_raw_init(int fd)
202{
203 struct termios tio;
204
205 if(tcgetattr(fd, &tio)) return;
206 if(tcgetattr(fd, &tio_save)) return;
207
208 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
209
210 /* no timeout but request at least one character per read */
211 tio.c_cc[VTIME] = 0;
212 tio.c_cc[VMIN] = 1;
213
214 tcsetattr(fd, TCSANOW, &tio);
215 tcflush(fd, TCIFLUSH);
216}
217
218static void stdin_raw_restore(int fd)
219{
220 tcsetattr(fd, TCSANOW, &tio_save);
221 tcflush(fd, TCIFLUSH);
222}
223#endif
224
225static void read_and_dump(int fd)
226{
227 char buf[4096];
228 int len;
229
230 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700231 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800232 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700233 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234 if(len == 0) {
235 break;
236 }
237
238 if(len < 0) {
239 if(errno == EINTR) continue;
240 break;
241 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400242 fwrite(buf, 1, len, stdout);
243 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244 }
245}
246
Christopher Tated2f54152011-04-21 12:53:28 -0700247static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700248 const size_t BUFSIZE = 32 * 1024;
249 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700250 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700251 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700252
253 D("copy_to_file(%d -> %d)\n", inFd, outFd);
254 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700255 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700256 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700257 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700258 break;
259 }
260 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700261 if (errno == EINTR) {
262 D("copy_to_file() : EINTR, retrying\n");
263 continue;
264 }
Christopher Tated2f54152011-04-21 12:53:28 -0700265 D("copy_to_file() : error %d\n", errno);
266 break;
267 }
268 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700269 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700270 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700271 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700272 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700273}
274
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800275static void *stdin_read_thread(void *x)
276{
277 int fd, fdi;
278 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800279 int r, n;
280 int state = 0;
281
282 int *fds = (int*) x;
283 fd = fds[0];
284 fdi = fds[1];
285 free(fds);
286
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800287 for(;;) {
288 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700291 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 if(r == 0) break;
293 if(r < 0) {
294 if(errno == EINTR) continue;
295 break;
296 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400297 for(n = 0; n < r; n++){
298 switch(buf[n]) {
299 case '\n':
300 state = 1;
301 break;
302 case '\r':
303 state = 1;
304 break;
305 case '~':
306 if(state == 1) state++;
307 break;
308 case '.':
309 if(state == 2) {
310 fprintf(stderr,"\n* disconnect *\n");
311#ifdef HAVE_TERMIO_H
312 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400314 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400316 default:
317 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800318 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800319 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800320 r = adb_write(fd, buf, r);
321 if(r <= 0) {
322 break;
323 }
324 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800325 return 0;
326}
327
328int interactive_shell(void)
329{
330 adb_thread_t thr;
331 int fdi, fd;
332 int *fds;
333
334 fd = adb_connect("shell:");
335 if(fd < 0) {
336 fprintf(stderr,"error: %s\n", adb_error());
337 return 1;
338 }
339 fdi = 0; //dup(0);
340
341 fds = malloc(sizeof(int) * 2);
342 fds[0] = fd;
343 fds[1] = fdi;
344
345#ifdef HAVE_TERMIO_H
346 stdin_raw_init(fdi);
347#endif
348 adb_thread_create(&thr, stdin_read_thread, fds);
349 read_and_dump(fd);
350#ifdef HAVE_TERMIO_H
351 stdin_raw_restore(fdi);
352#endif
353 return 0;
354}
355
356
357static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
358{
359 if (serial) {
360 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
361 } else {
362 const char* prefix = "host";
363 if (ttype == kTransportUsb)
364 prefix = "host-usb";
365 else if (ttype == kTransportLocal)
366 prefix = "host-local";
367
368 snprintf(buffer, buflen, "%s:%s", prefix, command);
369 }
370}
371
372static void status_window(transport_type ttype, const char* serial)
373{
374 char command[4096];
375 char *state = 0;
376 char *laststate = 0;
377
378 /* silence stderr */
379#ifdef _WIN32
380 /* XXX: TODO */
381#else
382 int fd;
383 fd = unix_open("/dev/null", O_WRONLY);
384 dup2(fd, 2);
385 adb_close(fd);
386#endif
387
388 format_host_command(command, sizeof command, "get-state", ttype, serial);
389
390 for(;;) {
391 adb_sleep_ms(250);
392
393 if(state) {
394 free(state);
395 state = 0;
396 }
397
398 state = adb_query(command);
399
400 if(state) {
401 if(laststate && !strcmp(state,laststate)){
402 continue;
403 } else {
404 if(laststate) free(laststate);
405 laststate = strdup(state);
406 }
407 }
408
409 printf("%c[2J%c[2H", 27, 27);
410 printf("Android Debug Bridge\n");
411 printf("State: %s\n", state ? state : "offline");
412 fflush(stdout);
413 }
414}
415
416/** duplicate string and quote all \ " ( ) chars + space character. */
417static char *
418dupAndQuote(const char *s)
419{
420 const char *ts;
421 size_t alloc_len;
422 char *ret;
423 char *dest;
424
425 ts = s;
426
427 alloc_len = 0;
428
429 for( ;*ts != '\0'; ts++) {
430 alloc_len++;
431 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
432 alloc_len++;
433 }
434 }
435
436 ret = (char *)malloc(alloc_len + 1);
437
438 ts = s;
439 dest = ret;
440
441 for ( ;*ts != '\0'; ts++) {
442 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
443 *dest++ = '\\';
444 }
445
446 *dest++ = *ts;
447 }
448
449 *dest++ = '\0';
450
451 return ret;
452}
453
454/**
455 * Run ppp in "notty" mode against a resource listed as the first parameter
456 * eg:
457 *
458 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
459 *
460 */
461int ppp(int argc, char **argv)
462{
463#ifdef HAVE_WIN32_PROC
464 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
465 return -1;
466#else
467 char *adb_service_name;
468 pid_t pid;
469 int fd;
470
471 if (argc < 2) {
472 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
473 argv[0]);
474
475 return 1;
476 }
477
478 adb_service_name = argv[1];
479
480 fd = adb_connect(adb_service_name);
481
482 if(fd < 0) {
483 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
484 adb_service_name, adb_error());
485 return 1;
486 }
487
488 pid = fork();
489
490 if (pid < 0) {
491 perror("from fork()");
492 return 1;
493 } else if (pid == 0) {
494 int err;
495 int i;
496 const char **ppp_args;
497
498 // copy args
499 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
500 ppp_args[0] = "pppd";
501 for (i = 2 ; i < argc ; i++) {
502 //argv[2] and beyond become ppp_args[1] and beyond
503 ppp_args[i - 1] = argv[i];
504 }
505 ppp_args[i-1] = NULL;
506
507 // child side
508
509 dup2(fd, STDIN_FILENO);
510 dup2(fd, STDOUT_FILENO);
511 adb_close(STDERR_FILENO);
512 adb_close(fd);
513
514 err = execvp("pppd", (char * const *)ppp_args);
515
516 if (err < 0) {
517 perror("execing pppd");
518 }
519 exit(-1);
520 } else {
521 // parent side
522
523 adb_close(fd);
524 return 0;
525 }
526#endif /* !HAVE_WIN32_PROC */
527}
528
529static int send_shellcommand(transport_type transport, char* serial, char* buf)
530{
531 int fd, ret;
532
533 for(;;) {
534 fd = adb_connect(buf);
535 if(fd >= 0)
536 break;
537 fprintf(stderr,"- waiting for device -\n");
538 adb_sleep_ms(1000);
539 do_cmd(transport, serial, "wait-for-device", 0);
540 }
541
542 read_and_dump(fd);
543 ret = adb_close(fd);
544 if (ret)
545 perror("close");
546
547 return ret;
548}
549
550static int logcat(transport_type transport, char* serial, int argc, char **argv)
551{
552 char buf[4096];
553
554 char *log_tags;
555 char *quoted_log_tags;
556
557 log_tags = getenv("ANDROID_LOG_TAGS");
558 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
559
560 snprintf(buf, sizeof(buf),
561 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
562 quoted_log_tags);
563
564 free(quoted_log_tags);
565
566 argc -= 1;
567 argv += 1;
568 while(argc-- > 0) {
569 char *quoted;
570
571 quoted = dupAndQuote (*argv++);
572
573 strncat(buf, " ", sizeof(buf)-1);
574 strncat(buf, quoted, sizeof(buf)-1);
575 free(quoted);
576 }
577
578 send_shellcommand(transport, serial, buf);
579 return 0;
580}
581
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800582static int mkdirs(char *path)
583{
584 int ret;
585 char *x = path + 1;
586
587 for(;;) {
588 x = adb_dirstart(x);
589 if(x == 0) return 0;
590 *x = 0;
591 ret = adb_mkdir(path, 0775);
592 *x = OS_PATH_SEPARATOR;
593 if((ret < 0) && (errno != EEXIST)) {
594 return ret;
595 }
596 x++;
597 }
598 return 0;
599}
600
Christopher Tated2f54152011-04-21 12:53:28 -0700601static int backup(int argc, char** argv) {
602 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800603 char default_name[32];
604 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700605 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700606 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700607
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700608 /* find, extract, and use any -f argument */
609 for (i = 1; i < argc; i++) {
610 if (!strcmp("-f", argv[i])) {
611 if (i == argc-1) {
612 fprintf(stderr, "adb: -f passed with no filename\n");
613 return usage();
614 }
615 filename = argv[i+1];
616 for (j = i+2; j <= argc; ) {
617 argv[i++] = argv[j++];
618 }
619 argc -= 2;
620 argv[argc] = NULL;
621 }
Christopher Tated2f54152011-04-21 12:53:28 -0700622 }
623
Christopher Tatebb86bc52011-08-22 17:12:08 -0700624 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
625 if (argc < 2) return usage();
626
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800627 adb_unlink(filename);
628 mkdirs((char *)filename);
629 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700630 if (outFd < 0) {
631 fprintf(stderr, "adb: unable to open file %s\n", filename);
632 return -1;
633 }
634
635 snprintf(buf, sizeof(buf), "backup");
636 for (argc--, argv++; argc; argc--, argv++) {
637 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
638 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
639 }
640
641 D("backup. filename=%s buf=%s\n", filename, buf);
642 fd = adb_connect(buf);
643 if (fd < 0) {
644 fprintf(stderr, "adb: unable to connect for backup\n");
645 adb_close(outFd);
646 return -1;
647 }
648
649 copy_to_file(fd, outFd);
650
651 adb_close(fd);
652 adb_close(outFd);
653 return 0;
654}
655
Christopher Tate702967a2011-05-17 15:52:54 -0700656static int restore(int argc, char** argv) {
657 const char* filename;
658 int fd, tarFd;
659
660 if (argc != 2) return usage();
661
662 filename = argv[1];
663 tarFd = adb_open(filename, O_RDONLY);
664 if (tarFd < 0) {
665 fprintf(stderr, "adb: unable to open file %s\n", filename);
666 return -1;
667 }
668
669 fd = adb_connect("restore:");
670 if (fd < 0) {
671 fprintf(stderr, "adb: unable to connect for backup\n");
672 adb_close(tarFd);
673 return -1;
674 }
675
676 copy_to_file(tarFd, fd);
677
678 adb_close(fd);
679 adb_close(tarFd);
680 return 0;
681}
682
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800683#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
684static int top_works(const char *top)
685{
686 if (top != NULL && adb_is_absolute_host_path(top)) {
687 char path_buf[PATH_MAX];
688 snprintf(path_buf, sizeof(path_buf),
689 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
690 return access(path_buf, F_OK) == 0;
691 }
692 return 0;
693}
694
695static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
696{
697 strcpy(path_buf, indir);
698 while (1) {
699 if (top_works(path_buf)) {
700 return path_buf;
701 }
702 char *s = adb_dirstop(path_buf);
703 if (s != NULL) {
704 *s = '\0';
705 } else {
706 path_buf[0] = '\0';
707 return NULL;
708 }
709 }
710}
711
712static char *find_top(char path_buf[PATH_MAX])
713{
714 char *top = getenv("ANDROID_BUILD_TOP");
715 if (top != NULL && top[0] != '\0') {
716 if (!top_works(top)) {
717 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
718 return NULL;
719 }
720 } else {
721 top = getenv("TOP");
722 if (top != NULL && top[0] != '\0') {
723 if (!top_works(top)) {
724 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
725 return NULL;
726 }
727 } else {
728 top = NULL;
729 }
730 }
731
732 if (top != NULL) {
733 /* The environment pointed to a top directory that works.
734 */
735 strcpy(path_buf, top);
736 return path_buf;
737 }
738
739 /* The environment didn't help. Walk up the tree from the CWD
740 * to see if we can find the top.
741 */
742 char dir[PATH_MAX];
743 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
744 if (top == NULL) {
745 /* If the CWD isn't under a good-looking top, see if the
746 * executable is.
747 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100748 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749 top = find_top_from(dir, path_buf);
750 }
751 return top;
752}
753
754/* <hint> may be:
755 * - A simple product name
756 * e.g., "sooner"
757TODO: debug? sooner-debug, sooner:debug?
758 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
759 * e.g., "out/target/product/sooner"
760 * - An absolute path to the PRODUCT_OUT dir
761 * e.g., "/src/device/out/target/product/sooner"
762 *
763 * Given <hint>, try to construct an absolute path to the
764 * ANDROID_PRODUCT_OUT dir.
765 */
766static const char *find_product_out_path(const char *hint)
767{
768 static char path_buf[PATH_MAX];
769
770 if (hint == NULL || hint[0] == '\0') {
771 return NULL;
772 }
773
774 /* If it's already absolute, don't bother doing any work.
775 */
776 if (adb_is_absolute_host_path(hint)) {
777 strcpy(path_buf, hint);
778 return path_buf;
779 }
780
781 /* If there are any slashes in it, assume it's a relative path;
782 * make it absolute.
783 */
784 if (adb_dirstart(hint) != NULL) {
785 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
786 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
787 return NULL;
788 }
789 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
790 fprintf(stderr, "adb: Couldn't assemble path\n");
791 return NULL;
792 }
793 strcat(path_buf, OS_PATH_SEPARATOR_STR);
794 strcat(path_buf, hint);
795 return path_buf;
796 }
797
798 /* It's a string without any slashes. Try to do something with it.
799 *
800 * Try to find the root of the build tree, and build a PRODUCT_OUT
801 * path from there.
802 */
803 char top_buf[PATH_MAX];
804 const char *top = find_top(top_buf);
805 if (top == NULL) {
806 fprintf(stderr, "adb: Couldn't find top of build tree\n");
807 return NULL;
808 }
809//TODO: if we have a way to indicate debug, look in out/debug/target/...
810 snprintf(path_buf, sizeof(path_buf),
811 "%s" OS_PATH_SEPARATOR_STR
812 "out" OS_PATH_SEPARATOR_STR
813 "target" OS_PATH_SEPARATOR_STR
814 "product" OS_PATH_SEPARATOR_STR
815 "%s", top_buf, hint);
816 if (access(path_buf, F_OK) < 0) {
817 fprintf(stderr, "adb: Couldn't find a product dir "
818 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
819 return NULL;
820 }
821 return path_buf;
822}
823
824int adb_commandline(int argc, char **argv)
825{
826 char buf[4096];
827 int no_daemon = 0;
828 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100829 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800830 int persist = 0;
831 int r;
832 int quote;
833 transport_type ttype = kTransportAny;
834 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100835 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836
837 /* If defined, this should be an absolute path to
838 * the directory containing all of the various system images
839 * for a particular product. If not defined, and the adb
840 * command requires this information, then the user must
841 * specify the path using "-p".
842 */
843 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
844 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
845 gProductOutPath = NULL;
846 }
847 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
848
Nick Pellydb449262009-05-07 12:48:03 -0700849 serial = getenv("ANDROID_SERIAL");
850
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100851 /* Validate and assign the server port */
852 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
853 int server_port = DEFAULT_ADB_PORT;
854 if (server_port_str && strlen(server_port_str) > 0) {
855 server_port = (int) strtol(server_port_str, NULL, 0);
856 if (server_port <= 0) {
857 fprintf(stderr,
858 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
859 server_port_str);
860 return usage();
861 }
862 }
863
864 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800865 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100866 if(!strcmp(argv[0],"server")) {
867 is_server = 1;
868 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800869 no_daemon = 1;
870 } else if (!strcmp(argv[0], "fork-server")) {
871 /* this is a special flag used only when the ADB client launches the ADB Server */
872 is_daemon = 1;
873 } else if(!strcmp(argv[0],"persist")) {
874 persist = 1;
875 } else if(!strncmp(argv[0], "-p", 2)) {
876 const char *product = NULL;
877 if (argv[0][2] == '\0') {
878 if (argc < 2) return usage();
879 product = argv[1];
880 argc--;
881 argv++;
882 } else {
883 product = argv[1] + 2;
884 }
885 gProductOutPath = find_product_out_path(product);
886 if (gProductOutPath == NULL) {
887 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
888 product);
889 return usage();
890 }
891 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
892 if (isdigit(argv[0][2])) {
893 serial = argv[0] + 2;
894 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100895 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800896 serial = argv[1];
897 argc--;
898 argv++;
899 }
900 } else if (!strcmp(argv[0],"-d")) {
901 ttype = kTransportUsb;
902 } else if (!strcmp(argv[0],"-e")) {
903 ttype = kTransportLocal;
904 } else {
905 /* out of recognized modifiers and flags */
906 break;
907 }
908 argc--;
909 argv++;
910 }
911
912 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100913 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800914
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100915 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800916 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100917 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800918 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100919 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800920 }
921 if(r) {
922 fprintf(stderr,"* could not start server *\n");
923 }
924 return r;
925 }
926
927top:
928 if(argc == 0) {
929 return usage();
930 }
931
932 /* adb_connect() commands */
933
934 if(!strcmp(argv[0], "devices")) {
935 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -0700936 char *listopt;
937 if (argc < 2)
938 listopt = "";
939 else if (argc == 2 && !strcmp(argv[1], "-l"))
940 listopt = argv[1];
941 else {
942 fprintf(stderr, "Usage: adb devices [-l]\n");
943 return 1;
944 }
945 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800946 tmp = adb_query(buf);
947 if(tmp) {
948 printf("List of devices attached \n");
949 printf("%s\n", tmp);
950 return 0;
951 } else {
952 return 1;
953 }
954 }
955
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400956 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700957 char *tmp;
958 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400959 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -0700960 return 1;
961 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400962 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
963 tmp = adb_query(buf);
964 if(tmp) {
965 printf("%s\n", tmp);
966 return 0;
967 } else {
968 return 1;
969 }
970 }
971
972 if(!strcmp(argv[0], "disconnect")) {
973 char *tmp;
974 if (argc > 2) {
975 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
976 return 1;
977 }
978 if (argc == 2) {
979 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
980 } else {
981 snprintf(buf, sizeof buf, "host:disconnect:");
982 }
Mike Lockwoodff196702009-08-24 15:58:40 -0700983 tmp = adb_query(buf);
984 if(tmp) {
985 printf("%s\n", tmp);
986 return 0;
987 } else {
988 return 1;
989 }
990 }
991
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992 if (!strcmp(argv[0], "emu")) {
993 return adb_send_emulator_command(argc, argv);
994 }
995
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400996 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800997 int r;
998 int fd;
999
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001000 char h = (argv[0][0] == 'h');
1001
1002 if (h) {
1003 printf("\x1b[41;33m");
1004 fflush(stdout);
1005 }
1006
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001007 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001008 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001009 r = interactive_shell();
1010 if (h) {
1011 printf("\x1b[0m");
1012 fflush(stdout);
1013 }
1014 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001015 }
1016
1017 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1018 argc -= 2;
1019 argv += 2;
1020 while(argc-- > 0) {
1021 strcat(buf, " ");
1022
1023 /* quote empty strings and strings with spaces */
1024 quote = (**argv == 0 || strchr(*argv, ' '));
1025 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001026 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001027 strcat(buf, *argv++);
1028 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001029 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001030 }
1031
1032 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001033 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001034 fd = adb_connect(buf);
1035 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001036 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001037 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001038 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001039 adb_close(fd);
1040 r = 0;
1041 } else {
1042 fprintf(stderr,"error: %s\n", adb_error());
1043 r = -1;
1044 }
1045
1046 if(persist) {
1047 fprintf(stderr,"\n- waiting for device -\n");
1048 adb_sleep_ms(1000);
1049 do_cmd(ttype, serial, "wait-for-device", 0);
1050 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001051 if (h) {
1052 printf("\x1b[0m");
1053 fflush(stdout);
1054 }
JP Abgrall408fa572011-03-16 15:57:42 -07001055 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001056 return r;
1057 }
1058 }
1059 }
1060
1061 if(!strcmp(argv[0], "kill-server")) {
1062 int fd;
1063 fd = _adb_connect("host:kill");
1064 if(fd == -1) {
1065 fprintf(stderr,"* server not running *\n");
1066 return 1;
1067 }
1068 return 0;
1069 }
1070
Mike Lockwoodff196702009-08-24 15:58:40 -07001071 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001072 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001073 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001074 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001075 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001076 if (!strcmp(argv[0], "reboot-bootloader"))
1077 snprintf(command, sizeof(command), "reboot:bootloader");
1078 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001079 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001080 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001081 snprintf(command, sizeof(command), "%s:", argv[0]);
1082 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001083 if(fd >= 0) {
1084 read_and_dump(fd);
1085 adb_close(fd);
1086 return 0;
1087 }
1088 fprintf(stderr,"error: %s\n", adb_error());
1089 return 1;
1090 }
1091
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001092 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001093 if (argc != 1) return usage();
1094 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001095 return 0;
1096 }
1097
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001098 /* adb_command() wrapper commands */
1099
1100 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1101 char* service = argv[0];
1102 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1103 if (ttype == kTransportUsb) {
1104 service = "wait-for-usb";
1105 } else if (ttype == kTransportLocal) {
1106 service = "wait-for-local";
1107 } else {
1108 service = "wait-for-any";
1109 }
1110 }
1111
1112 format_host_command(buf, sizeof buf, service, ttype, serial);
1113
1114 if (adb_command(buf)) {
1115 D("failure: %s *\n",adb_error());
1116 fprintf(stderr,"error: %s\n", adb_error());
1117 return 1;
1118 }
1119
1120 /* Allow a command to be run after wait-for-device,
1121 * e.g. 'adb wait-for-device shell'.
1122 */
1123 if(argc > 1) {
1124 argc--;
1125 argv++;
1126 goto top;
1127 }
1128 return 0;
1129 }
1130
1131 if(!strcmp(argv[0], "forward")) {
1132 if(argc != 3) return usage();
1133 if (serial) {
Mike Lockwood64e99542009-11-28 12:46:13 -05001134 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1135 } else if (ttype == kTransportUsb) {
1136 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1137 } else if (ttype == kTransportLocal) {
1138 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139 } else {
Mike Lockwood64e99542009-11-28 12:46:13 -05001140 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141 }
1142 if(adb_command(buf)) {
1143 fprintf(stderr,"error: %s\n", adb_error());
1144 return 1;
1145 }
1146 return 0;
1147 }
1148
1149 /* do_sync_*() commands */
1150
1151 if(!strcmp(argv[0], "ls")) {
1152 if(argc != 2) return usage();
1153 return do_sync_ls(argv[1]);
1154 }
1155
1156 if(!strcmp(argv[0], "push")) {
1157 if(argc != 3) return usage();
1158 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1159 }
1160
1161 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001162 if (argc == 2) {
1163 return do_sync_pull(argv[1], ".");
1164 } else if (argc == 3) {
1165 return do_sync_pull(argv[1], argv[2]);
1166 } else {
1167 return usage();
1168 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001169 }
1170
1171 if(!strcmp(argv[0], "install")) {
1172 if (argc < 2) return usage();
1173 return install_app(ttype, serial, argc, argv);
1174 }
1175
1176 if(!strcmp(argv[0], "uninstall")) {
1177 if (argc < 2) return usage();
1178 return uninstall_app(ttype, serial, argc, argv);
1179 }
1180
1181 if(!strcmp(argv[0], "sync")) {
1182 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001183 int listonly = 0;
1184
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001185 int ret;
1186 if(argc < 2) {
1187 /* No local path was specified. */
1188 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001189 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1190 listonly = 1;
1191 if (argc == 3) {
1192 srcarg = argv[2];
1193 } else {
1194 srcarg = NULL;
1195 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001196 } else if(argc == 2) {
1197 /* A local path or "android"/"data" arg was specified. */
1198 srcarg = argv[1];
1199 } else {
1200 return usage();
1201 }
1202 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1203 if(ret != 0) return usage();
1204
1205 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001206 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001207 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001208 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001209
1210 free(android_srcpath);
1211 free(data_srcpath);
1212 return ret;
1213 }
1214
1215 /* passthrough commands */
1216
1217 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001218 !strcmp(argv[0],"get-serialno") ||
1219 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 {
1221 char *tmp;
1222
1223 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1224 tmp = adb_query(buf);
1225 if(tmp) {
1226 printf("%s\n", tmp);
1227 return 0;
1228 } else {
1229 return 1;
1230 }
1231 }
1232
1233 /* other commands */
1234
1235 if(!strcmp(argv[0],"status-window")) {
1236 status_window(ttype, serial);
1237 return 0;
1238 }
1239
1240 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1241 return logcat(ttype, serial, argc, argv);
1242 }
1243
1244 if(!strcmp(argv[0],"ppp")) {
1245 return ppp(argc, argv);
1246 }
1247
1248 if (!strcmp(argv[0], "start-server")) {
1249 return adb_connect("host:start-server");
1250 }
1251
Christopher Tated2f54152011-04-21 12:53:28 -07001252 if (!strcmp(argv[0], "backup")) {
1253 return backup(argc, argv);
1254 }
1255
Christopher Tate702967a2011-05-17 15:52:54 -07001256 if (!strcmp(argv[0], "restore")) {
1257 return restore(argc, argv);
1258 }
1259
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001260 if (!strcmp(argv[0], "jdwp")) {
1261 int fd = adb_connect("jdwp");
1262 if (fd >= 0) {
1263 read_and_dump(fd);
1264 adb_close(fd);
1265 return 0;
1266 } else {
1267 fprintf(stderr, "error: %s\n", adb_error());
1268 return -1;
1269 }
1270 }
1271
1272 /* "adb /?" is a common idiom under Windows */
1273 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1274 help();
1275 return 0;
1276 }
1277
1278 if(!strcmp(argv[0], "version")) {
1279 version(stdout);
1280 return 0;
1281 }
1282
1283 usage();
1284 return 1;
1285}
1286
1287static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1288{
1289 char *argv[16];
1290 int argc;
1291 va_list ap;
1292
1293 va_start(ap, cmd);
1294 argc = 0;
1295
1296 if (serial) {
1297 argv[argc++] = "-s";
1298 argv[argc++] = serial;
1299 } else if (ttype == kTransportUsb) {
1300 argv[argc++] = "-d";
1301 } else if (ttype == kTransportLocal) {
1302 argv[argc++] = "-e";
1303 }
1304
1305 argv[argc++] = cmd;
1306 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1307 va_end(ap);
1308
1309#if 0
1310 int n;
1311 fprintf(stderr,"argc = %d\n",argc);
1312 for(n = 0; n < argc; n++) {
1313 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1314 }
1315#endif
1316
1317 return adb_commandline(argc, argv);
1318}
1319
1320int find_sync_dirs(const char *srcarg,
1321 char **android_srcdir_out, char **data_srcdir_out)
1322{
1323 char *android_srcdir, *data_srcdir;
1324
1325 if(srcarg == NULL) {
1326 android_srcdir = product_file("system");
1327 data_srcdir = product_file("data");
1328 } else {
1329 /* srcarg may be "data", "system" or NULL.
1330 * if srcarg is NULL, then both data and system are synced
1331 */
1332 if(strcmp(srcarg, "system") == 0) {
1333 android_srcdir = product_file("system");
1334 data_srcdir = NULL;
1335 } else if(strcmp(srcarg, "data") == 0) {
1336 android_srcdir = NULL;
1337 data_srcdir = product_file("data");
1338 } else {
1339 /* It's not "system" or "data".
1340 */
1341 return 1;
1342 }
1343 }
1344
1345 if(android_srcdir_out != NULL)
1346 *android_srcdir_out = android_srcdir;
1347 else
1348 free(android_srcdir);
1349
1350 if(data_srcdir_out != NULL)
1351 *data_srcdir_out = data_srcdir;
1352 else
1353 free(data_srcdir);
1354
1355 return 0;
1356}
1357
1358static int pm_command(transport_type transport, char* serial,
1359 int argc, char** argv)
1360{
1361 char buf[4096];
1362
1363 snprintf(buf, sizeof(buf), "shell:pm");
1364
1365 while(argc-- > 0) {
1366 char *quoted;
1367
1368 quoted = dupAndQuote(*argv++);
1369
1370 strncat(buf, " ", sizeof(buf)-1);
1371 strncat(buf, quoted, sizeof(buf)-1);
1372 free(quoted);
1373 }
1374
1375 send_shellcommand(transport, serial, buf);
1376 return 0;
1377}
1378
1379int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1380{
1381 /* if the user choose the -k option, we refuse to do it until devices are
1382 out with the option to uninstall the remaining data somehow (adb/ui) */
1383 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1384 {
1385 printf(
1386 "The -k option uninstalls the application while retaining the data/cache.\n"
1387 "At the moment, there is no way to remove the remaining data.\n"
1388 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1389 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1390 return -1;
1391 }
1392
1393 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1394 return pm_command(transport, serial, argc, argv);
1395}
1396
1397static int delete_file(transport_type transport, char* serial, char* filename)
1398{
1399 char buf[4096];
1400 char* quoted;
1401
1402 snprintf(buf, sizeof(buf), "shell:rm ");
1403 quoted = dupAndQuote(filename);
1404 strncat(buf, quoted, sizeof(buf)-1);
1405 free(quoted);
1406
1407 send_shellcommand(transport, serial, buf);
1408 return 0;
1409}
1410
Kenny Root597ea5b2011-08-05 11:19:45 -07001411static const char* get_basename(const char* filename)
1412{
1413 const char* basename = adb_dirstop(filename);
1414 if (basename) {
1415 basename++;
1416 return basename;
1417 } else {
1418 return filename;
1419 }
1420}
1421
1422static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423{
1424 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001425
Kenny Root597ea5b2011-08-05 11:19:45 -07001426 if (filename == NULL) {
1427 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001428 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001429
Kenny Root597ea5b2011-08-05 11:19:45 -07001430 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001431 fprintf(stderr, "can't find '%s' to install\n", filename);
1432 return 1;
1433 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001434
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001435 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001436 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001437 return 1;
1438 }
1439
Kenny Root597ea5b2011-08-05 11:19:45 -07001440 return 0;
1441}
1442
1443int install_app(transport_type transport, char* serial, int argc, char** argv)
1444{
1445 static const char *const DATA_DEST = "/data/local/tmp/%s";
1446 static const char *const SD_DEST = "/sdcard/tmp/%s";
1447 const char* where = DATA_DEST;
1448 char apk_dest[PATH_MAX];
1449 char verification_dest[PATH_MAX];
1450 char* apk_file;
1451 char* verification_file = NULL;
1452 int file_arg = -1;
1453 int err;
1454 int i;
1455
1456 for (i = 1; i < argc; i++) {
1457 if (*argv[i] != '-') {
1458 file_arg = i;
1459 break;
Kenny Roota031a912011-09-23 12:46:39 -07001460 } else if (!strcmp(argv[i], "-i")) {
1461 // Skip the installer package name.
1462 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001463 } else if (!strcmp(argv[i], "-s")) {
1464 where = SD_DEST;
1465 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001466 }
1467
Kenny Root597ea5b2011-08-05 11:19:45 -07001468 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001469 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001470 return 1;
1471 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001472 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001473 return 1;
1474 }
1475
1476 apk_file = argv[file_arg];
1477
1478 if (file_arg != argc - 1) {
1479 verification_file = argv[file_arg + 1];
1480 }
1481
1482 if (check_file(apk_file) || check_file(verification_file)) {
1483 return 1;
1484 }
1485
1486 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1487 if (verification_file != NULL) {
1488 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1489
1490 if (!strcmp(apk_dest, verification_dest)) {
1491 fprintf(stderr, "APK and verification file can't have the same name\n");
1492 return 1;
1493 }
1494 }
1495
1496 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1497 if (err) {
1498 return err;
1499 } else {
1500 argv[file_arg] = apk_dest; /* destination name, not source location */
1501 }
1502
1503 if (verification_file != NULL) {
1504 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1505 if (err) {
1506 goto cleanup_apk;
1507 } else {
1508 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1509 }
1510 }
1511
1512 pm_command(transport, serial, argc, argv);
1513
1514 if (verification_file != NULL) {
1515 delete_file(transport, serial, verification_dest);
1516 }
1517
1518cleanup_apk:
1519 delete_file(transport, serial, apk_dest);
1520
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001521 return err;
1522}