blob: a4c2f40eee050b153798d5ed4c75f613d119491c [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov857f17a2009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
44 char **android_srcdir_out, char **data_srcdir_out);
45int install_app(transport_type transport, char* serial, int argc, char** argv);
46int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47
48static const char *gProductOutPath = NULL;
49
50static char *product_file(const char *extra)
51{
52 int n;
53 char *x;
54
55 if (gProductOutPath == NULL) {
56 fprintf(stderr, "adb: Product directory not specified; "
57 "use -p or define ANDROID_PRODUCT_OUT\n");
58 exit(1);
59 }
60
61 n = strlen(gProductOutPath) + strlen(extra) + 2;
62 x = malloc(n);
63 if (x == 0) {
64 fprintf(stderr, "adb: Out of memory (product_file())\n");
65 exit(1);
66 }
67
68 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
69 return x;
70}
71
72void version(FILE * out) {
73 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
74 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
75}
76
77void help()
78{
79 version(stderr);
80
81 fprintf(stderr,
82 "\n"
83 " -d - directs command to the only connected USB device\n"
84 " returns an error if more than one USB device is present.\n"
85 " -e - directs command to the only running emulator.\n"
86 " returns an error if more than one emulator is running.\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -070087 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson27042382012-05-30 18:11:27 -070088 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080090 " -p <product name or path> - simple product name like 'sooner', or\n"
91 " a relative/absolute path to a product\n"
92 " out directory like 'out/target/product/sooner'.\n"
93 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94 " environment variable is used, which must\n"
95 " be an absolute path.\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -070096 " devices [-l] - list all connected devices\n"
Scott Anderson27042382012-05-30 18:11:27 -070097 " ('-l' will also list device qualifiers)\n"
Mike Lockwood01c2c302010-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-Fischerc3e82b82011-04-26 12:46:05 +0200102 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400103 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800104 "\n"
105 "device commands:\n"
106 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato23595b02010-01-05 13:42:25 -0800107 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800108 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600109 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-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"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100115 " adb forward --list - list all forward socket connections.\n"
116 " the format is a list of lines with the following format:\n"
117 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800118 " adb forward <local> <remote> - forward socket connections\n"
119 " forward specs are one of: \n"
120 " tcp:<port>\n"
121 " localabstract:<unix domain socket name>\n"
122 " localreserved:<unix domain socket name>\n"
123 " localfilesystem:<unix domain socket name>\n"
124 " dev:<character device name>\n"
125 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100126 " adb forward --no-rebind <local> <remote>\n"
127 " - same as 'adb forward <local> <remote>' but fails\n"
128 " if <local> is already forwarded\n"
129 " adb forward --remove <local> - remove a specific forward socket connection\n"
130 " adb forward --remove-all - remove all forward socket connections\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800131 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700132 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
133 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800134 " ('-l' means forward-lock the app)\n"
135 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500136 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700137 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800138 " adb uninstall [-k] <package> - remove this app package from the device\n"
139 " ('-k' means keep the data and cache directories)\n"
140 " adb bugreport - return all information from the device\n"
141 " that should be included in a bug report.\n"
142 "\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700143 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
144 " - write an archive of the device's data to <file>.\n"
145 " If no -f option is supplied then the data is written\n"
146 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700147 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700148 " in the archive; the default is noapk.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700149 " (-shared|-noshared enable/disable backup of the device's\n"
150 " shared storage / SD card contents; the default is noshared.)\n"
151 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700152 " (-system|-nosystem toggles whether -all automatically includes\n"
153 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700154 " (<packages...> is the list of applications to be backed up. If\n"
155 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700156 " list is optional. Applications explicitly given on the\n"
157 " command line will be included even if -nosystem would\n"
158 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700159 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700160 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700161 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800162 " adb help - show this help message\n"
163 " adb version - show version num\n"
164 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800165 "scripting:\n"
166 " adb wait-for-device - block until device is online\n"
167 " adb start-server - ensure that there is a server running\n"
168 " adb kill-server - kill the server if it is running\n"
169 " adb get-state - prints: offline | bootloader | device\n"
170 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700171 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800172 " adb status-window - continuously print device status for a specified device\n"
173 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400174 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800175 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700176 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800177 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700178 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800179 "\n"
180 "networking:\n"
181 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500182 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800183 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
184 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
185 "\n"
186 "adb sync notes: adb sync [ <directory> ]\n"
187 " <localdir> can be interpreted in several ways:\n"
188 "\n"
189 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
190 "\n"
191 " - If it is \"system\" or \"data\", only the corresponding partition\n"
192 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000193 "\n"
194 "environmental variables:\n"
195 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
196 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
197 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
198 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800199 );
200}
201
202int usage()
203{
204 help();
205 return 1;
206}
207
208#ifdef HAVE_TERMIO_H
209static struct termios tio_save;
210
211static void stdin_raw_init(int fd)
212{
213 struct termios tio;
214
215 if(tcgetattr(fd, &tio)) return;
216 if(tcgetattr(fd, &tio_save)) return;
217
218 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
219
220 /* no timeout but request at least one character per read */
221 tio.c_cc[VTIME] = 0;
222 tio.c_cc[VMIN] = 1;
223
224 tcsetattr(fd, TCSANOW, &tio);
225 tcflush(fd, TCIFLUSH);
226}
227
228static void stdin_raw_restore(int fd)
229{
230 tcsetattr(fd, TCSANOW, &tio_save);
231 tcflush(fd, TCIFLUSH);
232}
233#endif
234
235static void read_and_dump(int fd)
236{
237 char buf[4096];
238 int len;
239
240 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700241 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800242 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700243 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800244 if(len == 0) {
245 break;
246 }
247
248 if(len < 0) {
249 if(errno == EINTR) continue;
250 break;
251 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400252 fwrite(buf, 1, len, stdout);
253 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800254 }
255}
256
Christopher Tate73779122011-04-21 12:53:28 -0700257static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700258 const size_t BUFSIZE = 32 * 1024;
259 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700260 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700261 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700262
263 D("copy_to_file(%d -> %d)\n", inFd, outFd);
264 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700265 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700266 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700267 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700268 break;
269 }
270 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700271 if (errno == EINTR) {
272 D("copy_to_file() : EINTR, retrying\n");
273 continue;
274 }
Christopher Tate73779122011-04-21 12:53:28 -0700275 D("copy_to_file() : error %d\n", errno);
276 break;
277 }
278 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700279 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700280 }
Christopher Tatefba22972011-06-01 17:56:23 -0700281 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700282 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700283}
284
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800285static void *stdin_read_thread(void *x)
286{
287 int fd, fdi;
288 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800289 int r, n;
290 int state = 0;
291
292 int *fds = (int*) x;
293 fd = fds[0];
294 fdi = fds[1];
295 free(fds);
296
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800297 for(;;) {
298 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700299 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800300 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700301 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800302 if(r == 0) break;
303 if(r < 0) {
304 if(errno == EINTR) continue;
305 break;
306 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400307 for(n = 0; n < r; n++){
308 switch(buf[n]) {
309 case '\n':
310 state = 1;
311 break;
312 case '\r':
313 state = 1;
314 break;
315 case '~':
316 if(state == 1) state++;
317 break;
318 case '.':
319 if(state == 2) {
320 fprintf(stderr,"\n* disconnect *\n");
321#ifdef HAVE_TERMIO_H
322 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800323#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400324 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800325 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400326 default:
327 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800328 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800329 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800330 r = adb_write(fd, buf, r);
331 if(r <= 0) {
332 break;
333 }
334 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800335 return 0;
336}
337
338int interactive_shell(void)
339{
340 adb_thread_t thr;
341 int fdi, fd;
342 int *fds;
343
344 fd = adb_connect("shell:");
345 if(fd < 0) {
346 fprintf(stderr,"error: %s\n", adb_error());
347 return 1;
348 }
349 fdi = 0; //dup(0);
350
351 fds = malloc(sizeof(int) * 2);
352 fds[0] = fd;
353 fds[1] = fdi;
354
355#ifdef HAVE_TERMIO_H
356 stdin_raw_init(fdi);
357#endif
358 adb_thread_create(&thr, stdin_read_thread, fds);
359 read_and_dump(fd);
360#ifdef HAVE_TERMIO_H
361 stdin_raw_restore(fdi);
362#endif
363 return 0;
364}
365
366
367static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
368{
369 if (serial) {
370 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
371 } else {
372 const char* prefix = "host";
373 if (ttype == kTransportUsb)
374 prefix = "host-usb";
375 else if (ttype == kTransportLocal)
376 prefix = "host-local";
377
378 snprintf(buffer, buflen, "%s:%s", prefix, command);
379 }
380}
381
Doug Zongker6b217ed2012-01-09 14:54:53 -0800382int adb_download_buffer(const char *service, const void* data, int sz,
383 unsigned progress)
384{
385 char buf[4096];
386 unsigned total;
387 int fd;
388 const unsigned char *ptr;
389
390 sprintf(buf,"%s:%d", service, sz);
391 fd = adb_connect(buf);
392 if(fd < 0) {
393 fprintf(stderr,"error: %s\n", adb_error());
394 return -1;
395 }
396
397 int opt = CHUNK_SIZE;
398 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
399
400 total = sz;
401 ptr = data;
402
403 if(progress) {
404 char *x = strrchr(service, ':');
405 if(x) service = x + 1;
406 }
407
408 while(sz > 0) {
409 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
410 if(writex(fd, ptr, xfer)) {
411 adb_status(fd);
412 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
413 return -1;
414 }
415 sz -= xfer;
416 ptr += xfer;
417 if(progress) {
418 printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
419 fflush(stdout);
420 }
421 }
422 if(progress) {
423 printf("\n");
424 }
425
426 if(readx(fd, buf, 4)){
427 fprintf(stderr,"* error reading response *\n");
428 adb_close(fd);
429 return -1;
430 }
431 if(memcmp(buf, "OKAY", 4)) {
432 buf[4] = 0;
433 fprintf(stderr,"* error response '%s' *\n", buf);
434 adb_close(fd);
435 return -1;
436 }
437
438 adb_close(fd);
439 return 0;
440}
441
442
443int adb_download(const char *service, const char *fn, unsigned progress)
444{
445 void *data;
446 unsigned sz;
447
448 data = load_file(fn, &sz);
449 if(data == 0) {
450 fprintf(stderr,"* cannot read '%s' *\n", service);
451 return -1;
452 }
453
454 int status = adb_download_buffer(service, data, sz, progress);
455 free(data);
456 return status;
457}
458
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800459static void status_window(transport_type ttype, const char* serial)
460{
461 char command[4096];
462 char *state = 0;
463 char *laststate = 0;
464
465 /* silence stderr */
466#ifdef _WIN32
467 /* XXX: TODO */
468#else
469 int fd;
470 fd = unix_open("/dev/null", O_WRONLY);
471 dup2(fd, 2);
472 adb_close(fd);
473#endif
474
475 format_host_command(command, sizeof command, "get-state", ttype, serial);
476
477 for(;;) {
478 adb_sleep_ms(250);
479
480 if(state) {
481 free(state);
482 state = 0;
483 }
484
485 state = adb_query(command);
486
487 if(state) {
488 if(laststate && !strcmp(state,laststate)){
489 continue;
490 } else {
491 if(laststate) free(laststate);
492 laststate = strdup(state);
493 }
494 }
495
496 printf("%c[2J%c[2H", 27, 27);
497 printf("Android Debug Bridge\n");
498 printf("State: %s\n", state ? state : "offline");
499 fflush(stdout);
500 }
501}
502
503/** duplicate string and quote all \ " ( ) chars + space character. */
504static char *
505dupAndQuote(const char *s)
506{
507 const char *ts;
508 size_t alloc_len;
509 char *ret;
510 char *dest;
511
512 ts = s;
513
514 alloc_len = 0;
515
516 for( ;*ts != '\0'; ts++) {
517 alloc_len++;
518 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
519 alloc_len++;
520 }
521 }
522
523 ret = (char *)malloc(alloc_len + 1);
524
525 ts = s;
526 dest = ret;
527
528 for ( ;*ts != '\0'; ts++) {
529 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
530 *dest++ = '\\';
531 }
532
533 *dest++ = *ts;
534 }
535
536 *dest++ = '\0';
537
538 return ret;
539}
540
541/**
542 * Run ppp in "notty" mode against a resource listed as the first parameter
543 * eg:
544 *
545 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
546 *
547 */
548int ppp(int argc, char **argv)
549{
550#ifdef HAVE_WIN32_PROC
551 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
552 return -1;
553#else
554 char *adb_service_name;
555 pid_t pid;
556 int fd;
557
558 if (argc < 2) {
559 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
560 argv[0]);
561
562 return 1;
563 }
564
565 adb_service_name = argv[1];
566
567 fd = adb_connect(adb_service_name);
568
569 if(fd < 0) {
570 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
571 adb_service_name, adb_error());
572 return 1;
573 }
574
575 pid = fork();
576
577 if (pid < 0) {
578 perror("from fork()");
579 return 1;
580 } else if (pid == 0) {
581 int err;
582 int i;
583 const char **ppp_args;
584
585 // copy args
586 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
587 ppp_args[0] = "pppd";
588 for (i = 2 ; i < argc ; i++) {
589 //argv[2] and beyond become ppp_args[1] and beyond
590 ppp_args[i - 1] = argv[i];
591 }
592 ppp_args[i-1] = NULL;
593
594 // child side
595
596 dup2(fd, STDIN_FILENO);
597 dup2(fd, STDOUT_FILENO);
598 adb_close(STDERR_FILENO);
599 adb_close(fd);
600
601 err = execvp("pppd", (char * const *)ppp_args);
602
603 if (err < 0) {
604 perror("execing pppd");
605 }
606 exit(-1);
607 } else {
608 // parent side
609
610 adb_close(fd);
611 return 0;
612 }
613#endif /* !HAVE_WIN32_PROC */
614}
615
616static int send_shellcommand(transport_type transport, char* serial, char* buf)
617{
618 int fd, ret;
619
620 for(;;) {
621 fd = adb_connect(buf);
622 if(fd >= 0)
623 break;
624 fprintf(stderr,"- waiting for device -\n");
625 adb_sleep_ms(1000);
626 do_cmd(transport, serial, "wait-for-device", 0);
627 }
628
629 read_and_dump(fd);
630 ret = adb_close(fd);
631 if (ret)
632 perror("close");
633
634 return ret;
635}
636
637static int logcat(transport_type transport, char* serial, int argc, char **argv)
638{
639 char buf[4096];
640
641 char *log_tags;
642 char *quoted_log_tags;
643
644 log_tags = getenv("ANDROID_LOG_TAGS");
645 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
646
647 snprintf(buf, sizeof(buf),
648 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
649 quoted_log_tags);
650
651 free(quoted_log_tags);
652
Christopher Tate7b9b5162011-11-30 13:00:33 -0800653 if (!strcmp(argv[0],"longcat")) {
654 strncat(buf, " -v long", sizeof(buf)-1);
655 }
656
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800657 argc -= 1;
658 argv += 1;
659 while(argc-- > 0) {
660 char *quoted;
661
662 quoted = dupAndQuote (*argv++);
663
664 strncat(buf, " ", sizeof(buf)-1);
665 strncat(buf, quoted, sizeof(buf)-1);
666 free(quoted);
667 }
668
669 send_shellcommand(transport, serial, buf);
670 return 0;
671}
672
Christopher Tate1e9f2392011-12-08 19:04:34 -0800673static int mkdirs(char *path)
674{
675 int ret;
676 char *x = path + 1;
677
678 for(;;) {
679 x = adb_dirstart(x);
680 if(x == 0) return 0;
681 *x = 0;
682 ret = adb_mkdir(path, 0775);
683 *x = OS_PATH_SEPARATOR;
684 if((ret < 0) && (errno != EEXIST)) {
685 return ret;
686 }
687 x++;
688 }
689 return 0;
690}
691
Christopher Tate73779122011-04-21 12:53:28 -0700692static int backup(int argc, char** argv) {
693 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800694 char default_name[32];
695 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700696 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700697 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700698
Christopher Tatefba22972011-06-01 17:56:23 -0700699 /* find, extract, and use any -f argument */
700 for (i = 1; i < argc; i++) {
701 if (!strcmp("-f", argv[i])) {
702 if (i == argc-1) {
703 fprintf(stderr, "adb: -f passed with no filename\n");
704 return usage();
705 }
706 filename = argv[i+1];
707 for (j = i+2; j <= argc; ) {
708 argv[i++] = argv[j++];
709 }
710 argc -= 2;
711 argv[argc] = NULL;
712 }
Christopher Tate73779122011-04-21 12:53:28 -0700713 }
714
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700715 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
716 if (argc < 2) return usage();
717
Christopher Tate1e9f2392011-12-08 19:04:34 -0800718 adb_unlink(filename);
719 mkdirs((char *)filename);
720 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700721 if (outFd < 0) {
722 fprintf(stderr, "adb: unable to open file %s\n", filename);
723 return -1;
724 }
725
726 snprintf(buf, sizeof(buf), "backup");
727 for (argc--, argv++; argc; argc--, argv++) {
728 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
729 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
730 }
731
732 D("backup. filename=%s buf=%s\n", filename, buf);
733 fd = adb_connect(buf);
734 if (fd < 0) {
735 fprintf(stderr, "adb: unable to connect for backup\n");
736 adb_close(outFd);
737 return -1;
738 }
739
Christopher Tate9c829102012-01-06 15:43:03 -0800740 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700741 copy_to_file(fd, outFd);
742
743 adb_close(fd);
744 adb_close(outFd);
745 return 0;
746}
747
Christopher Tatecf5379b2011-05-17 15:52:54 -0700748static int restore(int argc, char** argv) {
749 const char* filename;
750 int fd, tarFd;
751
752 if (argc != 2) return usage();
753
754 filename = argv[1];
755 tarFd = adb_open(filename, O_RDONLY);
756 if (tarFd < 0) {
757 fprintf(stderr, "adb: unable to open file %s\n", filename);
758 return -1;
759 }
760
761 fd = adb_connect("restore:");
762 if (fd < 0) {
763 fprintf(stderr, "adb: unable to connect for backup\n");
764 adb_close(tarFd);
765 return -1;
766 }
767
Christopher Tate9c829102012-01-06 15:43:03 -0800768 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700769 copy_to_file(tarFd, fd);
770
771 adb_close(fd);
772 adb_close(tarFd);
773 return 0;
774}
775
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800776#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
777static int top_works(const char *top)
778{
779 if (top != NULL && adb_is_absolute_host_path(top)) {
780 char path_buf[PATH_MAX];
781 snprintf(path_buf, sizeof(path_buf),
782 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
783 return access(path_buf, F_OK) == 0;
784 }
785 return 0;
786}
787
788static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
789{
790 strcpy(path_buf, indir);
791 while (1) {
792 if (top_works(path_buf)) {
793 return path_buf;
794 }
795 char *s = adb_dirstop(path_buf);
796 if (s != NULL) {
797 *s = '\0';
798 } else {
799 path_buf[0] = '\0';
800 return NULL;
801 }
802 }
803}
804
805static char *find_top(char path_buf[PATH_MAX])
806{
807 char *top = getenv("ANDROID_BUILD_TOP");
808 if (top != NULL && top[0] != '\0') {
809 if (!top_works(top)) {
810 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
811 return NULL;
812 }
813 } else {
814 top = getenv("TOP");
815 if (top != NULL && top[0] != '\0') {
816 if (!top_works(top)) {
817 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
818 return NULL;
819 }
820 } else {
821 top = NULL;
822 }
823 }
824
825 if (top != NULL) {
826 /* The environment pointed to a top directory that works.
827 */
828 strcpy(path_buf, top);
829 return path_buf;
830 }
831
832 /* The environment didn't help. Walk up the tree from the CWD
833 * to see if we can find the top.
834 */
835 char dir[PATH_MAX];
836 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
837 if (top == NULL) {
838 /* If the CWD isn't under a good-looking top, see if the
839 * executable is.
840 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100841 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800842 top = find_top_from(dir, path_buf);
843 }
844 return top;
845}
846
847/* <hint> may be:
848 * - A simple product name
849 * e.g., "sooner"
850TODO: debug? sooner-debug, sooner:debug?
851 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
852 * e.g., "out/target/product/sooner"
853 * - An absolute path to the PRODUCT_OUT dir
854 * e.g., "/src/device/out/target/product/sooner"
855 *
856 * Given <hint>, try to construct an absolute path to the
857 * ANDROID_PRODUCT_OUT dir.
858 */
859static const char *find_product_out_path(const char *hint)
860{
861 static char path_buf[PATH_MAX];
862
863 if (hint == NULL || hint[0] == '\0') {
864 return NULL;
865 }
866
867 /* If it's already absolute, don't bother doing any work.
868 */
869 if (adb_is_absolute_host_path(hint)) {
870 strcpy(path_buf, hint);
871 return path_buf;
872 }
873
874 /* If there are any slashes in it, assume it's a relative path;
875 * make it absolute.
876 */
877 if (adb_dirstart(hint) != NULL) {
878 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
879 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
880 return NULL;
881 }
882 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
883 fprintf(stderr, "adb: Couldn't assemble path\n");
884 return NULL;
885 }
886 strcat(path_buf, OS_PATH_SEPARATOR_STR);
887 strcat(path_buf, hint);
888 return path_buf;
889 }
890
891 /* It's a string without any slashes. Try to do something with it.
892 *
893 * Try to find the root of the build tree, and build a PRODUCT_OUT
894 * path from there.
895 */
896 char top_buf[PATH_MAX];
897 const char *top = find_top(top_buf);
898 if (top == NULL) {
899 fprintf(stderr, "adb: Couldn't find top of build tree\n");
900 return NULL;
901 }
902//TODO: if we have a way to indicate debug, look in out/debug/target/...
903 snprintf(path_buf, sizeof(path_buf),
904 "%s" OS_PATH_SEPARATOR_STR
905 "out" OS_PATH_SEPARATOR_STR
906 "target" OS_PATH_SEPARATOR_STR
907 "product" OS_PATH_SEPARATOR_STR
908 "%s", top_buf, hint);
909 if (access(path_buf, F_OK) < 0) {
910 fprintf(stderr, "adb: Couldn't find a product dir "
911 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
912 return NULL;
913 }
914 return path_buf;
915}
916
917int adb_commandline(int argc, char **argv)
918{
919 char buf[4096];
920 int no_daemon = 0;
921 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100922 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800923 int persist = 0;
924 int r;
925 int quote;
926 transport_type ttype = kTransportAny;
927 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100928 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800929
930 /* If defined, this should be an absolute path to
931 * the directory containing all of the various system images
932 * for a particular product. If not defined, and the adb
933 * command requires this information, then the user must
934 * specify the path using "-p".
935 */
936 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
937 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
938 gProductOutPath = NULL;
939 }
940 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
941
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700942 serial = getenv("ANDROID_SERIAL");
943
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100944 /* Validate and assign the server port */
945 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
946 int server_port = DEFAULT_ADB_PORT;
947 if (server_port_str && strlen(server_port_str) > 0) {
948 server_port = (int) strtol(server_port_str, NULL, 0);
949 if (server_port <= 0) {
950 fprintf(stderr,
951 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
952 server_port_str);
953 return usage();
954 }
955 }
956
957 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800958 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100959 if(!strcmp(argv[0],"server")) {
960 is_server = 1;
961 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800962 no_daemon = 1;
963 } else if (!strcmp(argv[0], "fork-server")) {
964 /* this is a special flag used only when the ADB client launches the ADB Server */
965 is_daemon = 1;
966 } else if(!strcmp(argv[0],"persist")) {
967 persist = 1;
968 } else if(!strncmp(argv[0], "-p", 2)) {
969 const char *product = NULL;
970 if (argv[0][2] == '\0') {
971 if (argc < 2) return usage();
972 product = argv[1];
973 argc--;
974 argv++;
975 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -0700976 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800977 }
978 gProductOutPath = find_product_out_path(product);
979 if (gProductOutPath == NULL) {
980 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
981 product);
982 return usage();
983 }
984 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
985 if (isdigit(argv[0][2])) {
986 serial = argv[0] + 2;
987 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100988 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800989 serial = argv[1];
990 argc--;
991 argv++;
992 }
993 } else if (!strcmp(argv[0],"-d")) {
994 ttype = kTransportUsb;
995 } else if (!strcmp(argv[0],"-e")) {
996 ttype = kTransportLocal;
997 } else {
998 /* out of recognized modifiers and flags */
999 break;
1000 }
1001 argc--;
1002 argv++;
1003 }
1004
1005 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001006 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001007
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001008 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001009 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001010 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001011 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001012 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001013 }
1014 if(r) {
1015 fprintf(stderr,"* could not start server *\n");
1016 }
1017 return r;
1018 }
1019
1020top:
1021 if(argc == 0) {
1022 return usage();
1023 }
1024
1025 /* adb_connect() commands */
1026
1027 if(!strcmp(argv[0], "devices")) {
1028 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001029 char *listopt;
1030 if (argc < 2)
1031 listopt = "";
1032 else if (argc == 2 && !strcmp(argv[1], "-l"))
1033 listopt = argv[1];
1034 else {
1035 fprintf(stderr, "Usage: adb devices [-l]\n");
1036 return 1;
1037 }
1038 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001039 tmp = adb_query(buf);
1040 if(tmp) {
1041 printf("List of devices attached \n");
1042 printf("%s\n", tmp);
1043 return 0;
1044 } else {
1045 return 1;
1046 }
1047 }
1048
Mike Lockwood01c2c302010-05-24 10:44:35 -04001049 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001050 char *tmp;
1051 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001052 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001053 return 1;
1054 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001055 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1056 tmp = adb_query(buf);
1057 if(tmp) {
1058 printf("%s\n", tmp);
1059 return 0;
1060 } else {
1061 return 1;
1062 }
1063 }
1064
1065 if(!strcmp(argv[0], "disconnect")) {
1066 char *tmp;
1067 if (argc > 2) {
1068 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1069 return 1;
1070 }
1071 if (argc == 2) {
1072 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1073 } else {
1074 snprintf(buf, sizeof buf, "host:disconnect:");
1075 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001076 tmp = adb_query(buf);
1077 if(tmp) {
1078 printf("%s\n", tmp);
1079 return 0;
1080 } else {
1081 return 1;
1082 }
1083 }
1084
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001085 if (!strcmp(argv[0], "emu")) {
1086 return adb_send_emulator_command(argc, argv);
1087 }
1088
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001089 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001090 int r;
1091 int fd;
1092
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001093 char h = (argv[0][0] == 'h');
1094
1095 if (h) {
1096 printf("\x1b[41;33m");
1097 fflush(stdout);
1098 }
1099
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001100 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001101 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001102 r = interactive_shell();
1103 if (h) {
1104 printf("\x1b[0m");
1105 fflush(stdout);
1106 }
1107 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001108 }
1109
1110 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1111 argc -= 2;
1112 argv += 2;
1113 while(argc-- > 0) {
1114 strcat(buf, " ");
1115
1116 /* quote empty strings and strings with spaces */
1117 quote = (**argv == 0 || strchr(*argv, ' '));
1118 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001119 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001120 strcat(buf, *argv++);
1121 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001122 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001123 }
1124
1125 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001126 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001127 fd = adb_connect(buf);
1128 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001129 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001130 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001131 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001132 adb_close(fd);
1133 r = 0;
1134 } else {
1135 fprintf(stderr,"error: %s\n", adb_error());
1136 r = -1;
1137 }
1138
1139 if(persist) {
1140 fprintf(stderr,"\n- waiting for device -\n");
1141 adb_sleep_ms(1000);
1142 do_cmd(ttype, serial, "wait-for-device", 0);
1143 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001144 if (h) {
1145 printf("\x1b[0m");
1146 fflush(stdout);
1147 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001148 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001149 return r;
1150 }
1151 }
1152 }
1153
1154 if(!strcmp(argv[0], "kill-server")) {
1155 int fd;
1156 fd = _adb_connect("host:kill");
1157 if(fd == -1) {
1158 fprintf(stderr,"* server not running *\n");
1159 return 1;
1160 }
1161 return 0;
1162 }
1163
Doug Zongker6b217ed2012-01-09 14:54:53 -08001164 if(!strcmp(argv[0], "sideload")) {
1165 if(argc != 2) return usage();
1166 if(adb_download("sideload", argv[1], 1)) {
1167 return 1;
1168 } else {
1169 return 0;
1170 }
1171 }
1172
Mike Lockwood26b88e32009-08-24 15:58:40 -07001173 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001174 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001175 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001176 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001177 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001178 if (!strcmp(argv[0], "reboot-bootloader"))
1179 snprintf(command, sizeof(command), "reboot:bootloader");
1180 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001181 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001182 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001183 snprintf(command, sizeof(command), "%s:", argv[0]);
1184 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001185 if(fd >= 0) {
1186 read_and_dump(fd);
1187 adb_close(fd);
1188 return 0;
1189 }
1190 fprintf(stderr,"error: %s\n", adb_error());
1191 return 1;
1192 }
1193
Mike Lockwood78589f32009-09-03 14:54:58 -04001194 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001195 if (argc != 1) return usage();
1196 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001197 return 0;
1198 }
1199
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001200 /* adb_command() wrapper commands */
1201
1202 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1203 char* service = argv[0];
1204 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1205 if (ttype == kTransportUsb) {
1206 service = "wait-for-usb";
1207 } else if (ttype == kTransportLocal) {
1208 service = "wait-for-local";
1209 } else {
1210 service = "wait-for-any";
1211 }
1212 }
1213
1214 format_host_command(buf, sizeof buf, service, ttype, serial);
1215
1216 if (adb_command(buf)) {
1217 D("failure: %s *\n",adb_error());
1218 fprintf(stderr,"error: %s\n", adb_error());
1219 return 1;
1220 }
1221
1222 /* Allow a command to be run after wait-for-device,
1223 * e.g. 'adb wait-for-device shell'.
1224 */
1225 if(argc > 1) {
1226 argc--;
1227 argv++;
1228 goto top;
1229 }
1230 return 0;
1231 }
1232
1233 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001234 char host_prefix[64];
1235 char remove = 0;
1236 char remove_all = 0;
1237 char list = 0;
1238 char no_rebind = 0;
1239
1240 // Parse options here.
1241 while (argc > 1 && argv[1][0] == '-') {
1242 if (!strcmp(argv[1], "--list"))
1243 list = 1;
1244 else if (!strcmp(argv[1], "--remove"))
1245 remove = 1;
1246 else if (!strcmp(argv[1], "--remove-all"))
1247 remove_all = 1;
1248 else if (!strcmp(argv[1], "--no-rebind"))
1249 no_rebind = 1;
1250 else {
1251 return usage();
1252 }
1253 argc--;
1254 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001255 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001256
1257 // Ensure we can only use one option at a time.
1258 if (list + remove + remove_all + no_rebind > 1) {
1259 return usage();
1260 }
1261
1262 // Determine the <host-prefix> for this command.
1263 if (serial) {
1264 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1265 serial);
1266 } else if (ttype == kTransportUsb) {
1267 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1268 } else if (ttype == kTransportLocal) {
1269 snprintf(host_prefix, sizeof host_prefix, "host-local");
1270 } else {
1271 snprintf(host_prefix, sizeof host_prefix, "host");
1272 }
1273
1274 // Implement forward --list
1275 if (list) {
1276 if (argc != 1)
1277 return usage();
1278 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1279 char* forwards = adb_query(buf);
1280 if (forwards == NULL) {
1281 fprintf(stderr, "error: %s\n", adb_error());
1282 return 1;
1283 }
1284 printf("%s", forwards);
1285 free(forwards);
1286 return 0;
1287 }
1288
1289 // Implement forward --remove-all
1290 else if (remove_all) {
1291 if (argc != 1)
1292 return usage();
1293 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1294 }
1295
1296 // Implement forward --remove <local>
1297 else if (remove) {
1298 if (argc != 2)
1299 return usage();
1300 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1301 }
1302 // Or implement one of:
1303 // forward <local> <remote>
1304 // forward --no-rebind <local> <remote>
1305 else
1306 {
1307 if (argc != 3)
1308 return usage();
1309 const char* command = no_rebind ? "forward:norebind:" : "forward";
1310 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1311 }
1312
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001313 if(adb_command(buf)) {
1314 fprintf(stderr,"error: %s\n", adb_error());
1315 return 1;
1316 }
1317 return 0;
1318 }
1319
1320 /* do_sync_*() commands */
1321
1322 if(!strcmp(argv[0], "ls")) {
1323 if(argc != 2) return usage();
1324 return do_sync_ls(argv[1]);
1325 }
1326
1327 if(!strcmp(argv[0], "push")) {
1328 if(argc != 3) return usage();
1329 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1330 }
1331
1332 if(!strcmp(argv[0], "pull")) {
Joe Onorato23595b02010-01-05 13:42:25 -08001333 if (argc == 2) {
1334 return do_sync_pull(argv[1], ".");
1335 } else if (argc == 3) {
1336 return do_sync_pull(argv[1], argv[2]);
1337 } else {
1338 return usage();
1339 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001340 }
1341
1342 if(!strcmp(argv[0], "install")) {
1343 if (argc < 2) return usage();
1344 return install_app(ttype, serial, argc, argv);
1345 }
1346
1347 if(!strcmp(argv[0], "uninstall")) {
1348 if (argc < 2) return usage();
1349 return uninstall_app(ttype, serial, argc, argv);
1350 }
1351
1352 if(!strcmp(argv[0], "sync")) {
1353 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001354 int listonly = 0;
1355
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001356 int ret;
1357 if(argc < 2) {
1358 /* No local path was specified. */
1359 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001360 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1361 listonly = 1;
1362 if (argc == 3) {
1363 srcarg = argv[2];
1364 } else {
1365 srcarg = NULL;
1366 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001367 } else if(argc == 2) {
1368 /* A local path or "android"/"data" arg was specified. */
1369 srcarg = argv[1];
1370 } else {
1371 return usage();
1372 }
1373 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1374 if(ret != 0) return usage();
1375
1376 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001377 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001378 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001379 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001380
1381 free(android_srcpath);
1382 free(data_srcpath);
1383 return ret;
1384 }
1385
1386 /* passthrough commands */
1387
1388 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001389 !strcmp(argv[0],"get-serialno") ||
1390 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001391 {
1392 char *tmp;
1393
1394 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1395 tmp = adb_query(buf);
1396 if(tmp) {
1397 printf("%s\n", tmp);
1398 return 0;
1399 } else {
1400 return 1;
1401 }
1402 }
1403
1404 /* other commands */
1405
1406 if(!strcmp(argv[0],"status-window")) {
1407 status_window(ttype, serial);
1408 return 0;
1409 }
1410
Christopher Tate7b9b5162011-11-30 13:00:33 -08001411 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001412 return logcat(ttype, serial, argc, argv);
1413 }
1414
1415 if(!strcmp(argv[0],"ppp")) {
1416 return ppp(argc, argv);
1417 }
1418
1419 if (!strcmp(argv[0], "start-server")) {
1420 return adb_connect("host:start-server");
1421 }
1422
Christopher Tate73779122011-04-21 12:53:28 -07001423 if (!strcmp(argv[0], "backup")) {
1424 return backup(argc, argv);
1425 }
1426
Christopher Tatecf5379b2011-05-17 15:52:54 -07001427 if (!strcmp(argv[0], "restore")) {
1428 return restore(argc, argv);
1429 }
1430
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001431 if (!strcmp(argv[0], "jdwp")) {
1432 int fd = adb_connect("jdwp");
1433 if (fd >= 0) {
1434 read_and_dump(fd);
1435 adb_close(fd);
1436 return 0;
1437 } else {
1438 fprintf(stderr, "error: %s\n", adb_error());
1439 return -1;
1440 }
1441 }
1442
1443 /* "adb /?" is a common idiom under Windows */
1444 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1445 help();
1446 return 0;
1447 }
1448
1449 if(!strcmp(argv[0], "version")) {
1450 version(stdout);
1451 return 0;
1452 }
1453
1454 usage();
1455 return 1;
1456}
1457
1458static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1459{
1460 char *argv[16];
1461 int argc;
1462 va_list ap;
1463
1464 va_start(ap, cmd);
1465 argc = 0;
1466
1467 if (serial) {
1468 argv[argc++] = "-s";
1469 argv[argc++] = serial;
1470 } else if (ttype == kTransportUsb) {
1471 argv[argc++] = "-d";
1472 } else if (ttype == kTransportLocal) {
1473 argv[argc++] = "-e";
1474 }
1475
1476 argv[argc++] = cmd;
1477 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1478 va_end(ap);
1479
1480#if 0
1481 int n;
1482 fprintf(stderr,"argc = %d\n",argc);
1483 for(n = 0; n < argc; n++) {
1484 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1485 }
1486#endif
1487
1488 return adb_commandline(argc, argv);
1489}
1490
1491int find_sync_dirs(const char *srcarg,
1492 char **android_srcdir_out, char **data_srcdir_out)
1493{
1494 char *android_srcdir, *data_srcdir;
1495
1496 if(srcarg == NULL) {
1497 android_srcdir = product_file("system");
1498 data_srcdir = product_file("data");
1499 } else {
1500 /* srcarg may be "data", "system" or NULL.
1501 * if srcarg is NULL, then both data and system are synced
1502 */
1503 if(strcmp(srcarg, "system") == 0) {
1504 android_srcdir = product_file("system");
1505 data_srcdir = NULL;
1506 } else if(strcmp(srcarg, "data") == 0) {
1507 android_srcdir = NULL;
1508 data_srcdir = product_file("data");
1509 } else {
1510 /* It's not "system" or "data".
1511 */
1512 return 1;
1513 }
1514 }
1515
1516 if(android_srcdir_out != NULL)
1517 *android_srcdir_out = android_srcdir;
1518 else
1519 free(android_srcdir);
1520
1521 if(data_srcdir_out != NULL)
1522 *data_srcdir_out = data_srcdir;
1523 else
1524 free(data_srcdir);
1525
1526 return 0;
1527}
1528
1529static int pm_command(transport_type transport, char* serial,
1530 int argc, char** argv)
1531{
1532 char buf[4096];
1533
1534 snprintf(buf, sizeof(buf), "shell:pm");
1535
1536 while(argc-- > 0) {
1537 char *quoted;
1538
1539 quoted = dupAndQuote(*argv++);
1540
1541 strncat(buf, " ", sizeof(buf)-1);
1542 strncat(buf, quoted, sizeof(buf)-1);
1543 free(quoted);
1544 }
1545
1546 send_shellcommand(transport, serial, buf);
1547 return 0;
1548}
1549
1550int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1551{
1552 /* if the user choose the -k option, we refuse to do it until devices are
1553 out with the option to uninstall the remaining data somehow (adb/ui) */
1554 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1555 {
1556 printf(
1557 "The -k option uninstalls the application while retaining the data/cache.\n"
1558 "At the moment, there is no way to remove the remaining data.\n"
1559 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1560 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1561 return -1;
1562 }
1563
1564 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1565 return pm_command(transport, serial, argc, argv);
1566}
1567
1568static int delete_file(transport_type transport, char* serial, char* filename)
1569{
1570 char buf[4096];
1571 char* quoted;
1572
1573 snprintf(buf, sizeof(buf), "shell:rm ");
1574 quoted = dupAndQuote(filename);
1575 strncat(buf, quoted, sizeof(buf)-1);
1576 free(quoted);
1577
1578 send_shellcommand(transport, serial, buf);
1579 return 0;
1580}
1581
Kenny Root3802c992011-08-05 11:19:45 -07001582static const char* get_basename(const char* filename)
1583{
1584 const char* basename = adb_dirstop(filename);
1585 if (basename) {
1586 basename++;
1587 return basename;
1588 } else {
1589 return filename;
1590 }
1591}
1592
1593static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001594{
1595 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001596
Kenny Root3802c992011-08-05 11:19:45 -07001597 if (filename == NULL) {
1598 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001599 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001600
Kenny Root3802c992011-08-05 11:19:45 -07001601 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001602 fprintf(stderr, "can't find '%s' to install\n", filename);
1603 return 1;
1604 }
Kenny Root3802c992011-08-05 11:19:45 -07001605
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001606 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001607 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001608 return 1;
1609 }
1610
Kenny Root3802c992011-08-05 11:19:45 -07001611 return 0;
1612}
1613
1614int install_app(transport_type transport, char* serial, int argc, char** argv)
1615{
1616 static const char *const DATA_DEST = "/data/local/tmp/%s";
1617 static const char *const SD_DEST = "/sdcard/tmp/%s";
1618 const char* where = DATA_DEST;
1619 char apk_dest[PATH_MAX];
1620 char verification_dest[PATH_MAX];
1621 char* apk_file;
1622 char* verification_file = NULL;
1623 int file_arg = -1;
1624 int err;
1625 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001626 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001627
1628 for (i = 1; i < argc; i++) {
1629 if (*argv[i] != '-') {
1630 file_arg = i;
1631 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001632 } else if (!strcmp(argv[i], "-i")) {
1633 // Skip the installer package name.
1634 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001635 } else if (!strcmp(argv[i], "-s")) {
1636 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001637 } else if (!strcmp(argv[i], "--algo")) {
1638 verify_apk = 0;
1639 i++;
1640 } else if (!strcmp(argv[i], "--iv")) {
1641 verify_apk = 0;
1642 i++;
1643 } else if (!strcmp(argv[i], "--key")) {
1644 verify_apk = 0;
1645 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001646 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001647 }
1648
Kenny Root3802c992011-08-05 11:19:45 -07001649 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001650 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001651 return 1;
1652 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001653 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001654 return 1;
1655 }
1656
1657 apk_file = argv[file_arg];
1658
1659 if (file_arg != argc - 1) {
1660 verification_file = argv[file_arg + 1];
1661 }
1662
1663 if (check_file(apk_file) || check_file(verification_file)) {
1664 return 1;
1665 }
1666
1667 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1668 if (verification_file != NULL) {
1669 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1670
1671 if (!strcmp(apk_dest, verification_dest)) {
1672 fprintf(stderr, "APK and verification file can't have the same name\n");
1673 return 1;
1674 }
1675 }
1676
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001677 err = do_sync_push(apk_file, apk_dest, verify_apk);
Kenny Root3802c992011-08-05 11:19:45 -07001678 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001679 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001680 } else {
1681 argv[file_arg] = apk_dest; /* destination name, not source location */
1682 }
1683
1684 if (verification_file != NULL) {
1685 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1686 if (err) {
1687 goto cleanup_apk;
1688 } else {
1689 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1690 }
1691 }
1692
1693 pm_command(transport, serial, argc, argv);
1694
Kenny Root58d5f222012-03-26 16:14:02 -07001695cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001696 if (verification_file != NULL) {
1697 delete_file(transport, serial, verification_dest);
1698 }
1699
Kenny Root3802c992011-08-05 11:19:45 -07001700 delete_file(transport, serial, apk_dest);
1701
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001702 return err;
1703}