blob: 973932fb94fb73c7708e24168ab01a8409602aba [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 Tated2f54152011-04-21 12:53:28 -0700132 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [<packages...>]\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700133 " - Write an archive of the device's data to <file>.\n"
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700134 " If a -f option is not supplied then the data is\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700135 " written 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"
141 " (<packages...> is the list of applications to be backed up. If\n"
142 " the -all or -shared flags are passed, then the package\n"
143 " list is optional.)\n"
144 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700145 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700146 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800147 " adb help - show this help message\n"
148 " adb version - show version num\n"
149 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 "scripting:\n"
151 " adb wait-for-device - block until device is online\n"
152 " adb start-server - ensure that there is a server running\n"
153 " adb kill-server - kill the server if it is running\n"
154 " adb get-state - prints: offline | bootloader | device\n"
155 " adb get-serialno - prints: <serial-number>\n"
156 " adb status-window - continuously print device status for a specified device\n"
157 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400158 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800159 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700160 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800161 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700162 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800163 "\n"
164 "networking:\n"
165 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500166 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
168 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
169 "\n"
170 "adb sync notes: adb sync [ <directory> ]\n"
171 " <localdir> can be interpreted in several ways:\n"
172 "\n"
173 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
174 "\n"
175 " - If it is \"system\" or \"data\", only the corresponding partition\n"
176 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000177 "\n"
178 "environmental variables:\n"
179 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
180 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
181 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
182 " 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 -0800183 );
184}
185
186int usage()
187{
188 help();
189 return 1;
190}
191
192#ifdef HAVE_TERMIO_H
193static struct termios tio_save;
194
195static void stdin_raw_init(int fd)
196{
197 struct termios tio;
198
199 if(tcgetattr(fd, &tio)) return;
200 if(tcgetattr(fd, &tio_save)) return;
201
202 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
203
204 /* no timeout but request at least one character per read */
205 tio.c_cc[VTIME] = 0;
206 tio.c_cc[VMIN] = 1;
207
208 tcsetattr(fd, TCSANOW, &tio);
209 tcflush(fd, TCIFLUSH);
210}
211
212static void stdin_raw_restore(int fd)
213{
214 tcsetattr(fd, TCSANOW, &tio_save);
215 tcflush(fd, TCIFLUSH);
216}
217#endif
218
219static void read_and_dump(int fd)
220{
221 char buf[4096];
222 int len;
223
224 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700225 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700227 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 if(len == 0) {
229 break;
230 }
231
232 if(len < 0) {
233 if(errno == EINTR) continue;
234 break;
235 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400236 fwrite(buf, 1, len, stdout);
237 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238 }
239}
240
Christopher Tated2f54152011-04-21 12:53:28 -0700241static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700242 const size_t BUFSIZE = 32 * 1024;
243 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700244 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700245 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700246
247 D("copy_to_file(%d -> %d)\n", inFd, outFd);
248 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700249 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700250 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700251 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700252 break;
253 }
254 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700255 if (errno == EINTR) {
256 D("copy_to_file() : EINTR, retrying\n");
257 continue;
258 }
Christopher Tated2f54152011-04-21 12:53:28 -0700259 D("copy_to_file() : error %d\n", errno);
260 break;
261 }
262 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700263 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700264 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700265 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700266 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700267}
268
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269static void *stdin_read_thread(void *x)
270{
271 int fd, fdi;
272 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273 int r, n;
274 int state = 0;
275
276 int *fds = (int*) x;
277 fd = fds[0];
278 fdi = fds[1];
279 free(fds);
280
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 for(;;) {
282 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700283 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700285 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800286 if(r == 0) break;
287 if(r < 0) {
288 if(errno == EINTR) continue;
289 break;
290 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400291 for(n = 0; n < r; n++){
292 switch(buf[n]) {
293 case '\n':
294 state = 1;
295 break;
296 case '\r':
297 state = 1;
298 break;
299 case '~':
300 if(state == 1) state++;
301 break;
302 case '.':
303 if(state == 2) {
304 fprintf(stderr,"\n* disconnect *\n");
305#ifdef HAVE_TERMIO_H
306 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400308 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800309 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400310 default:
311 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800312 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800314 r = adb_write(fd, buf, r);
315 if(r <= 0) {
316 break;
317 }
318 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800319 return 0;
320}
321
322int interactive_shell(void)
323{
324 adb_thread_t thr;
325 int fdi, fd;
326 int *fds;
327
328 fd = adb_connect("shell:");
329 if(fd < 0) {
330 fprintf(stderr,"error: %s\n", adb_error());
331 return 1;
332 }
333 fdi = 0; //dup(0);
334
335 fds = malloc(sizeof(int) * 2);
336 fds[0] = fd;
337 fds[1] = fdi;
338
339#ifdef HAVE_TERMIO_H
340 stdin_raw_init(fdi);
341#endif
342 adb_thread_create(&thr, stdin_read_thread, fds);
343 read_and_dump(fd);
344#ifdef HAVE_TERMIO_H
345 stdin_raw_restore(fdi);
346#endif
347 return 0;
348}
349
350
351static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
352{
353 if (serial) {
354 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
355 } else {
356 const char* prefix = "host";
357 if (ttype == kTransportUsb)
358 prefix = "host-usb";
359 else if (ttype == kTransportLocal)
360 prefix = "host-local";
361
362 snprintf(buffer, buflen, "%s:%s", prefix, command);
363 }
364}
365
366static void status_window(transport_type ttype, const char* serial)
367{
368 char command[4096];
369 char *state = 0;
370 char *laststate = 0;
371
372 /* silence stderr */
373#ifdef _WIN32
374 /* XXX: TODO */
375#else
376 int fd;
377 fd = unix_open("/dev/null", O_WRONLY);
378 dup2(fd, 2);
379 adb_close(fd);
380#endif
381
382 format_host_command(command, sizeof command, "get-state", ttype, serial);
383
384 for(;;) {
385 adb_sleep_ms(250);
386
387 if(state) {
388 free(state);
389 state = 0;
390 }
391
392 state = adb_query(command);
393
394 if(state) {
395 if(laststate && !strcmp(state,laststate)){
396 continue;
397 } else {
398 if(laststate) free(laststate);
399 laststate = strdup(state);
400 }
401 }
402
403 printf("%c[2J%c[2H", 27, 27);
404 printf("Android Debug Bridge\n");
405 printf("State: %s\n", state ? state : "offline");
406 fflush(stdout);
407 }
408}
409
410/** duplicate string and quote all \ " ( ) chars + space character. */
411static char *
412dupAndQuote(const char *s)
413{
414 const char *ts;
415 size_t alloc_len;
416 char *ret;
417 char *dest;
418
419 ts = s;
420
421 alloc_len = 0;
422
423 for( ;*ts != '\0'; ts++) {
424 alloc_len++;
425 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
426 alloc_len++;
427 }
428 }
429
430 ret = (char *)malloc(alloc_len + 1);
431
432 ts = s;
433 dest = ret;
434
435 for ( ;*ts != '\0'; ts++) {
436 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
437 *dest++ = '\\';
438 }
439
440 *dest++ = *ts;
441 }
442
443 *dest++ = '\0';
444
445 return ret;
446}
447
448/**
449 * Run ppp in "notty" mode against a resource listed as the first parameter
450 * eg:
451 *
452 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
453 *
454 */
455int ppp(int argc, char **argv)
456{
457#ifdef HAVE_WIN32_PROC
458 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
459 return -1;
460#else
461 char *adb_service_name;
462 pid_t pid;
463 int fd;
464
465 if (argc < 2) {
466 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
467 argv[0]);
468
469 return 1;
470 }
471
472 adb_service_name = argv[1];
473
474 fd = adb_connect(adb_service_name);
475
476 if(fd < 0) {
477 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
478 adb_service_name, adb_error());
479 return 1;
480 }
481
482 pid = fork();
483
484 if (pid < 0) {
485 perror("from fork()");
486 return 1;
487 } else if (pid == 0) {
488 int err;
489 int i;
490 const char **ppp_args;
491
492 // copy args
493 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
494 ppp_args[0] = "pppd";
495 for (i = 2 ; i < argc ; i++) {
496 //argv[2] and beyond become ppp_args[1] and beyond
497 ppp_args[i - 1] = argv[i];
498 }
499 ppp_args[i-1] = NULL;
500
501 // child side
502
503 dup2(fd, STDIN_FILENO);
504 dup2(fd, STDOUT_FILENO);
505 adb_close(STDERR_FILENO);
506 adb_close(fd);
507
508 err = execvp("pppd", (char * const *)ppp_args);
509
510 if (err < 0) {
511 perror("execing pppd");
512 }
513 exit(-1);
514 } else {
515 // parent side
516
517 adb_close(fd);
518 return 0;
519 }
520#endif /* !HAVE_WIN32_PROC */
521}
522
523static int send_shellcommand(transport_type transport, char* serial, char* buf)
524{
525 int fd, ret;
526
527 for(;;) {
528 fd = adb_connect(buf);
529 if(fd >= 0)
530 break;
531 fprintf(stderr,"- waiting for device -\n");
532 adb_sleep_ms(1000);
533 do_cmd(transport, serial, "wait-for-device", 0);
534 }
535
536 read_and_dump(fd);
537 ret = adb_close(fd);
538 if (ret)
539 perror("close");
540
541 return ret;
542}
543
544static int logcat(transport_type transport, char* serial, int argc, char **argv)
545{
546 char buf[4096];
547
548 char *log_tags;
549 char *quoted_log_tags;
550
551 log_tags = getenv("ANDROID_LOG_TAGS");
552 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
553
554 snprintf(buf, sizeof(buf),
555 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
556 quoted_log_tags);
557
558 free(quoted_log_tags);
559
560 argc -= 1;
561 argv += 1;
562 while(argc-- > 0) {
563 char *quoted;
564
565 quoted = dupAndQuote (*argv++);
566
567 strncat(buf, " ", sizeof(buf)-1);
568 strncat(buf, quoted, sizeof(buf)-1);
569 free(quoted);
570 }
571
572 send_shellcommand(transport, serial, buf);
573 return 0;
574}
575
Christopher Tated2f54152011-04-21 12:53:28 -0700576static int backup(int argc, char** argv) {
577 char buf[4096];
Christopher Tatede034ec2011-08-09 17:05:29 -0700578 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700579 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700580 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700581
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700582 /* find, extract, and use any -f argument */
583 for (i = 1; i < argc; i++) {
584 if (!strcmp("-f", argv[i])) {
585 if (i == argc-1) {
586 fprintf(stderr, "adb: -f passed with no filename\n");
587 return usage();
588 }
589 filename = argv[i+1];
590 for (j = i+2; j <= argc; ) {
591 argv[i++] = argv[j++];
592 }
593 argc -= 2;
594 argv[argc] = NULL;
595 }
Christopher Tated2f54152011-04-21 12:53:28 -0700596 }
597
Christopher Tatebb86bc52011-08-22 17:12:08 -0700598 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
599 if (argc < 2) return usage();
600
Christopher Tated2f54152011-04-21 12:53:28 -0700601 outFd = adb_open_mode(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
602 if (outFd < 0) {
603 fprintf(stderr, "adb: unable to open file %s\n", filename);
604 return -1;
605 }
606
607 snprintf(buf, sizeof(buf), "backup");
608 for (argc--, argv++; argc; argc--, argv++) {
609 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
610 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
611 }
612
613 D("backup. filename=%s buf=%s\n", filename, buf);
614 fd = adb_connect(buf);
615 if (fd < 0) {
616 fprintf(stderr, "adb: unable to connect for backup\n");
617 adb_close(outFd);
618 return -1;
619 }
620
621 copy_to_file(fd, outFd);
622
623 adb_close(fd);
624 adb_close(outFd);
625 return 0;
626}
627
Christopher Tate702967a2011-05-17 15:52:54 -0700628static int restore(int argc, char** argv) {
629 const char* filename;
630 int fd, tarFd;
631
632 if (argc != 2) return usage();
633
634 filename = argv[1];
635 tarFd = adb_open(filename, O_RDONLY);
636 if (tarFd < 0) {
637 fprintf(stderr, "adb: unable to open file %s\n", filename);
638 return -1;
639 }
640
641 fd = adb_connect("restore:");
642 if (fd < 0) {
643 fprintf(stderr, "adb: unable to connect for backup\n");
644 adb_close(tarFd);
645 return -1;
646 }
647
648 copy_to_file(tarFd, fd);
649
650 adb_close(fd);
651 adb_close(tarFd);
652 return 0;
653}
654
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800655#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
656static int top_works(const char *top)
657{
658 if (top != NULL && adb_is_absolute_host_path(top)) {
659 char path_buf[PATH_MAX];
660 snprintf(path_buf, sizeof(path_buf),
661 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
662 return access(path_buf, F_OK) == 0;
663 }
664 return 0;
665}
666
667static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
668{
669 strcpy(path_buf, indir);
670 while (1) {
671 if (top_works(path_buf)) {
672 return path_buf;
673 }
674 char *s = adb_dirstop(path_buf);
675 if (s != NULL) {
676 *s = '\0';
677 } else {
678 path_buf[0] = '\0';
679 return NULL;
680 }
681 }
682}
683
684static char *find_top(char path_buf[PATH_MAX])
685{
686 char *top = getenv("ANDROID_BUILD_TOP");
687 if (top != NULL && top[0] != '\0') {
688 if (!top_works(top)) {
689 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
690 return NULL;
691 }
692 } else {
693 top = getenv("TOP");
694 if (top != NULL && top[0] != '\0') {
695 if (!top_works(top)) {
696 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
697 return NULL;
698 }
699 } else {
700 top = NULL;
701 }
702 }
703
704 if (top != NULL) {
705 /* The environment pointed to a top directory that works.
706 */
707 strcpy(path_buf, top);
708 return path_buf;
709 }
710
711 /* The environment didn't help. Walk up the tree from the CWD
712 * to see if we can find the top.
713 */
714 char dir[PATH_MAX];
715 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
716 if (top == NULL) {
717 /* If the CWD isn't under a good-looking top, see if the
718 * executable is.
719 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100720 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 top = find_top_from(dir, path_buf);
722 }
723 return top;
724}
725
726/* <hint> may be:
727 * - A simple product name
728 * e.g., "sooner"
729TODO: debug? sooner-debug, sooner:debug?
730 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
731 * e.g., "out/target/product/sooner"
732 * - An absolute path to the PRODUCT_OUT dir
733 * e.g., "/src/device/out/target/product/sooner"
734 *
735 * Given <hint>, try to construct an absolute path to the
736 * ANDROID_PRODUCT_OUT dir.
737 */
738static const char *find_product_out_path(const char *hint)
739{
740 static char path_buf[PATH_MAX];
741
742 if (hint == NULL || hint[0] == '\0') {
743 return NULL;
744 }
745
746 /* If it's already absolute, don't bother doing any work.
747 */
748 if (adb_is_absolute_host_path(hint)) {
749 strcpy(path_buf, hint);
750 return path_buf;
751 }
752
753 /* If there are any slashes in it, assume it's a relative path;
754 * make it absolute.
755 */
756 if (adb_dirstart(hint) != NULL) {
757 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
758 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
759 return NULL;
760 }
761 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
762 fprintf(stderr, "adb: Couldn't assemble path\n");
763 return NULL;
764 }
765 strcat(path_buf, OS_PATH_SEPARATOR_STR);
766 strcat(path_buf, hint);
767 return path_buf;
768 }
769
770 /* It's a string without any slashes. Try to do something with it.
771 *
772 * Try to find the root of the build tree, and build a PRODUCT_OUT
773 * path from there.
774 */
775 char top_buf[PATH_MAX];
776 const char *top = find_top(top_buf);
777 if (top == NULL) {
778 fprintf(stderr, "adb: Couldn't find top of build tree\n");
779 return NULL;
780 }
781//TODO: if we have a way to indicate debug, look in out/debug/target/...
782 snprintf(path_buf, sizeof(path_buf),
783 "%s" OS_PATH_SEPARATOR_STR
784 "out" OS_PATH_SEPARATOR_STR
785 "target" OS_PATH_SEPARATOR_STR
786 "product" OS_PATH_SEPARATOR_STR
787 "%s", top_buf, hint);
788 if (access(path_buf, F_OK) < 0) {
789 fprintf(stderr, "adb: Couldn't find a product dir "
790 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
791 return NULL;
792 }
793 return path_buf;
794}
795
796int adb_commandline(int argc, char **argv)
797{
798 char buf[4096];
799 int no_daemon = 0;
800 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100801 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800802 int persist = 0;
803 int r;
804 int quote;
805 transport_type ttype = kTransportAny;
806 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100807 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800808
809 /* If defined, this should be an absolute path to
810 * the directory containing all of the various system images
811 * for a particular product. If not defined, and the adb
812 * command requires this information, then the user must
813 * specify the path using "-p".
814 */
815 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
816 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
817 gProductOutPath = NULL;
818 }
819 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
820
Nick Pellydb449262009-05-07 12:48:03 -0700821 serial = getenv("ANDROID_SERIAL");
822
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100823 /* Validate and assign the server port */
824 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
825 int server_port = DEFAULT_ADB_PORT;
826 if (server_port_str && strlen(server_port_str) > 0) {
827 server_port = (int) strtol(server_port_str, NULL, 0);
828 if (server_port <= 0) {
829 fprintf(stderr,
830 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
831 server_port_str);
832 return usage();
833 }
834 }
835
836 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800837 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100838 if(!strcmp(argv[0],"server")) {
839 is_server = 1;
840 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841 no_daemon = 1;
842 } else if (!strcmp(argv[0], "fork-server")) {
843 /* this is a special flag used only when the ADB client launches the ADB Server */
844 is_daemon = 1;
845 } else if(!strcmp(argv[0],"persist")) {
846 persist = 1;
847 } else if(!strncmp(argv[0], "-p", 2)) {
848 const char *product = NULL;
849 if (argv[0][2] == '\0') {
850 if (argc < 2) return usage();
851 product = argv[1];
852 argc--;
853 argv++;
854 } else {
855 product = argv[1] + 2;
856 }
857 gProductOutPath = find_product_out_path(product);
858 if (gProductOutPath == NULL) {
859 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
860 product);
861 return usage();
862 }
863 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
864 if (isdigit(argv[0][2])) {
865 serial = argv[0] + 2;
866 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100867 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800868 serial = argv[1];
869 argc--;
870 argv++;
871 }
872 } else if (!strcmp(argv[0],"-d")) {
873 ttype = kTransportUsb;
874 } else if (!strcmp(argv[0],"-e")) {
875 ttype = kTransportLocal;
876 } else {
877 /* out of recognized modifiers and flags */
878 break;
879 }
880 argc--;
881 argv++;
882 }
883
884 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100885 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800886
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100887 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800888 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100889 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800890 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100891 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800892 }
893 if(r) {
894 fprintf(stderr,"* could not start server *\n");
895 }
896 return r;
897 }
898
899top:
900 if(argc == 0) {
901 return usage();
902 }
903
904 /* adb_connect() commands */
905
906 if(!strcmp(argv[0], "devices")) {
907 char *tmp;
908 snprintf(buf, sizeof buf, "host:%s", argv[0]);
909 tmp = adb_query(buf);
910 if(tmp) {
911 printf("List of devices attached \n");
912 printf("%s\n", tmp);
913 return 0;
914 } else {
915 return 1;
916 }
917 }
918
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400919 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700920 char *tmp;
921 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400922 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -0700923 return 1;
924 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400925 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
926 tmp = adb_query(buf);
927 if(tmp) {
928 printf("%s\n", tmp);
929 return 0;
930 } else {
931 return 1;
932 }
933 }
934
935 if(!strcmp(argv[0], "disconnect")) {
936 char *tmp;
937 if (argc > 2) {
938 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
939 return 1;
940 }
941 if (argc == 2) {
942 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
943 } else {
944 snprintf(buf, sizeof buf, "host:disconnect:");
945 }
Mike Lockwoodff196702009-08-24 15:58:40 -0700946 tmp = adb_query(buf);
947 if(tmp) {
948 printf("%s\n", tmp);
949 return 0;
950 } else {
951 return 1;
952 }
953 }
954
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800955 if (!strcmp(argv[0], "emu")) {
956 return adb_send_emulator_command(argc, argv);
957 }
958
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400959 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800960 int r;
961 int fd;
962
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400963 char h = (argv[0][0] == 'h');
964
965 if (h) {
966 printf("\x1b[41;33m");
967 fflush(stdout);
968 }
969
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800970 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -0700971 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400972 r = interactive_shell();
973 if (h) {
974 printf("\x1b[0m");
975 fflush(stdout);
976 }
977 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800978 }
979
980 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
981 argc -= 2;
982 argv += 2;
983 while(argc-- > 0) {
984 strcat(buf, " ");
985
986 /* quote empty strings and strings with spaces */
987 quote = (**argv == 0 || strchr(*argv, ' '));
988 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100989 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800990 strcat(buf, *argv++);
991 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100992 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800993 }
994
995 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -0700996 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800997 fd = adb_connect(buf);
998 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700999 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001001 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001002 adb_close(fd);
1003 r = 0;
1004 } else {
1005 fprintf(stderr,"error: %s\n", adb_error());
1006 r = -1;
1007 }
1008
1009 if(persist) {
1010 fprintf(stderr,"\n- waiting for device -\n");
1011 adb_sleep_ms(1000);
1012 do_cmd(ttype, serial, "wait-for-device", 0);
1013 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001014 if (h) {
1015 printf("\x1b[0m");
1016 fflush(stdout);
1017 }
JP Abgrall408fa572011-03-16 15:57:42 -07001018 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001019 return r;
1020 }
1021 }
1022 }
1023
1024 if(!strcmp(argv[0], "kill-server")) {
1025 int fd;
1026 fd = _adb_connect("host:kill");
1027 if(fd == -1) {
1028 fprintf(stderr,"* server not running *\n");
1029 return 1;
1030 }
1031 return 0;
1032 }
1033
Mike Lockwoodff196702009-08-24 15:58:40 -07001034 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001035 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001036 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001037 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001038 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001039 if (!strcmp(argv[0], "reboot-bootloader"))
1040 snprintf(command, sizeof(command), "reboot:bootloader");
1041 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001042 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001043 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001044 snprintf(command, sizeof(command), "%s:", argv[0]);
1045 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001046 if(fd >= 0) {
1047 read_and_dump(fd);
1048 adb_close(fd);
1049 return 0;
1050 }
1051 fprintf(stderr,"error: %s\n", adb_error());
1052 return 1;
1053 }
1054
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001055 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001056 if (argc != 1) return usage();
1057 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001058 return 0;
1059 }
1060
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001061 /* adb_command() wrapper commands */
1062
1063 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1064 char* service = argv[0];
1065 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1066 if (ttype == kTransportUsb) {
1067 service = "wait-for-usb";
1068 } else if (ttype == kTransportLocal) {
1069 service = "wait-for-local";
1070 } else {
1071 service = "wait-for-any";
1072 }
1073 }
1074
1075 format_host_command(buf, sizeof buf, service, ttype, serial);
1076
1077 if (adb_command(buf)) {
1078 D("failure: %s *\n",adb_error());
1079 fprintf(stderr,"error: %s\n", adb_error());
1080 return 1;
1081 }
1082
1083 /* Allow a command to be run after wait-for-device,
1084 * e.g. 'adb wait-for-device shell'.
1085 */
1086 if(argc > 1) {
1087 argc--;
1088 argv++;
1089 goto top;
1090 }
1091 return 0;
1092 }
1093
1094 if(!strcmp(argv[0], "forward")) {
1095 if(argc != 3) return usage();
1096 if (serial) {
Mike Lockwood64e99542009-11-28 12:46:13 -05001097 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1098 } else if (ttype == kTransportUsb) {
1099 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1100 } else if (ttype == kTransportLocal) {
1101 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001102 } else {
Mike Lockwood64e99542009-11-28 12:46:13 -05001103 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104 }
1105 if(adb_command(buf)) {
1106 fprintf(stderr,"error: %s\n", adb_error());
1107 return 1;
1108 }
1109 return 0;
1110 }
1111
1112 /* do_sync_*() commands */
1113
1114 if(!strcmp(argv[0], "ls")) {
1115 if(argc != 2) return usage();
1116 return do_sync_ls(argv[1]);
1117 }
1118
1119 if(!strcmp(argv[0], "push")) {
1120 if(argc != 3) return usage();
1121 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1122 }
1123
1124 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001125 if (argc == 2) {
1126 return do_sync_pull(argv[1], ".");
1127 } else if (argc == 3) {
1128 return do_sync_pull(argv[1], argv[2]);
1129 } else {
1130 return usage();
1131 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001132 }
1133
1134 if(!strcmp(argv[0], "install")) {
1135 if (argc < 2) return usage();
1136 return install_app(ttype, serial, argc, argv);
1137 }
1138
1139 if(!strcmp(argv[0], "uninstall")) {
1140 if (argc < 2) return usage();
1141 return uninstall_app(ttype, serial, argc, argv);
1142 }
1143
1144 if(!strcmp(argv[0], "sync")) {
1145 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001146 int listonly = 0;
1147
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148 int ret;
1149 if(argc < 2) {
1150 /* No local path was specified. */
1151 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001152 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1153 listonly = 1;
1154 if (argc == 3) {
1155 srcarg = argv[2];
1156 } else {
1157 srcarg = NULL;
1158 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001159 } else if(argc == 2) {
1160 /* A local path or "android"/"data" arg was specified. */
1161 srcarg = argv[1];
1162 } else {
1163 return usage();
1164 }
1165 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1166 if(ret != 0) return usage();
1167
1168 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001169 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001170 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001171 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001172
1173 free(android_srcpath);
1174 free(data_srcpath);
1175 return ret;
1176 }
1177
1178 /* passthrough commands */
1179
1180 if(!strcmp(argv[0],"get-state") ||
1181 !strcmp(argv[0],"get-serialno"))
1182 {
1183 char *tmp;
1184
1185 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1186 tmp = adb_query(buf);
1187 if(tmp) {
1188 printf("%s\n", tmp);
1189 return 0;
1190 } else {
1191 return 1;
1192 }
1193 }
1194
1195 /* other commands */
1196
1197 if(!strcmp(argv[0],"status-window")) {
1198 status_window(ttype, serial);
1199 return 0;
1200 }
1201
1202 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1203 return logcat(ttype, serial, argc, argv);
1204 }
1205
1206 if(!strcmp(argv[0],"ppp")) {
1207 return ppp(argc, argv);
1208 }
1209
1210 if (!strcmp(argv[0], "start-server")) {
1211 return adb_connect("host:start-server");
1212 }
1213
Christopher Tated2f54152011-04-21 12:53:28 -07001214 if (!strcmp(argv[0], "backup")) {
1215 return backup(argc, argv);
1216 }
1217
Christopher Tate702967a2011-05-17 15:52:54 -07001218 if (!strcmp(argv[0], "restore")) {
1219 return restore(argc, argv);
1220 }
1221
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001222 if (!strcmp(argv[0], "jdwp")) {
1223 int fd = adb_connect("jdwp");
1224 if (fd >= 0) {
1225 read_and_dump(fd);
1226 adb_close(fd);
1227 return 0;
1228 } else {
1229 fprintf(stderr, "error: %s\n", adb_error());
1230 return -1;
1231 }
1232 }
1233
1234 /* "adb /?" is a common idiom under Windows */
1235 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1236 help();
1237 return 0;
1238 }
1239
1240 if(!strcmp(argv[0], "version")) {
1241 version(stdout);
1242 return 0;
1243 }
1244
1245 usage();
1246 return 1;
1247}
1248
1249static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1250{
1251 char *argv[16];
1252 int argc;
1253 va_list ap;
1254
1255 va_start(ap, cmd);
1256 argc = 0;
1257
1258 if (serial) {
1259 argv[argc++] = "-s";
1260 argv[argc++] = serial;
1261 } else if (ttype == kTransportUsb) {
1262 argv[argc++] = "-d";
1263 } else if (ttype == kTransportLocal) {
1264 argv[argc++] = "-e";
1265 }
1266
1267 argv[argc++] = cmd;
1268 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1269 va_end(ap);
1270
1271#if 0
1272 int n;
1273 fprintf(stderr,"argc = %d\n",argc);
1274 for(n = 0; n < argc; n++) {
1275 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1276 }
1277#endif
1278
1279 return adb_commandline(argc, argv);
1280}
1281
1282int find_sync_dirs(const char *srcarg,
1283 char **android_srcdir_out, char **data_srcdir_out)
1284{
1285 char *android_srcdir, *data_srcdir;
1286
1287 if(srcarg == NULL) {
1288 android_srcdir = product_file("system");
1289 data_srcdir = product_file("data");
1290 } else {
1291 /* srcarg may be "data", "system" or NULL.
1292 * if srcarg is NULL, then both data and system are synced
1293 */
1294 if(strcmp(srcarg, "system") == 0) {
1295 android_srcdir = product_file("system");
1296 data_srcdir = NULL;
1297 } else if(strcmp(srcarg, "data") == 0) {
1298 android_srcdir = NULL;
1299 data_srcdir = product_file("data");
1300 } else {
1301 /* It's not "system" or "data".
1302 */
1303 return 1;
1304 }
1305 }
1306
1307 if(android_srcdir_out != NULL)
1308 *android_srcdir_out = android_srcdir;
1309 else
1310 free(android_srcdir);
1311
1312 if(data_srcdir_out != NULL)
1313 *data_srcdir_out = data_srcdir;
1314 else
1315 free(data_srcdir);
1316
1317 return 0;
1318}
1319
1320static int pm_command(transport_type transport, char* serial,
1321 int argc, char** argv)
1322{
1323 char buf[4096];
1324
1325 snprintf(buf, sizeof(buf), "shell:pm");
1326
1327 while(argc-- > 0) {
1328 char *quoted;
1329
1330 quoted = dupAndQuote(*argv++);
1331
1332 strncat(buf, " ", sizeof(buf)-1);
1333 strncat(buf, quoted, sizeof(buf)-1);
1334 free(quoted);
1335 }
1336
1337 send_shellcommand(transport, serial, buf);
1338 return 0;
1339}
1340
1341int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1342{
1343 /* if the user choose the -k option, we refuse to do it until devices are
1344 out with the option to uninstall the remaining data somehow (adb/ui) */
1345 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1346 {
1347 printf(
1348 "The -k option uninstalls the application while retaining the data/cache.\n"
1349 "At the moment, there is no way to remove the remaining data.\n"
1350 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1351 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1352 return -1;
1353 }
1354
1355 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1356 return pm_command(transport, serial, argc, argv);
1357}
1358
1359static int delete_file(transport_type transport, char* serial, char* filename)
1360{
1361 char buf[4096];
1362 char* quoted;
1363
1364 snprintf(buf, sizeof(buf), "shell:rm ");
1365 quoted = dupAndQuote(filename);
1366 strncat(buf, quoted, sizeof(buf)-1);
1367 free(quoted);
1368
1369 send_shellcommand(transport, serial, buf);
1370 return 0;
1371}
1372
Kenny Root597ea5b2011-08-05 11:19:45 -07001373static const char* get_basename(const char* filename)
1374{
1375 const char* basename = adb_dirstop(filename);
1376 if (basename) {
1377 basename++;
1378 return basename;
1379 } else {
1380 return filename;
1381 }
1382}
1383
1384static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385{
1386 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001387
Kenny Root597ea5b2011-08-05 11:19:45 -07001388 if (filename == NULL) {
1389 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001390 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001391
Kenny Root597ea5b2011-08-05 11:19:45 -07001392 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001393 fprintf(stderr, "can't find '%s' to install\n", filename);
1394 return 1;
1395 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001396
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001397 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001398 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001399 return 1;
1400 }
1401
Kenny Root597ea5b2011-08-05 11:19:45 -07001402 return 0;
1403}
1404
1405int install_app(transport_type transport, char* serial, int argc, char** argv)
1406{
1407 static const char *const DATA_DEST = "/data/local/tmp/%s";
1408 static const char *const SD_DEST = "/sdcard/tmp/%s";
1409 const char* where = DATA_DEST;
1410 char apk_dest[PATH_MAX];
1411 char verification_dest[PATH_MAX];
1412 char* apk_file;
1413 char* verification_file = NULL;
1414 int file_arg = -1;
1415 int err;
1416 int i;
1417
1418 for (i = 1; i < argc; i++) {
1419 if (*argv[i] != '-') {
1420 file_arg = i;
1421 break;
Kenny Roota031a912011-09-23 12:46:39 -07001422 } else if (!strcmp(argv[i], "-i")) {
1423 // Skip the installer package name.
1424 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001425 } else if (!strcmp(argv[i], "-s")) {
1426 where = SD_DEST;
1427 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001428 }
1429
Kenny Root597ea5b2011-08-05 11:19:45 -07001430 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001431 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001432 return 1;
1433 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001434 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001435 return 1;
1436 }
1437
1438 apk_file = argv[file_arg];
1439
1440 if (file_arg != argc - 1) {
1441 verification_file = argv[file_arg + 1];
1442 }
1443
1444 if (check_file(apk_file) || check_file(verification_file)) {
1445 return 1;
1446 }
1447
1448 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1449 if (verification_file != NULL) {
1450 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1451
1452 if (!strcmp(apk_dest, verification_dest)) {
1453 fprintf(stderr, "APK and verification file can't have the same name\n");
1454 return 1;
1455 }
1456 }
1457
1458 err = do_sync_push(apk_file, apk_dest, 1 /* verify APK */);
1459 if (err) {
1460 return err;
1461 } else {
1462 argv[file_arg] = apk_dest; /* destination name, not source location */
1463 }
1464
1465 if (verification_file != NULL) {
1466 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1467 if (err) {
1468 goto cleanup_apk;
1469 } else {
1470 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1471 }
1472 }
1473
1474 pm_command(transport, serial, argc, argv);
1475
1476 if (verification_file != NULL) {
1477 delete_file(transport, serial, verification_dest);
1478 }
1479
1480cleanup_apk:
1481 delete_file(transport, serial, apk_dest);
1482
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001483 return err;
1484}