blob: 24cbb5a6f3ee34cd8e09999c6a9d749461ddb35b [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov31664102009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
44 char **android_srcdir_out, char **data_srcdir_out);
45int install_app(transport_type transport, char* serial, int argc, char** argv);
46int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47
48static const char *gProductOutPath = NULL;
49
50static char *product_file(const char *extra)
51{
52 int n;
53 char *x;
54
55 if (gProductOutPath == NULL) {
56 fprintf(stderr, "adb: Product directory not specified; "
57 "use -p or define ANDROID_PRODUCT_OUT\n");
58 exit(1);
59 }
60
61 n = strlen(gProductOutPath) + strlen(extra) + 2;
62 x = malloc(n);
63 if (x == 0) {
64 fprintf(stderr, "adb: Out of memory (product_file())\n");
65 exit(1);
66 }
67
68 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
69 return x;
70}
71
72void version(FILE * out) {
73 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
74 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
75}
76
77void help()
78{
79 version(stderr);
80
81 fprintf(stderr,
82 "\n"
83 " -d - directs command to the only connected USB device\n"
84 " returns an error if more than one USB device is present.\n"
85 " -e - directs command to the only running emulator.\n"
86 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070087 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070088 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080090 " -p <product name or path> - simple product name like 'sooner', or\n"
91 " a relative/absolute path to a product\n"
92 " out directory like 'out/target/product/sooner'.\n"
93 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94 " environment variable is used, which must\n"
95 " be an absolute path.\n"
Scott Andersone109d262012-04-20 11:21:14 -070096 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070097 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040098 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
99 " Port 5555 is used by default if no port number is specified.\n"
100 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
101 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200102 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400103 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800104 "\n"
105 "device commands:\n"
106 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato00c0eea2010-01-05 13:42:25 -0800107 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800108 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600109 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800110 " (see 'adb help all')\n"
111 " adb shell - run remote shell interactively\n"
112 " adb shell <command> - run remote shell command\n"
113 " adb emu <command> - run emulator console command\n"
114 " adb logcat [ <filter-spec> ] - View device log\n"
115 " adb forward <local> <remote> - forward socket connections\n"
116 " forward specs are one of: \n"
117 " tcp:<port>\n"
118 " localabstract:<unix domain socket name>\n"
119 " localreserved:<unix domain socket name>\n"
120 " localfilesystem:<unix domain socket name>\n"
121 " dev:<character device name>\n"
122 " jdwp:<process pid> (remote only)\n"
123 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700124 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
125 " - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 " ('-l' means forward-lock the app)\n"
127 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500128 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700129 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800130 " adb uninstall [-k] <package> - remove this app package from the device\n"
131 " ('-k' means keep the data and cache directories)\n"
132 " adb bugreport - return all information from the device\n"
133 " that should be included in a bug report.\n"
134 "\n"
Christopher Tate56885092011-10-03 18:27:01 -0700135 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
136 " - write an archive of the device's data to <file>.\n"
137 " If no -f option is supplied then the data is written\n"
138 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700139 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700140 " in the archive; the default is noapk.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700141 " (-shared|-noshared enable/disable backup of the device's\n"
142 " shared storage / SD card contents; the default is noshared.)\n"
143 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700144 " (-system|-nosystem toggles whether -all automatically includes\n"
145 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700146 " (<packages...> is the list of applications to be backed up. If\n"
147 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700148 " list is optional. Applications explicitly given on the\n"
149 " command line will be included even if -nosystem would\n"
150 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700151 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700152 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700153 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800154 " adb help - show this help message\n"
155 " adb version - show version num\n"
156 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157 "scripting:\n"
158 " adb wait-for-device - block until device is online\n"
159 " adb start-server - ensure that there is a server running\n"
160 " adb kill-server - kill the server if it is running\n"
161 " adb get-state - prints: offline | bootloader | device\n"
162 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700163 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800164 " adb status-window - continuously print device status for a specified device\n"
165 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400166 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800167 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700168 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800169 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700170 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800171 "\n"
172 "networking:\n"
173 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500174 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800175 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
176 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
177 "\n"
178 "adb sync notes: adb sync [ <directory> ]\n"
179 " <localdir> can be interpreted in several ways:\n"
180 "\n"
181 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
182 "\n"
183 " - If it is \"system\" or \"data\", only the corresponding partition\n"
184 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000185 "\n"
186 "environmental variables:\n"
187 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
188 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
189 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
190 " 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 -0800191 );
192}
193
194int usage()
195{
196 help();
197 return 1;
198}
199
200#ifdef HAVE_TERMIO_H
201static struct termios tio_save;
202
203static void stdin_raw_init(int fd)
204{
205 struct termios tio;
206
207 if(tcgetattr(fd, &tio)) return;
208 if(tcgetattr(fd, &tio_save)) return;
209
210 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
211
212 /* no timeout but request at least one character per read */
213 tio.c_cc[VTIME] = 0;
214 tio.c_cc[VMIN] = 1;
215
216 tcsetattr(fd, TCSANOW, &tio);
217 tcflush(fd, TCIFLUSH);
218}
219
220static void stdin_raw_restore(int fd)
221{
222 tcsetattr(fd, TCSANOW, &tio_save);
223 tcflush(fd, TCIFLUSH);
224}
225#endif
226
227static void read_and_dump(int fd)
228{
229 char buf[4096];
230 int len;
231
232 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700233 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700235 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800236 if(len == 0) {
237 break;
238 }
239
240 if(len < 0) {
241 if(errno == EINTR) continue;
242 break;
243 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400244 fwrite(buf, 1, len, stdout);
245 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800246 }
247}
248
Christopher Tated2f54152011-04-21 12:53:28 -0700249static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700250 const size_t BUFSIZE = 32 * 1024;
251 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700252 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700253 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700254
255 D("copy_to_file(%d -> %d)\n", inFd, outFd);
256 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700257 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700258 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700259 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700260 break;
261 }
262 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700263 if (errno == EINTR) {
264 D("copy_to_file() : EINTR, retrying\n");
265 continue;
266 }
Christopher Tated2f54152011-04-21 12:53:28 -0700267 D("copy_to_file() : error %d\n", errno);
268 break;
269 }
270 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700271 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700272 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700273 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700274 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700275}
276
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277static void *stdin_read_thread(void *x)
278{
279 int fd, fdi;
280 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 int r, n;
282 int state = 0;
283
284 int *fds = (int*) x;
285 fd = fds[0];
286 fdi = fds[1];
287 free(fds);
288
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800289 for(;;) {
290 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700291 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700293 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800294 if(r == 0) break;
295 if(r < 0) {
296 if(errno == EINTR) continue;
297 break;
298 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400299 for(n = 0; n < r; n++){
300 switch(buf[n]) {
301 case '\n':
302 state = 1;
303 break;
304 case '\r':
305 state = 1;
306 break;
307 case '~':
308 if(state == 1) state++;
309 break;
310 case '.':
311 if(state == 2) {
312 fprintf(stderr,"\n* disconnect *\n");
313#ifdef HAVE_TERMIO_H
314 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400316 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800317 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400318 default:
319 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800320 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800321 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800322 r = adb_write(fd, buf, r);
323 if(r <= 0) {
324 break;
325 }
326 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800327 return 0;
328}
329
330int interactive_shell(void)
331{
332 adb_thread_t thr;
333 int fdi, fd;
334 int *fds;
335
336 fd = adb_connect("shell:");
337 if(fd < 0) {
338 fprintf(stderr,"error: %s\n", adb_error());
339 return 1;
340 }
341 fdi = 0; //dup(0);
342
343 fds = malloc(sizeof(int) * 2);
344 fds[0] = fd;
345 fds[1] = fdi;
346
347#ifdef HAVE_TERMIO_H
348 stdin_raw_init(fdi);
349#endif
350 adb_thread_create(&thr, stdin_read_thread, fds);
351 read_and_dump(fd);
352#ifdef HAVE_TERMIO_H
353 stdin_raw_restore(fdi);
354#endif
355 return 0;
356}
357
358
359static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
360{
361 if (serial) {
362 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
363 } else {
364 const char* prefix = "host";
365 if (ttype == kTransportUsb)
366 prefix = "host-usb";
367 else if (ttype == kTransportLocal)
368 prefix = "host-local";
369
370 snprintf(buffer, buflen, "%s:%s", prefix, command);
371 }
372}
373
Doug Zongker447f0612012-01-09 14:54:53 -0800374int adb_download_buffer(const char *service, const void* data, int sz,
375 unsigned progress)
376{
377 char buf[4096];
378 unsigned total;
379 int fd;
380 const unsigned char *ptr;
381
382 sprintf(buf,"%s:%d", service, sz);
383 fd = adb_connect(buf);
384 if(fd < 0) {
385 fprintf(stderr,"error: %s\n", adb_error());
386 return -1;
387 }
388
389 int opt = CHUNK_SIZE;
390 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
391
392 total = sz;
393 ptr = data;
394
395 if(progress) {
396 char *x = strrchr(service, ':');
397 if(x) service = x + 1;
398 }
399
400 while(sz > 0) {
401 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
402 if(writex(fd, ptr, xfer)) {
403 adb_status(fd);
404 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
405 return -1;
406 }
407 sz -= xfer;
408 ptr += xfer;
409 if(progress) {
410 printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total))));
411 fflush(stdout);
412 }
413 }
414 if(progress) {
415 printf("\n");
416 }
417
418 if(readx(fd, buf, 4)){
419 fprintf(stderr,"* error reading response *\n");
420 adb_close(fd);
421 return -1;
422 }
423 if(memcmp(buf, "OKAY", 4)) {
424 buf[4] = 0;
425 fprintf(stderr,"* error response '%s' *\n", buf);
426 adb_close(fd);
427 return -1;
428 }
429
430 adb_close(fd);
431 return 0;
432}
433
434
435int adb_download(const char *service, const char *fn, unsigned progress)
436{
437 void *data;
438 unsigned sz;
439
440 data = load_file(fn, &sz);
441 if(data == 0) {
442 fprintf(stderr,"* cannot read '%s' *\n", service);
443 return -1;
444 }
445
446 int status = adb_download_buffer(service, data, sz, progress);
447 free(data);
448 return status;
449}
450
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800451static void status_window(transport_type ttype, const char* serial)
452{
453 char command[4096];
454 char *state = 0;
455 char *laststate = 0;
456
457 /* silence stderr */
458#ifdef _WIN32
459 /* XXX: TODO */
460#else
461 int fd;
462 fd = unix_open("/dev/null", O_WRONLY);
463 dup2(fd, 2);
464 adb_close(fd);
465#endif
466
467 format_host_command(command, sizeof command, "get-state", ttype, serial);
468
469 for(;;) {
470 adb_sleep_ms(250);
471
472 if(state) {
473 free(state);
474 state = 0;
475 }
476
477 state = adb_query(command);
478
479 if(state) {
480 if(laststate && !strcmp(state,laststate)){
481 continue;
482 } else {
483 if(laststate) free(laststate);
484 laststate = strdup(state);
485 }
486 }
487
488 printf("%c[2J%c[2H", 27, 27);
489 printf("Android Debug Bridge\n");
490 printf("State: %s\n", state ? state : "offline");
491 fflush(stdout);
492 }
493}
494
495/** duplicate string and quote all \ " ( ) chars + space character. */
496static char *
497dupAndQuote(const char *s)
498{
499 const char *ts;
500 size_t alloc_len;
501 char *ret;
502 char *dest;
503
504 ts = s;
505
506 alloc_len = 0;
507
508 for( ;*ts != '\0'; ts++) {
509 alloc_len++;
510 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
511 alloc_len++;
512 }
513 }
514
515 ret = (char *)malloc(alloc_len + 1);
516
517 ts = s;
518 dest = ret;
519
520 for ( ;*ts != '\0'; ts++) {
521 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
522 *dest++ = '\\';
523 }
524
525 *dest++ = *ts;
526 }
527
528 *dest++ = '\0';
529
530 return ret;
531}
532
533/**
534 * Run ppp in "notty" mode against a resource listed as the first parameter
535 * eg:
536 *
537 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
538 *
539 */
540int ppp(int argc, char **argv)
541{
542#ifdef HAVE_WIN32_PROC
543 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
544 return -1;
545#else
546 char *adb_service_name;
547 pid_t pid;
548 int fd;
549
550 if (argc < 2) {
551 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
552 argv[0]);
553
554 return 1;
555 }
556
557 adb_service_name = argv[1];
558
559 fd = adb_connect(adb_service_name);
560
561 if(fd < 0) {
562 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
563 adb_service_name, adb_error());
564 return 1;
565 }
566
567 pid = fork();
568
569 if (pid < 0) {
570 perror("from fork()");
571 return 1;
572 } else if (pid == 0) {
573 int err;
574 int i;
575 const char **ppp_args;
576
577 // copy args
578 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
579 ppp_args[0] = "pppd";
580 for (i = 2 ; i < argc ; i++) {
581 //argv[2] and beyond become ppp_args[1] and beyond
582 ppp_args[i - 1] = argv[i];
583 }
584 ppp_args[i-1] = NULL;
585
586 // child side
587
588 dup2(fd, STDIN_FILENO);
589 dup2(fd, STDOUT_FILENO);
590 adb_close(STDERR_FILENO);
591 adb_close(fd);
592
593 err = execvp("pppd", (char * const *)ppp_args);
594
595 if (err < 0) {
596 perror("execing pppd");
597 }
598 exit(-1);
599 } else {
600 // parent side
601
602 adb_close(fd);
603 return 0;
604 }
605#endif /* !HAVE_WIN32_PROC */
606}
607
608static int send_shellcommand(transport_type transport, char* serial, char* buf)
609{
610 int fd, ret;
611
612 for(;;) {
613 fd = adb_connect(buf);
614 if(fd >= 0)
615 break;
616 fprintf(stderr,"- waiting for device -\n");
617 adb_sleep_ms(1000);
618 do_cmd(transport, serial, "wait-for-device", 0);
619 }
620
621 read_and_dump(fd);
622 ret = adb_close(fd);
623 if (ret)
624 perror("close");
625
626 return ret;
627}
628
629static int logcat(transport_type transport, char* serial, int argc, char **argv)
630{
631 char buf[4096];
632
633 char *log_tags;
634 char *quoted_log_tags;
635
636 log_tags = getenv("ANDROID_LOG_TAGS");
637 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
638
639 snprintf(buf, sizeof(buf),
640 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
641 quoted_log_tags);
642
643 free(quoted_log_tags);
644
Christopher Tatedb0a8802011-11-30 13:00:33 -0800645 if (!strcmp(argv[0],"longcat")) {
646 strncat(buf, " -v long", sizeof(buf)-1);
647 }
648
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800649 argc -= 1;
650 argv += 1;
651 while(argc-- > 0) {
652 char *quoted;
653
654 quoted = dupAndQuote (*argv++);
655
656 strncat(buf, " ", sizeof(buf)-1);
657 strncat(buf, quoted, sizeof(buf)-1);
658 free(quoted);
659 }
660
661 send_shellcommand(transport, serial, buf);
662 return 0;
663}
664
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800665static int mkdirs(char *path)
666{
667 int ret;
668 char *x = path + 1;
669
670 for(;;) {
671 x = adb_dirstart(x);
672 if(x == 0) return 0;
673 *x = 0;
674 ret = adb_mkdir(path, 0775);
675 *x = OS_PATH_SEPARATOR;
676 if((ret < 0) && (errno != EEXIST)) {
677 return ret;
678 }
679 x++;
680 }
681 return 0;
682}
683
Christopher Tated2f54152011-04-21 12:53:28 -0700684static int backup(int argc, char** argv) {
685 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800686 char default_name[32];
687 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700688 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700689 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700690
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700691 /* find, extract, and use any -f argument */
692 for (i = 1; i < argc; i++) {
693 if (!strcmp("-f", argv[i])) {
694 if (i == argc-1) {
695 fprintf(stderr, "adb: -f passed with no filename\n");
696 return usage();
697 }
698 filename = argv[i+1];
699 for (j = i+2; j <= argc; ) {
700 argv[i++] = argv[j++];
701 }
702 argc -= 2;
703 argv[argc] = NULL;
704 }
Christopher Tated2f54152011-04-21 12:53:28 -0700705 }
706
Christopher Tatebb86bc52011-08-22 17:12:08 -0700707 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
708 if (argc < 2) return usage();
709
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800710 adb_unlink(filename);
711 mkdirs((char *)filename);
712 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700713 if (outFd < 0) {
714 fprintf(stderr, "adb: unable to open file %s\n", filename);
715 return -1;
716 }
717
718 snprintf(buf, sizeof(buf), "backup");
719 for (argc--, argv++; argc; argc--, argv++) {
720 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
721 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
722 }
723
724 D("backup. filename=%s buf=%s\n", filename, buf);
725 fd = adb_connect(buf);
726 if (fd < 0) {
727 fprintf(stderr, "adb: unable to connect for backup\n");
728 adb_close(outFd);
729 return -1;
730 }
731
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800732 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700733 copy_to_file(fd, outFd);
734
735 adb_close(fd);
736 adb_close(outFd);
737 return 0;
738}
739
Christopher Tate702967a2011-05-17 15:52:54 -0700740static int restore(int argc, char** argv) {
741 const char* filename;
742 int fd, tarFd;
743
744 if (argc != 2) return usage();
745
746 filename = argv[1];
747 tarFd = adb_open(filename, O_RDONLY);
748 if (tarFd < 0) {
749 fprintf(stderr, "adb: unable to open file %s\n", filename);
750 return -1;
751 }
752
753 fd = adb_connect("restore:");
754 if (fd < 0) {
755 fprintf(stderr, "adb: unable to connect for backup\n");
756 adb_close(tarFd);
757 return -1;
758 }
759
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800760 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700761 copy_to_file(tarFd, fd);
762
763 adb_close(fd);
764 adb_close(tarFd);
765 return 0;
766}
767
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800768#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
769static int top_works(const char *top)
770{
771 if (top != NULL && adb_is_absolute_host_path(top)) {
772 char path_buf[PATH_MAX];
773 snprintf(path_buf, sizeof(path_buf),
774 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
775 return access(path_buf, F_OK) == 0;
776 }
777 return 0;
778}
779
780static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
781{
782 strcpy(path_buf, indir);
783 while (1) {
784 if (top_works(path_buf)) {
785 return path_buf;
786 }
787 char *s = adb_dirstop(path_buf);
788 if (s != NULL) {
789 *s = '\0';
790 } else {
791 path_buf[0] = '\0';
792 return NULL;
793 }
794 }
795}
796
797static char *find_top(char path_buf[PATH_MAX])
798{
799 char *top = getenv("ANDROID_BUILD_TOP");
800 if (top != NULL && top[0] != '\0') {
801 if (!top_works(top)) {
802 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
803 return NULL;
804 }
805 } else {
806 top = getenv("TOP");
807 if (top != NULL && top[0] != '\0') {
808 if (!top_works(top)) {
809 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
810 return NULL;
811 }
812 } else {
813 top = NULL;
814 }
815 }
816
817 if (top != NULL) {
818 /* The environment pointed to a top directory that works.
819 */
820 strcpy(path_buf, top);
821 return path_buf;
822 }
823
824 /* The environment didn't help. Walk up the tree from the CWD
825 * to see if we can find the top.
826 */
827 char dir[PATH_MAX];
828 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
829 if (top == NULL) {
830 /* If the CWD isn't under a good-looking top, see if the
831 * executable is.
832 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100833 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800834 top = find_top_from(dir, path_buf);
835 }
836 return top;
837}
838
839/* <hint> may be:
840 * - A simple product name
841 * e.g., "sooner"
842TODO: debug? sooner-debug, sooner:debug?
843 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
844 * e.g., "out/target/product/sooner"
845 * - An absolute path to the PRODUCT_OUT dir
846 * e.g., "/src/device/out/target/product/sooner"
847 *
848 * Given <hint>, try to construct an absolute path to the
849 * ANDROID_PRODUCT_OUT dir.
850 */
851static const char *find_product_out_path(const char *hint)
852{
853 static char path_buf[PATH_MAX];
854
855 if (hint == NULL || hint[0] == '\0') {
856 return NULL;
857 }
858
859 /* If it's already absolute, don't bother doing any work.
860 */
861 if (adb_is_absolute_host_path(hint)) {
862 strcpy(path_buf, hint);
863 return path_buf;
864 }
865
866 /* If there are any slashes in it, assume it's a relative path;
867 * make it absolute.
868 */
869 if (adb_dirstart(hint) != NULL) {
870 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
871 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
872 return NULL;
873 }
874 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
875 fprintf(stderr, "adb: Couldn't assemble path\n");
876 return NULL;
877 }
878 strcat(path_buf, OS_PATH_SEPARATOR_STR);
879 strcat(path_buf, hint);
880 return path_buf;
881 }
882
883 /* It's a string without any slashes. Try to do something with it.
884 *
885 * Try to find the root of the build tree, and build a PRODUCT_OUT
886 * path from there.
887 */
888 char top_buf[PATH_MAX];
889 const char *top = find_top(top_buf);
890 if (top == NULL) {
891 fprintf(stderr, "adb: Couldn't find top of build tree\n");
892 return NULL;
893 }
894//TODO: if we have a way to indicate debug, look in out/debug/target/...
895 snprintf(path_buf, sizeof(path_buf),
896 "%s" OS_PATH_SEPARATOR_STR
897 "out" OS_PATH_SEPARATOR_STR
898 "target" OS_PATH_SEPARATOR_STR
899 "product" OS_PATH_SEPARATOR_STR
900 "%s", top_buf, hint);
901 if (access(path_buf, F_OK) < 0) {
902 fprintf(stderr, "adb: Couldn't find a product dir "
903 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
904 return NULL;
905 }
906 return path_buf;
907}
908
909int adb_commandline(int argc, char **argv)
910{
911 char buf[4096];
912 int no_daemon = 0;
913 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100914 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800915 int persist = 0;
916 int r;
917 int quote;
918 transport_type ttype = kTransportAny;
919 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100920 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800921
922 /* If defined, this should be an absolute path to
923 * the directory containing all of the various system images
924 * for a particular product. If not defined, and the adb
925 * command requires this information, then the user must
926 * specify the path using "-p".
927 */
928 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
929 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
930 gProductOutPath = NULL;
931 }
932 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
933
Nick Pellydb449262009-05-07 12:48:03 -0700934 serial = getenv("ANDROID_SERIAL");
935
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100936 /* Validate and assign the server port */
937 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
938 int server_port = DEFAULT_ADB_PORT;
939 if (server_port_str && strlen(server_port_str) > 0) {
940 server_port = (int) strtol(server_port_str, NULL, 0);
941 if (server_port <= 0) {
942 fprintf(stderr,
943 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
944 server_port_str);
945 return usage();
946 }
947 }
948
949 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800950 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100951 if(!strcmp(argv[0],"server")) {
952 is_server = 1;
953 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800954 no_daemon = 1;
955 } else if (!strcmp(argv[0], "fork-server")) {
956 /* this is a special flag used only when the ADB client launches the ADB Server */
957 is_daemon = 1;
958 } else if(!strcmp(argv[0],"persist")) {
959 persist = 1;
960 } else if(!strncmp(argv[0], "-p", 2)) {
961 const char *product = NULL;
962 if (argv[0][2] == '\0') {
963 if (argc < 2) return usage();
964 product = argv[1];
965 argc--;
966 argv++;
967 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -0700968 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800969 }
970 gProductOutPath = find_product_out_path(product);
971 if (gProductOutPath == NULL) {
972 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
973 product);
974 return usage();
975 }
976 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
977 if (isdigit(argv[0][2])) {
978 serial = argv[0] + 2;
979 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100980 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800981 serial = argv[1];
982 argc--;
983 argv++;
984 }
985 } else if (!strcmp(argv[0],"-d")) {
986 ttype = kTransportUsb;
987 } else if (!strcmp(argv[0],"-e")) {
988 ttype = kTransportLocal;
989 } else {
990 /* out of recognized modifiers and flags */
991 break;
992 }
993 argc--;
994 argv++;
995 }
996
997 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100998 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800999
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001000 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001001 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001002 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001003 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001004 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001005 }
1006 if(r) {
1007 fprintf(stderr,"* could not start server *\n");
1008 }
1009 return r;
1010 }
1011
1012top:
1013 if(argc == 0) {
1014 return usage();
1015 }
1016
1017 /* adb_connect() commands */
1018
1019 if(!strcmp(argv[0], "devices")) {
1020 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001021 char *listopt;
1022 if (argc < 2)
1023 listopt = "";
1024 else if (argc == 2 && !strcmp(argv[1], "-l"))
1025 listopt = argv[1];
1026 else {
1027 fprintf(stderr, "Usage: adb devices [-l]\n");
1028 return 1;
1029 }
1030 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001031 tmp = adb_query(buf);
1032 if(tmp) {
1033 printf("List of devices attached \n");
1034 printf("%s\n", tmp);
1035 return 0;
1036 } else {
1037 return 1;
1038 }
1039 }
1040
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001041 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001042 char *tmp;
1043 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001044 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001045 return 1;
1046 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001047 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1048 tmp = adb_query(buf);
1049 if(tmp) {
1050 printf("%s\n", tmp);
1051 return 0;
1052 } else {
1053 return 1;
1054 }
1055 }
1056
1057 if(!strcmp(argv[0], "disconnect")) {
1058 char *tmp;
1059 if (argc > 2) {
1060 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1061 return 1;
1062 }
1063 if (argc == 2) {
1064 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1065 } else {
1066 snprintf(buf, sizeof buf, "host:disconnect:");
1067 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001068 tmp = adb_query(buf);
1069 if(tmp) {
1070 printf("%s\n", tmp);
1071 return 0;
1072 } else {
1073 return 1;
1074 }
1075 }
1076
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001077 if (!strcmp(argv[0], "emu")) {
1078 return adb_send_emulator_command(argc, argv);
1079 }
1080
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001081 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001082 int r;
1083 int fd;
1084
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001085 char h = (argv[0][0] == 'h');
1086
1087 if (h) {
1088 printf("\x1b[41;33m");
1089 fflush(stdout);
1090 }
1091
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001092 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001093 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001094 r = interactive_shell();
1095 if (h) {
1096 printf("\x1b[0m");
1097 fflush(stdout);
1098 }
1099 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001100 }
1101
1102 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1103 argc -= 2;
1104 argv += 2;
1105 while(argc-- > 0) {
1106 strcat(buf, " ");
1107
1108 /* quote empty strings and strings with spaces */
1109 quote = (**argv == 0 || strchr(*argv, ' '));
1110 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001111 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001112 strcat(buf, *argv++);
1113 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001114 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001115 }
1116
1117 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001118 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001119 fd = adb_connect(buf);
1120 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001121 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001122 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001123 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001124 adb_close(fd);
1125 r = 0;
1126 } else {
1127 fprintf(stderr,"error: %s\n", adb_error());
1128 r = -1;
1129 }
1130
1131 if(persist) {
1132 fprintf(stderr,"\n- waiting for device -\n");
1133 adb_sleep_ms(1000);
1134 do_cmd(ttype, serial, "wait-for-device", 0);
1135 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001136 if (h) {
1137 printf("\x1b[0m");
1138 fflush(stdout);
1139 }
JP Abgrall408fa572011-03-16 15:57:42 -07001140 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141 return r;
1142 }
1143 }
1144 }
1145
1146 if(!strcmp(argv[0], "kill-server")) {
1147 int fd;
1148 fd = _adb_connect("host:kill");
1149 if(fd == -1) {
1150 fprintf(stderr,"* server not running *\n");
1151 return 1;
1152 }
1153 return 0;
1154 }
1155
Doug Zongker447f0612012-01-09 14:54:53 -08001156 if(!strcmp(argv[0], "sideload")) {
1157 if(argc != 2) return usage();
1158 if(adb_download("sideload", argv[1], 1)) {
1159 return 1;
1160 } else {
1161 return 0;
1162 }
1163 }
1164
Mike Lockwoodff196702009-08-24 15:58:40 -07001165 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001166 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001167 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001168 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001169 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001170 if (!strcmp(argv[0], "reboot-bootloader"))
1171 snprintf(command, sizeof(command), "reboot:bootloader");
1172 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001173 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001174 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001175 snprintf(command, sizeof(command), "%s:", argv[0]);
1176 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001177 if(fd >= 0) {
1178 read_and_dump(fd);
1179 adb_close(fd);
1180 return 0;
1181 }
1182 fprintf(stderr,"error: %s\n", adb_error());
1183 return 1;
1184 }
1185
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001186 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001187 if (argc != 1) return usage();
1188 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001189 return 0;
1190 }
1191
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 /* adb_command() wrapper commands */
1193
1194 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1195 char* service = argv[0];
1196 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1197 if (ttype == kTransportUsb) {
1198 service = "wait-for-usb";
1199 } else if (ttype == kTransportLocal) {
1200 service = "wait-for-local";
1201 } else {
1202 service = "wait-for-any";
1203 }
1204 }
1205
1206 format_host_command(buf, sizeof buf, service, ttype, serial);
1207
1208 if (adb_command(buf)) {
1209 D("failure: %s *\n",adb_error());
1210 fprintf(stderr,"error: %s\n", adb_error());
1211 return 1;
1212 }
1213
1214 /* Allow a command to be run after wait-for-device,
1215 * e.g. 'adb wait-for-device shell'.
1216 */
1217 if(argc > 1) {
1218 argc--;
1219 argv++;
1220 goto top;
1221 }
1222 return 0;
1223 }
1224
1225 if(!strcmp(argv[0], "forward")) {
1226 if(argc != 3) return usage();
1227 if (serial) {
Mike Lockwood64e99542009-11-28 12:46:13 -05001228 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1229 } else if (ttype == kTransportUsb) {
1230 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1231 } else if (ttype == kTransportLocal) {
1232 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001233 } else {
Mike Lockwood64e99542009-11-28 12:46:13 -05001234 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001235 }
1236 if(adb_command(buf)) {
1237 fprintf(stderr,"error: %s\n", adb_error());
1238 return 1;
1239 }
1240 return 0;
1241 }
1242
1243 /* do_sync_*() commands */
1244
1245 if(!strcmp(argv[0], "ls")) {
1246 if(argc != 2) return usage();
1247 return do_sync_ls(argv[1]);
1248 }
1249
1250 if(!strcmp(argv[0], "push")) {
1251 if(argc != 3) return usage();
1252 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1253 }
1254
1255 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001256 if (argc == 2) {
1257 return do_sync_pull(argv[1], ".");
1258 } else if (argc == 3) {
1259 return do_sync_pull(argv[1], argv[2]);
1260 } else {
1261 return usage();
1262 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263 }
1264
1265 if(!strcmp(argv[0], "install")) {
1266 if (argc < 2) return usage();
1267 return install_app(ttype, serial, argc, argv);
1268 }
1269
1270 if(!strcmp(argv[0], "uninstall")) {
1271 if (argc < 2) return usage();
1272 return uninstall_app(ttype, serial, argc, argv);
1273 }
1274
1275 if(!strcmp(argv[0], "sync")) {
1276 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001277 int listonly = 0;
1278
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001279 int ret;
1280 if(argc < 2) {
1281 /* No local path was specified. */
1282 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001283 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1284 listonly = 1;
1285 if (argc == 3) {
1286 srcarg = argv[2];
1287 } else {
1288 srcarg = NULL;
1289 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001290 } else if(argc == 2) {
1291 /* A local path or "android"/"data" arg was specified. */
1292 srcarg = argv[1];
1293 } else {
1294 return usage();
1295 }
1296 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1297 if(ret != 0) return usage();
1298
1299 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001300 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001301 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001302 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001303
1304 free(android_srcpath);
1305 free(data_srcpath);
1306 return ret;
1307 }
1308
1309 /* passthrough commands */
1310
1311 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001312 !strcmp(argv[0],"get-serialno") ||
1313 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001314 {
1315 char *tmp;
1316
1317 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1318 tmp = adb_query(buf);
1319 if(tmp) {
1320 printf("%s\n", tmp);
1321 return 0;
1322 } else {
1323 return 1;
1324 }
1325 }
1326
1327 /* other commands */
1328
1329 if(!strcmp(argv[0],"status-window")) {
1330 status_window(ttype, serial);
1331 return 0;
1332 }
1333
Christopher Tatedb0a8802011-11-30 13:00:33 -08001334 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001335 return logcat(ttype, serial, argc, argv);
1336 }
1337
1338 if(!strcmp(argv[0],"ppp")) {
1339 return ppp(argc, argv);
1340 }
1341
1342 if (!strcmp(argv[0], "start-server")) {
1343 return adb_connect("host:start-server");
1344 }
1345
Christopher Tated2f54152011-04-21 12:53:28 -07001346 if (!strcmp(argv[0], "backup")) {
1347 return backup(argc, argv);
1348 }
1349
Christopher Tate702967a2011-05-17 15:52:54 -07001350 if (!strcmp(argv[0], "restore")) {
1351 return restore(argc, argv);
1352 }
1353
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001354 if (!strcmp(argv[0], "jdwp")) {
1355 int fd = adb_connect("jdwp");
1356 if (fd >= 0) {
1357 read_and_dump(fd);
1358 adb_close(fd);
1359 return 0;
1360 } else {
1361 fprintf(stderr, "error: %s\n", adb_error());
1362 return -1;
1363 }
1364 }
1365
1366 /* "adb /?" is a common idiom under Windows */
1367 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1368 help();
1369 return 0;
1370 }
1371
1372 if(!strcmp(argv[0], "version")) {
1373 version(stdout);
1374 return 0;
1375 }
1376
1377 usage();
1378 return 1;
1379}
1380
1381static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1382{
1383 char *argv[16];
1384 int argc;
1385 va_list ap;
1386
1387 va_start(ap, cmd);
1388 argc = 0;
1389
1390 if (serial) {
1391 argv[argc++] = "-s";
1392 argv[argc++] = serial;
1393 } else if (ttype == kTransportUsb) {
1394 argv[argc++] = "-d";
1395 } else if (ttype == kTransportLocal) {
1396 argv[argc++] = "-e";
1397 }
1398
1399 argv[argc++] = cmd;
1400 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1401 va_end(ap);
1402
1403#if 0
1404 int n;
1405 fprintf(stderr,"argc = %d\n",argc);
1406 for(n = 0; n < argc; n++) {
1407 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1408 }
1409#endif
1410
1411 return adb_commandline(argc, argv);
1412}
1413
1414int find_sync_dirs(const char *srcarg,
1415 char **android_srcdir_out, char **data_srcdir_out)
1416{
1417 char *android_srcdir, *data_srcdir;
1418
1419 if(srcarg == NULL) {
1420 android_srcdir = product_file("system");
1421 data_srcdir = product_file("data");
1422 } else {
1423 /* srcarg may be "data", "system" or NULL.
1424 * if srcarg is NULL, then both data and system are synced
1425 */
1426 if(strcmp(srcarg, "system") == 0) {
1427 android_srcdir = product_file("system");
1428 data_srcdir = NULL;
1429 } else if(strcmp(srcarg, "data") == 0) {
1430 android_srcdir = NULL;
1431 data_srcdir = product_file("data");
1432 } else {
1433 /* It's not "system" or "data".
1434 */
1435 return 1;
1436 }
1437 }
1438
1439 if(android_srcdir_out != NULL)
1440 *android_srcdir_out = android_srcdir;
1441 else
1442 free(android_srcdir);
1443
1444 if(data_srcdir_out != NULL)
1445 *data_srcdir_out = data_srcdir;
1446 else
1447 free(data_srcdir);
1448
1449 return 0;
1450}
1451
1452static int pm_command(transport_type transport, char* serial,
1453 int argc, char** argv)
1454{
1455 char buf[4096];
1456
1457 snprintf(buf, sizeof(buf), "shell:pm");
1458
1459 while(argc-- > 0) {
1460 char *quoted;
1461
1462 quoted = dupAndQuote(*argv++);
1463
1464 strncat(buf, " ", sizeof(buf)-1);
1465 strncat(buf, quoted, sizeof(buf)-1);
1466 free(quoted);
1467 }
1468
1469 send_shellcommand(transport, serial, buf);
1470 return 0;
1471}
1472
1473int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1474{
1475 /* if the user choose the -k option, we refuse to do it until devices are
1476 out with the option to uninstall the remaining data somehow (adb/ui) */
1477 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1478 {
1479 printf(
1480 "The -k option uninstalls the application while retaining the data/cache.\n"
1481 "At the moment, there is no way to remove the remaining data.\n"
1482 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1483 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1484 return -1;
1485 }
1486
1487 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1488 return pm_command(transport, serial, argc, argv);
1489}
1490
1491static int delete_file(transport_type transport, char* serial, char* filename)
1492{
1493 char buf[4096];
1494 char* quoted;
1495
1496 snprintf(buf, sizeof(buf), "shell:rm ");
1497 quoted = dupAndQuote(filename);
1498 strncat(buf, quoted, sizeof(buf)-1);
1499 free(quoted);
1500
1501 send_shellcommand(transport, serial, buf);
1502 return 0;
1503}
1504
Kenny Root597ea5b2011-08-05 11:19:45 -07001505static const char* get_basename(const char* filename)
1506{
1507 const char* basename = adb_dirstop(filename);
1508 if (basename) {
1509 basename++;
1510 return basename;
1511 } else {
1512 return filename;
1513 }
1514}
1515
1516static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001517{
1518 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001519
Kenny Root597ea5b2011-08-05 11:19:45 -07001520 if (filename == NULL) {
1521 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001522 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001523
Kenny Root597ea5b2011-08-05 11:19:45 -07001524 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 fprintf(stderr, "can't find '%s' to install\n", filename);
1526 return 1;
1527 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001528
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001529 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001530 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 return 1;
1532 }
1533
Kenny Root597ea5b2011-08-05 11:19:45 -07001534 return 0;
1535}
1536
1537int install_app(transport_type transport, char* serial, int argc, char** argv)
1538{
1539 static const char *const DATA_DEST = "/data/local/tmp/%s";
1540 static const char *const SD_DEST = "/sdcard/tmp/%s";
1541 const char* where = DATA_DEST;
1542 char apk_dest[PATH_MAX];
1543 char verification_dest[PATH_MAX];
1544 char* apk_file;
1545 char* verification_file = NULL;
1546 int file_arg = -1;
1547 int err;
1548 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001549 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001550
1551 for (i = 1; i < argc; i++) {
1552 if (*argv[i] != '-') {
1553 file_arg = i;
1554 break;
Kenny Roota031a912011-09-23 12:46:39 -07001555 } else if (!strcmp(argv[i], "-i")) {
1556 // Skip the installer package name.
1557 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001558 } else if (!strcmp(argv[i], "-s")) {
1559 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001560 } else if (!strcmp(argv[i], "--algo")) {
1561 verify_apk = 0;
1562 i++;
1563 } else if (!strcmp(argv[i], "--iv")) {
1564 verify_apk = 0;
1565 i++;
1566 } else if (!strcmp(argv[i], "--key")) {
1567 verify_apk = 0;
1568 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001569 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001570 }
1571
Kenny Root597ea5b2011-08-05 11:19:45 -07001572 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001573 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001574 return 1;
1575 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001576 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001577 return 1;
1578 }
1579
1580 apk_file = argv[file_arg];
1581
1582 if (file_arg != argc - 1) {
1583 verification_file = argv[file_arg + 1];
1584 }
1585
1586 if (check_file(apk_file) || check_file(verification_file)) {
1587 return 1;
1588 }
1589
1590 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1591 if (verification_file != NULL) {
1592 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1593
1594 if (!strcmp(apk_dest, verification_dest)) {
1595 fprintf(stderr, "APK and verification file can't have the same name\n");
1596 return 1;
1597 }
1598 }
1599
Anonymous Coward4474ac42012-04-24 10:43:41 -07001600 err = do_sync_push(apk_file, apk_dest, verify_apk);
Kenny Root597ea5b2011-08-05 11:19:45 -07001601 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001602 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001603 } else {
1604 argv[file_arg] = apk_dest; /* destination name, not source location */
1605 }
1606
1607 if (verification_file != NULL) {
1608 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1609 if (err) {
1610 goto cleanup_apk;
1611 } else {
1612 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1613 }
1614 }
1615
1616 pm_command(transport, serial, argc, argv);
1617
Kenny Root60733e92012-03-26 16:14:02 -07001618cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001619 if (verification_file != NULL) {
1620 delete_file(transport, serial, verification_dest);
1621 }
1622
Kenny Root597ea5b2011-08-05 11:19:45 -07001623 delete_file(transport, serial, apk_dest);
1624
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 return err;
1626}