blob: 27a175498c9bcc335c5a3e0f4c8f83afe8454eed [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;
Matt Gumbeld7b33082012-11-14 10:16:17 -080049extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
51static char *product_file(const char *extra)
52{
53 int n;
54 char *x;
55
56 if (gProductOutPath == NULL) {
57 fprintf(stderr, "adb: Product directory not specified; "
58 "use -p or define ANDROID_PRODUCT_OUT\n");
59 exit(1);
60 }
61
62 n = strlen(gProductOutPath) + strlen(extra) + 2;
63 x = malloc(n);
64 if (x == 0) {
65 fprintf(stderr, "adb: Out of memory (product_file())\n");
66 exit(1);
67 }
68
69 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
70 return x;
71}
72
73void version(FILE * out) {
74 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
75 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
76}
77
78void help()
79{
80 version(stderr);
81
82 fprintf(stderr,
83 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080084 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085 " -d - directs command to the only connected USB device\n"
86 " returns an error if more than one USB device is present.\n"
87 " -e - directs command to the only running emulator.\n"
88 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070089 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070090 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070091 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080092 " -p <product name or path> - simple product name like 'sooner', or\n"
93 " a relative/absolute path to a product\n"
94 " out directory like 'out/target/product/sooner'.\n"
95 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
96 " environment variable is used, which must\n"
97 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080098 " -H - Name of adb server host (default: localhost)\n"
99 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700100 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700101 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400102 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
103 " Port 5555 is used by default if no port number is specified.\n"
104 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
105 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200106 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400107 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800108 "\n"
109 "device commands:\n"
110 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato00c0eea2010-01-05 13:42:25 -0800111 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800112 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600113 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800114 " (see 'adb help all')\n"
115 " adb shell - run remote shell interactively\n"
116 " adb shell <command> - run remote shell command\n"
117 " adb emu <command> - run emulator console command\n"
118 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100119 " adb forward --list - list all forward socket connections.\n"
120 " the format is a list of lines with the following format:\n"
121 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800122 " adb forward <local> <remote> - forward socket connections\n"
123 " forward specs are one of: \n"
124 " tcp:<port>\n"
125 " localabstract:<unix domain socket name>\n"
126 " localreserved:<unix domain socket name>\n"
127 " localfilesystem:<unix domain socket name>\n"
128 " dev:<character device name>\n"
129 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100130 " adb forward --no-rebind <local> <remote>\n"
131 " - same as 'adb forward <local> <remote>' but fails\n"
132 " if <local> is already forwarded\n"
133 " adb forward --remove <local> - remove a specific forward socket connection\n"
134 " adb forward --remove-all - remove all forward socket connections\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800135 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700136 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
137 " - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800138 " ('-l' means forward-lock the app)\n"
139 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500140 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700141 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800142 " adb uninstall [-k] <package> - remove this app package from the device\n"
143 " ('-k' means keep the data and cache directories)\n"
144 " adb bugreport - return all information from the device\n"
145 " that should be included in a bug report.\n"
146 "\n"
Christopher Tatef3ae4a22013-03-06 16:40:52 -0800147 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700148 " - write an archive of the device's data to <file>.\n"
149 " If no -f option is supplied then the data is written\n"
150 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700151 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700152 " in the archive; the default is noapk.)\n"
Christopher Tatef3ae4a22013-03-06 16:40:52 -0800153 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
154 " (aka .obb) files associated with each application; the default\n"
155 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700156 " (-shared|-noshared enable/disable backup of the device's\n"
157 " shared storage / SD card contents; the default is noshared.)\n"
158 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700159 " (-system|-nosystem toggles whether -all automatically includes\n"
160 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700161 " (<packages...> is the list of applications to be backed up. If\n"
162 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700163 " list is optional. Applications explicitly given on the\n"
164 " command line will be included even if -nosystem would\n"
165 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700166 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700167 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700168 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 " adb help - show this help message\n"
170 " adb version - show version num\n"
171 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800172 "scripting:\n"
173 " adb wait-for-device - block until device is online\n"
174 " adb start-server - ensure that there is a server running\n"
175 " adb kill-server - kill the server if it is running\n"
176 " adb get-state - prints: offline | bootloader | device\n"
177 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700178 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800179 " adb status-window - continuously print device status for a specified device\n"
180 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400181 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800182 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700183 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800184 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700185 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800186 "\n"
187 "networking:\n"
188 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500189 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
191 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
192 "\n"
193 "adb sync notes: adb sync [ <directory> ]\n"
194 " <localdir> can be interpreted in several ways:\n"
195 "\n"
196 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
197 "\n"
198 " - If it is \"system\" or \"data\", only the corresponding partition\n"
199 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000200 "\n"
201 "environmental variables:\n"
202 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
203 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
204 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
205 " 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 -0800206 );
207}
208
209int usage()
210{
211 help();
212 return 1;
213}
214
215#ifdef HAVE_TERMIO_H
216static struct termios tio_save;
217
218static void stdin_raw_init(int fd)
219{
220 struct termios tio;
221
222 if(tcgetattr(fd, &tio)) return;
223 if(tcgetattr(fd, &tio_save)) return;
224
225 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
226
227 /* no timeout but request at least one character per read */
228 tio.c_cc[VTIME] = 0;
229 tio.c_cc[VMIN] = 1;
230
231 tcsetattr(fd, TCSANOW, &tio);
232 tcflush(fd, TCIFLUSH);
233}
234
235static void stdin_raw_restore(int fd)
236{
237 tcsetattr(fd, TCSANOW, &tio_save);
238 tcflush(fd, TCIFLUSH);
239}
240#endif
241
242static void read_and_dump(int fd)
243{
244 char buf[4096];
245 int len;
246
247 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700248 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800249 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700250 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251 if(len == 0) {
252 break;
253 }
254
255 if(len < 0) {
256 if(errno == EINTR) continue;
257 break;
258 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400259 fwrite(buf, 1, len, stdout);
260 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261 }
262}
263
Christopher Tated2f54152011-04-21 12:53:28 -0700264static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700265 const size_t BUFSIZE = 32 * 1024;
266 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700267 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700268 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700269
270 D("copy_to_file(%d -> %d)\n", inFd, outFd);
271 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700272 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700273 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700274 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700275 break;
276 }
277 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700278 if (errno == EINTR) {
279 D("copy_to_file() : EINTR, retrying\n");
280 continue;
281 }
Christopher Tated2f54152011-04-21 12:53:28 -0700282 D("copy_to_file() : error %d\n", errno);
283 break;
284 }
285 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700286 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700287 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700288 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700289 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700290}
291
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292static void *stdin_read_thread(void *x)
293{
294 int fd, fdi;
295 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296 int r, n;
297 int state = 0;
298
299 int *fds = (int*) x;
300 fd = fds[0];
301 fdi = fds[1];
302 free(fds);
303
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800304 for(;;) {
305 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700306 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700308 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800309 if(r == 0) break;
310 if(r < 0) {
311 if(errno == EINTR) continue;
312 break;
313 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400314 for(n = 0; n < r; n++){
315 switch(buf[n]) {
316 case '\n':
317 state = 1;
318 break;
319 case '\r':
320 state = 1;
321 break;
322 case '~':
323 if(state == 1) state++;
324 break;
325 case '.':
326 if(state == 2) {
327 fprintf(stderr,"\n* disconnect *\n");
328#ifdef HAVE_TERMIO_H
329 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800330#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400331 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800332 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400333 default:
334 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800335 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800336 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800337 r = adb_write(fd, buf, r);
338 if(r <= 0) {
339 break;
340 }
341 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800342 return 0;
343}
344
345int interactive_shell(void)
346{
347 adb_thread_t thr;
348 int fdi, fd;
349 int *fds;
350
351 fd = adb_connect("shell:");
352 if(fd < 0) {
353 fprintf(stderr,"error: %s\n", adb_error());
354 return 1;
355 }
356 fdi = 0; //dup(0);
357
358 fds = malloc(sizeof(int) * 2);
359 fds[0] = fd;
360 fds[1] = fdi;
361
362#ifdef HAVE_TERMIO_H
363 stdin_raw_init(fdi);
364#endif
365 adb_thread_create(&thr, stdin_read_thread, fds);
366 read_and_dump(fd);
367#ifdef HAVE_TERMIO_H
368 stdin_raw_restore(fdi);
369#endif
370 return 0;
371}
372
373
374static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
375{
376 if (serial) {
377 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
378 } else {
379 const char* prefix = "host";
380 if (ttype == kTransportUsb)
381 prefix = "host-usb";
382 else if (ttype == kTransportLocal)
383 prefix = "host-local";
384
385 snprintf(buffer, buflen, "%s:%s", prefix, command);
386 }
387}
388
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100389int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800390 unsigned progress)
391{
392 char buf[4096];
393 unsigned total;
394 int fd;
395 const unsigned char *ptr;
396
397 sprintf(buf,"%s:%d", service, sz);
398 fd = adb_connect(buf);
399 if(fd < 0) {
400 fprintf(stderr,"error: %s\n", adb_error());
401 return -1;
402 }
403
404 int opt = CHUNK_SIZE;
405 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
406
407 total = sz;
408 ptr = data;
409
410 if(progress) {
411 char *x = strrchr(service, ':');
412 if(x) service = x + 1;
413 }
414
415 while(sz > 0) {
416 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
417 if(writex(fd, ptr, xfer)) {
418 adb_status(fd);
419 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
420 return -1;
421 }
422 sz -= xfer;
423 ptr += xfer;
424 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100425 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800426 fflush(stdout);
427 }
428 }
429 if(progress) {
430 printf("\n");
431 }
432
433 if(readx(fd, buf, 4)){
434 fprintf(stderr,"* error reading response *\n");
435 adb_close(fd);
436 return -1;
437 }
438 if(memcmp(buf, "OKAY", 4)) {
439 buf[4] = 0;
440 fprintf(stderr,"* error response '%s' *\n", buf);
441 adb_close(fd);
442 return -1;
443 }
444
445 adb_close(fd);
446 return 0;
447}
448
449
450int adb_download(const char *service, const char *fn, unsigned progress)
451{
452 void *data;
453 unsigned sz;
454
455 data = load_file(fn, &sz);
456 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100457 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800458 return -1;
459 }
460
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100461 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800462 free(data);
463 return status;
464}
465
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800466static void status_window(transport_type ttype, const char* serial)
467{
468 char command[4096];
469 char *state = 0;
470 char *laststate = 0;
471
472 /* silence stderr */
473#ifdef _WIN32
474 /* XXX: TODO */
475#else
476 int fd;
477 fd = unix_open("/dev/null", O_WRONLY);
478 dup2(fd, 2);
479 adb_close(fd);
480#endif
481
482 format_host_command(command, sizeof command, "get-state", ttype, serial);
483
484 for(;;) {
485 adb_sleep_ms(250);
486
487 if(state) {
488 free(state);
489 state = 0;
490 }
491
492 state = adb_query(command);
493
494 if(state) {
495 if(laststate && !strcmp(state,laststate)){
496 continue;
497 } else {
498 if(laststate) free(laststate);
499 laststate = strdup(state);
500 }
501 }
502
503 printf("%c[2J%c[2H", 27, 27);
504 printf("Android Debug Bridge\n");
505 printf("State: %s\n", state ? state : "offline");
506 fflush(stdout);
507 }
508}
509
510/** duplicate string and quote all \ " ( ) chars + space character. */
511static char *
512dupAndQuote(const char *s)
513{
514 const char *ts;
515 size_t alloc_len;
516 char *ret;
517 char *dest;
518
519 ts = s;
520
521 alloc_len = 0;
522
523 for( ;*ts != '\0'; ts++) {
524 alloc_len++;
525 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
526 alloc_len++;
527 }
528 }
529
530 ret = (char *)malloc(alloc_len + 1);
531
532 ts = s;
533 dest = ret;
534
535 for ( ;*ts != '\0'; ts++) {
536 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
537 *dest++ = '\\';
538 }
539
540 *dest++ = *ts;
541 }
542
543 *dest++ = '\0';
544
545 return ret;
546}
547
548/**
549 * Run ppp in "notty" mode against a resource listed as the first parameter
550 * eg:
551 *
552 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
553 *
554 */
555int ppp(int argc, char **argv)
556{
557#ifdef HAVE_WIN32_PROC
558 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
559 return -1;
560#else
561 char *adb_service_name;
562 pid_t pid;
563 int fd;
564
565 if (argc < 2) {
566 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
567 argv[0]);
568
569 return 1;
570 }
571
572 adb_service_name = argv[1];
573
574 fd = adb_connect(adb_service_name);
575
576 if(fd < 0) {
577 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
578 adb_service_name, adb_error());
579 return 1;
580 }
581
582 pid = fork();
583
584 if (pid < 0) {
585 perror("from fork()");
586 return 1;
587 } else if (pid == 0) {
588 int err;
589 int i;
590 const char **ppp_args;
591
592 // copy args
593 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
594 ppp_args[0] = "pppd";
595 for (i = 2 ; i < argc ; i++) {
596 //argv[2] and beyond become ppp_args[1] and beyond
597 ppp_args[i - 1] = argv[i];
598 }
599 ppp_args[i-1] = NULL;
600
601 // child side
602
603 dup2(fd, STDIN_FILENO);
604 dup2(fd, STDOUT_FILENO);
605 adb_close(STDERR_FILENO);
606 adb_close(fd);
607
608 err = execvp("pppd", (char * const *)ppp_args);
609
610 if (err < 0) {
611 perror("execing pppd");
612 }
613 exit(-1);
614 } else {
615 // parent side
616
617 adb_close(fd);
618 return 0;
619 }
620#endif /* !HAVE_WIN32_PROC */
621}
622
623static int send_shellcommand(transport_type transport, char* serial, char* buf)
624{
625 int fd, ret;
626
627 for(;;) {
628 fd = adb_connect(buf);
629 if(fd >= 0)
630 break;
631 fprintf(stderr,"- waiting for device -\n");
632 adb_sleep_ms(1000);
633 do_cmd(transport, serial, "wait-for-device", 0);
634 }
635
636 read_and_dump(fd);
637 ret = adb_close(fd);
638 if (ret)
639 perror("close");
640
641 return ret;
642}
643
644static int logcat(transport_type transport, char* serial, int argc, char **argv)
645{
646 char buf[4096];
647
648 char *log_tags;
649 char *quoted_log_tags;
650
651 log_tags = getenv("ANDROID_LOG_TAGS");
652 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
653
654 snprintf(buf, sizeof(buf),
655 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
656 quoted_log_tags);
657
658 free(quoted_log_tags);
659
Christopher Tatedb0a8802011-11-30 13:00:33 -0800660 if (!strcmp(argv[0],"longcat")) {
661 strncat(buf, " -v long", sizeof(buf)-1);
662 }
663
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800664 argc -= 1;
665 argv += 1;
666 while(argc-- > 0) {
667 char *quoted;
668
669 quoted = dupAndQuote (*argv++);
670
671 strncat(buf, " ", sizeof(buf)-1);
672 strncat(buf, quoted, sizeof(buf)-1);
673 free(quoted);
674 }
675
676 send_shellcommand(transport, serial, buf);
677 return 0;
678}
679
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800680static int mkdirs(char *path)
681{
682 int ret;
683 char *x = path + 1;
684
685 for(;;) {
686 x = adb_dirstart(x);
687 if(x == 0) return 0;
688 *x = 0;
689 ret = adb_mkdir(path, 0775);
690 *x = OS_PATH_SEPARATOR;
691 if((ret < 0) && (errno != EEXIST)) {
692 return ret;
693 }
694 x++;
695 }
696 return 0;
697}
698
Christopher Tated2f54152011-04-21 12:53:28 -0700699static int backup(int argc, char** argv) {
700 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800701 char default_name[32];
702 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700703 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700704 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700705
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700706 /* find, extract, and use any -f argument */
707 for (i = 1; i < argc; i++) {
708 if (!strcmp("-f", argv[i])) {
709 if (i == argc-1) {
710 fprintf(stderr, "adb: -f passed with no filename\n");
711 return usage();
712 }
713 filename = argv[i+1];
714 for (j = i+2; j <= argc; ) {
715 argv[i++] = argv[j++];
716 }
717 argc -= 2;
718 argv[argc] = NULL;
719 }
Christopher Tated2f54152011-04-21 12:53:28 -0700720 }
721
Christopher Tatebb86bc52011-08-22 17:12:08 -0700722 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
723 if (argc < 2) return usage();
724
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800725 adb_unlink(filename);
726 mkdirs((char *)filename);
727 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700728 if (outFd < 0) {
729 fprintf(stderr, "adb: unable to open file %s\n", filename);
730 return -1;
731 }
732
733 snprintf(buf, sizeof(buf), "backup");
734 for (argc--, argv++; argc; argc--, argv++) {
735 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
736 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
737 }
738
739 D("backup. filename=%s buf=%s\n", filename, buf);
740 fd = adb_connect(buf);
741 if (fd < 0) {
742 fprintf(stderr, "adb: unable to connect for backup\n");
743 adb_close(outFd);
744 return -1;
745 }
746
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800747 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700748 copy_to_file(fd, outFd);
749
750 adb_close(fd);
751 adb_close(outFd);
752 return 0;
753}
754
Christopher Tate702967a2011-05-17 15:52:54 -0700755static int restore(int argc, char** argv) {
756 const char* filename;
757 int fd, tarFd;
758
759 if (argc != 2) return usage();
760
761 filename = argv[1];
762 tarFd = adb_open(filename, O_RDONLY);
763 if (tarFd < 0) {
764 fprintf(stderr, "adb: unable to open file %s\n", filename);
765 return -1;
766 }
767
768 fd = adb_connect("restore:");
769 if (fd < 0) {
770 fprintf(stderr, "adb: unable to connect for backup\n");
771 adb_close(tarFd);
772 return -1;
773 }
774
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800775 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700776 copy_to_file(tarFd, fd);
777
778 adb_close(fd);
779 adb_close(tarFd);
780 return 0;
781}
782
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800783#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
784static int top_works(const char *top)
785{
786 if (top != NULL && adb_is_absolute_host_path(top)) {
787 char path_buf[PATH_MAX];
788 snprintf(path_buf, sizeof(path_buf),
789 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
790 return access(path_buf, F_OK) == 0;
791 }
792 return 0;
793}
794
795static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
796{
797 strcpy(path_buf, indir);
798 while (1) {
799 if (top_works(path_buf)) {
800 return path_buf;
801 }
802 char *s = adb_dirstop(path_buf);
803 if (s != NULL) {
804 *s = '\0';
805 } else {
806 path_buf[0] = '\0';
807 return NULL;
808 }
809 }
810}
811
812static char *find_top(char path_buf[PATH_MAX])
813{
814 char *top = getenv("ANDROID_BUILD_TOP");
815 if (top != NULL && top[0] != '\0') {
816 if (!top_works(top)) {
817 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
818 return NULL;
819 }
820 } else {
821 top = getenv("TOP");
822 if (top != NULL && top[0] != '\0') {
823 if (!top_works(top)) {
824 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
825 return NULL;
826 }
827 } else {
828 top = NULL;
829 }
830 }
831
832 if (top != NULL) {
833 /* The environment pointed to a top directory that works.
834 */
835 strcpy(path_buf, top);
836 return path_buf;
837 }
838
839 /* The environment didn't help. Walk up the tree from the CWD
840 * to see if we can find the top.
841 */
842 char dir[PATH_MAX];
843 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
844 if (top == NULL) {
845 /* If the CWD isn't under a good-looking top, see if the
846 * executable is.
847 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100848 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800849 top = find_top_from(dir, path_buf);
850 }
851 return top;
852}
853
854/* <hint> may be:
855 * - A simple product name
856 * e.g., "sooner"
857TODO: debug? sooner-debug, sooner:debug?
858 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
859 * e.g., "out/target/product/sooner"
860 * - An absolute path to the PRODUCT_OUT dir
861 * e.g., "/src/device/out/target/product/sooner"
862 *
863 * Given <hint>, try to construct an absolute path to the
864 * ANDROID_PRODUCT_OUT dir.
865 */
866static const char *find_product_out_path(const char *hint)
867{
868 static char path_buf[PATH_MAX];
869
870 if (hint == NULL || hint[0] == '\0') {
871 return NULL;
872 }
873
874 /* If it's already absolute, don't bother doing any work.
875 */
876 if (adb_is_absolute_host_path(hint)) {
877 strcpy(path_buf, hint);
878 return path_buf;
879 }
880
881 /* If there are any slashes in it, assume it's a relative path;
882 * make it absolute.
883 */
884 if (adb_dirstart(hint) != NULL) {
885 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
886 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
887 return NULL;
888 }
889 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
890 fprintf(stderr, "adb: Couldn't assemble path\n");
891 return NULL;
892 }
893 strcat(path_buf, OS_PATH_SEPARATOR_STR);
894 strcat(path_buf, hint);
895 return path_buf;
896 }
897
898 /* It's a string without any slashes. Try to do something with it.
899 *
900 * Try to find the root of the build tree, and build a PRODUCT_OUT
901 * path from there.
902 */
903 char top_buf[PATH_MAX];
904 const char *top = find_top(top_buf);
905 if (top == NULL) {
906 fprintf(stderr, "adb: Couldn't find top of build tree\n");
907 return NULL;
908 }
909//TODO: if we have a way to indicate debug, look in out/debug/target/...
910 snprintf(path_buf, sizeof(path_buf),
911 "%s" OS_PATH_SEPARATOR_STR
912 "out" OS_PATH_SEPARATOR_STR
913 "target" OS_PATH_SEPARATOR_STR
914 "product" OS_PATH_SEPARATOR_STR
915 "%s", top_buf, hint);
916 if (access(path_buf, F_OK) < 0) {
917 fprintf(stderr, "adb: Couldn't find a product dir "
918 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
919 return NULL;
920 }
921 return path_buf;
922}
923
924int adb_commandline(int argc, char **argv)
925{
926 char buf[4096];
927 int no_daemon = 0;
928 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100929 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800930 int persist = 0;
931 int r;
932 int quote;
933 transport_type ttype = kTransportAny;
934 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100935 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800936
937 /* If defined, this should be an absolute path to
938 * the directory containing all of the various system images
939 * for a particular product. If not defined, and the adb
940 * command requires this information, then the user must
941 * specify the path using "-p".
942 */
943 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
944 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
945 gProductOutPath = NULL;
946 }
947 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
948
Nick Pellydb449262009-05-07 12:48:03 -0700949 serial = getenv("ANDROID_SERIAL");
950
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100951 /* Validate and assign the server port */
952 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
953 int server_port = DEFAULT_ADB_PORT;
954 if (server_port_str && strlen(server_port_str) > 0) {
955 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800956 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100957 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800958 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100959 server_port_str);
960 return usage();
961 }
962 }
963
964 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800965 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100966 if(!strcmp(argv[0],"server")) {
967 is_server = 1;
968 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800969 no_daemon = 1;
970 } else if (!strcmp(argv[0], "fork-server")) {
971 /* this is a special flag used only when the ADB client launches the ADB Server */
972 is_daemon = 1;
973 } else if(!strcmp(argv[0],"persist")) {
974 persist = 1;
975 } else if(!strncmp(argv[0], "-p", 2)) {
976 const char *product = NULL;
977 if (argv[0][2] == '\0') {
978 if (argc < 2) return usage();
979 product = argv[1];
980 argc--;
981 argv++;
982 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -0700983 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800984 }
985 gProductOutPath = find_product_out_path(product);
986 if (gProductOutPath == NULL) {
987 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
988 product);
989 return usage();
990 }
991 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
992 if (isdigit(argv[0][2])) {
993 serial = argv[0] + 2;
994 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100995 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 serial = argv[1];
997 argc--;
998 argv++;
999 }
1000 } else if (!strcmp(argv[0],"-d")) {
1001 ttype = kTransportUsb;
1002 } else if (!strcmp(argv[0],"-e")) {
1003 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001004 } else if (!strcmp(argv[0],"-a")) {
1005 gListenAll = 1;
1006 } else if(!strncmp(argv[0], "-H", 2)) {
1007 const char *hostname = NULL;
1008 if (argv[0][2] == '\0') {
1009 if (argc < 2) return usage();
1010 hostname = argv[1];
1011 argc--;
1012 argv++;
1013 } else {
1014 hostname = argv[0] + 2;
1015 }
1016 adb_set_tcp_name(hostname);
1017
1018 } else if(!strncmp(argv[0], "-P", 2)) {
1019 if (argv[0][2] == '\0') {
1020 if (argc < 2) return usage();
1021 server_port_str = argv[1];
1022 argc--;
1023 argv++;
1024 } else {
1025 server_port_str = argv[0] + 2;
1026 }
1027 if (strlen(server_port_str) > 0) {
1028 server_port = (int) strtol(server_port_str, NULL, 0);
1029 if (server_port <= 0 || server_port > 65535) {
1030 fprintf(stderr,
1031 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1032 server_port_str);
1033 return usage();
1034 }
1035 } else {
1036 fprintf(stderr,
1037 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1038 return usage();
1039 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001040 } else {
1041 /* out of recognized modifiers and flags */
1042 break;
1043 }
1044 argc--;
1045 argv++;
1046 }
1047
1048 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001049 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001050
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001051 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001052 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001053 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001054 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001055 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001056 }
1057 if(r) {
1058 fprintf(stderr,"* could not start server *\n");
1059 }
1060 return r;
1061 }
1062
1063top:
1064 if(argc == 0) {
1065 return usage();
1066 }
1067
1068 /* adb_connect() commands */
1069
1070 if(!strcmp(argv[0], "devices")) {
1071 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001072 char *listopt;
1073 if (argc < 2)
1074 listopt = "";
1075 else if (argc == 2 && !strcmp(argv[1], "-l"))
1076 listopt = argv[1];
1077 else {
1078 fprintf(stderr, "Usage: adb devices [-l]\n");
1079 return 1;
1080 }
1081 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001082 tmp = adb_query(buf);
1083 if(tmp) {
1084 printf("List of devices attached \n");
1085 printf("%s\n", tmp);
1086 return 0;
1087 } else {
1088 return 1;
1089 }
1090 }
1091
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001092 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001093 char *tmp;
1094 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001095 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001096 return 1;
1097 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001098 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1099 tmp = adb_query(buf);
1100 if(tmp) {
1101 printf("%s\n", tmp);
1102 return 0;
1103 } else {
1104 return 1;
1105 }
1106 }
1107
1108 if(!strcmp(argv[0], "disconnect")) {
1109 char *tmp;
1110 if (argc > 2) {
1111 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1112 return 1;
1113 }
1114 if (argc == 2) {
1115 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1116 } else {
1117 snprintf(buf, sizeof buf, "host:disconnect:");
1118 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001119 tmp = adb_query(buf);
1120 if(tmp) {
1121 printf("%s\n", tmp);
1122 return 0;
1123 } else {
1124 return 1;
1125 }
1126 }
1127
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001128 if (!strcmp(argv[0], "emu")) {
1129 return adb_send_emulator_command(argc, argv);
1130 }
1131
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001132 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133 int r;
1134 int fd;
1135
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001136 char h = (argv[0][0] == 'h');
1137
1138 if (h) {
1139 printf("\x1b[41;33m");
1140 fflush(stdout);
1141 }
1142
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001143 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001144 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001145 r = interactive_shell();
1146 if (h) {
1147 printf("\x1b[0m");
1148 fflush(stdout);
1149 }
1150 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001151 }
1152
1153 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1154 argc -= 2;
1155 argv += 2;
1156 while(argc-- > 0) {
1157 strcat(buf, " ");
1158
1159 /* quote empty strings and strings with spaces */
1160 quote = (**argv == 0 || strchr(*argv, ' '));
1161 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001162 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 strcat(buf, *argv++);
1164 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001165 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001166 }
1167
1168 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001169 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001170 fd = adb_connect(buf);
1171 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001172 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001173 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001174 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 adb_close(fd);
1176 r = 0;
1177 } else {
1178 fprintf(stderr,"error: %s\n", adb_error());
1179 r = -1;
1180 }
1181
1182 if(persist) {
1183 fprintf(stderr,"\n- waiting for device -\n");
1184 adb_sleep_ms(1000);
1185 do_cmd(ttype, serial, "wait-for-device", 0);
1186 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001187 if (h) {
1188 printf("\x1b[0m");
1189 fflush(stdout);
1190 }
JP Abgrall408fa572011-03-16 15:57:42 -07001191 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 return r;
1193 }
1194 }
1195 }
1196
1197 if(!strcmp(argv[0], "kill-server")) {
1198 int fd;
1199 fd = _adb_connect("host:kill");
1200 if(fd == -1) {
1201 fprintf(stderr,"* server not running *\n");
1202 return 1;
1203 }
1204 return 0;
1205 }
1206
Doug Zongker447f0612012-01-09 14:54:53 -08001207 if(!strcmp(argv[0], "sideload")) {
1208 if(argc != 2) return usage();
1209 if(adb_download("sideload", argv[1], 1)) {
1210 return 1;
1211 } else {
1212 return 0;
1213 }
1214 }
1215
Mike Lockwoodff196702009-08-24 15:58:40 -07001216 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001217 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001218 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001219 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001220 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001221 if (!strcmp(argv[0], "reboot-bootloader"))
1222 snprintf(command, sizeof(command), "reboot:bootloader");
1223 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001224 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001225 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001226 snprintf(command, sizeof(command), "%s:", argv[0]);
1227 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001228 if(fd >= 0) {
1229 read_and_dump(fd);
1230 adb_close(fd);
1231 return 0;
1232 }
1233 fprintf(stderr,"error: %s\n", adb_error());
1234 return 1;
1235 }
1236
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001237 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001238 if (argc != 1) return usage();
1239 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001240 return 0;
1241 }
1242
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001243 /* adb_command() wrapper commands */
1244
1245 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1246 char* service = argv[0];
1247 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1248 if (ttype == kTransportUsb) {
1249 service = "wait-for-usb";
1250 } else if (ttype == kTransportLocal) {
1251 service = "wait-for-local";
1252 } else {
1253 service = "wait-for-any";
1254 }
1255 }
1256
1257 format_host_command(buf, sizeof buf, service, ttype, serial);
1258
1259 if (adb_command(buf)) {
1260 D("failure: %s *\n",adb_error());
1261 fprintf(stderr,"error: %s\n", adb_error());
1262 return 1;
1263 }
1264
1265 /* Allow a command to be run after wait-for-device,
1266 * e.g. 'adb wait-for-device shell'.
1267 */
1268 if(argc > 1) {
1269 argc--;
1270 argv++;
1271 goto top;
1272 }
1273 return 0;
1274 }
1275
1276 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001277 char host_prefix[64];
1278 char remove = 0;
1279 char remove_all = 0;
1280 char list = 0;
1281 char no_rebind = 0;
1282
1283 // Parse options here.
1284 while (argc > 1 && argv[1][0] == '-') {
1285 if (!strcmp(argv[1], "--list"))
1286 list = 1;
1287 else if (!strcmp(argv[1], "--remove"))
1288 remove = 1;
1289 else if (!strcmp(argv[1], "--remove-all"))
1290 remove_all = 1;
1291 else if (!strcmp(argv[1], "--no-rebind"))
1292 no_rebind = 1;
1293 else {
1294 return usage();
1295 }
1296 argc--;
1297 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001298 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001299
1300 // Ensure we can only use one option at a time.
1301 if (list + remove + remove_all + no_rebind > 1) {
1302 return usage();
1303 }
1304
1305 // Determine the <host-prefix> for this command.
1306 if (serial) {
1307 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1308 serial);
1309 } else if (ttype == kTransportUsb) {
1310 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1311 } else if (ttype == kTransportLocal) {
1312 snprintf(host_prefix, sizeof host_prefix, "host-local");
1313 } else {
1314 snprintf(host_prefix, sizeof host_prefix, "host");
1315 }
1316
1317 // Implement forward --list
1318 if (list) {
1319 if (argc != 1)
1320 return usage();
1321 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1322 char* forwards = adb_query(buf);
1323 if (forwards == NULL) {
1324 fprintf(stderr, "error: %s\n", adb_error());
1325 return 1;
1326 }
1327 printf("%s", forwards);
1328 free(forwards);
1329 return 0;
1330 }
1331
1332 // Implement forward --remove-all
1333 else if (remove_all) {
1334 if (argc != 1)
1335 return usage();
1336 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1337 }
1338
1339 // Implement forward --remove <local>
1340 else if (remove) {
1341 if (argc != 2)
1342 return usage();
1343 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1344 }
1345 // Or implement one of:
1346 // forward <local> <remote>
1347 // forward --no-rebind <local> <remote>
1348 else
1349 {
1350 if (argc != 3)
1351 return usage();
1352 const char* command = no_rebind ? "forward:norebind:" : "forward";
1353 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1354 }
1355
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001356 if(adb_command(buf)) {
1357 fprintf(stderr,"error: %s\n", adb_error());
1358 return 1;
1359 }
1360 return 0;
1361 }
1362
1363 /* do_sync_*() commands */
1364
1365 if(!strcmp(argv[0], "ls")) {
1366 if(argc != 2) return usage();
1367 return do_sync_ls(argv[1]);
1368 }
1369
1370 if(!strcmp(argv[0], "push")) {
1371 if(argc != 3) return usage();
1372 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1373 }
1374
1375 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001376 if (argc == 2) {
1377 return do_sync_pull(argv[1], ".");
1378 } else if (argc == 3) {
1379 return do_sync_pull(argv[1], argv[2]);
1380 } else {
1381 return usage();
1382 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001383 }
1384
1385 if(!strcmp(argv[0], "install")) {
1386 if (argc < 2) return usage();
1387 return install_app(ttype, serial, argc, argv);
1388 }
1389
1390 if(!strcmp(argv[0], "uninstall")) {
1391 if (argc < 2) return usage();
1392 return uninstall_app(ttype, serial, argc, argv);
1393 }
1394
1395 if(!strcmp(argv[0], "sync")) {
1396 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001397 int listonly = 0;
1398
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001399 int ret;
1400 if(argc < 2) {
1401 /* No local path was specified. */
1402 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001403 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1404 listonly = 1;
1405 if (argc == 3) {
1406 srcarg = argv[2];
1407 } else {
1408 srcarg = NULL;
1409 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 } else if(argc == 2) {
1411 /* A local path or "android"/"data" arg was specified. */
1412 srcarg = argv[1];
1413 } else {
1414 return usage();
1415 }
1416 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1417 if(ret != 0) return usage();
1418
1419 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001420 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001421 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001422 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423
1424 free(android_srcpath);
1425 free(data_srcpath);
1426 return ret;
1427 }
1428
1429 /* passthrough commands */
1430
1431 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001432 !strcmp(argv[0],"get-serialno") ||
1433 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001434 {
1435 char *tmp;
1436
1437 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1438 tmp = adb_query(buf);
1439 if(tmp) {
1440 printf("%s\n", tmp);
1441 return 0;
1442 } else {
1443 return 1;
1444 }
1445 }
1446
1447 /* other commands */
1448
1449 if(!strcmp(argv[0],"status-window")) {
1450 status_window(ttype, serial);
1451 return 0;
1452 }
1453
Christopher Tatedb0a8802011-11-30 13:00:33 -08001454 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001455 return logcat(ttype, serial, argc, argv);
1456 }
1457
1458 if(!strcmp(argv[0],"ppp")) {
1459 return ppp(argc, argv);
1460 }
1461
1462 if (!strcmp(argv[0], "start-server")) {
1463 return adb_connect("host:start-server");
1464 }
1465
Christopher Tated2f54152011-04-21 12:53:28 -07001466 if (!strcmp(argv[0], "backup")) {
1467 return backup(argc, argv);
1468 }
1469
Christopher Tate702967a2011-05-17 15:52:54 -07001470 if (!strcmp(argv[0], "restore")) {
1471 return restore(argc, argv);
1472 }
1473
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001474 if (!strcmp(argv[0], "jdwp")) {
1475 int fd = adb_connect("jdwp");
1476 if (fd >= 0) {
1477 read_and_dump(fd);
1478 adb_close(fd);
1479 return 0;
1480 } else {
1481 fprintf(stderr, "error: %s\n", adb_error());
1482 return -1;
1483 }
1484 }
1485
1486 /* "adb /?" is a common idiom under Windows */
1487 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1488 help();
1489 return 0;
1490 }
1491
1492 if(!strcmp(argv[0], "version")) {
1493 version(stdout);
1494 return 0;
1495 }
1496
1497 usage();
1498 return 1;
1499}
1500
1501static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1502{
1503 char *argv[16];
1504 int argc;
1505 va_list ap;
1506
1507 va_start(ap, cmd);
1508 argc = 0;
1509
1510 if (serial) {
1511 argv[argc++] = "-s";
1512 argv[argc++] = serial;
1513 } else if (ttype == kTransportUsb) {
1514 argv[argc++] = "-d";
1515 } else if (ttype == kTransportLocal) {
1516 argv[argc++] = "-e";
1517 }
1518
1519 argv[argc++] = cmd;
1520 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1521 va_end(ap);
1522
1523#if 0
1524 int n;
1525 fprintf(stderr,"argc = %d\n",argc);
1526 for(n = 0; n < argc; n++) {
1527 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1528 }
1529#endif
1530
1531 return adb_commandline(argc, argv);
1532}
1533
1534int find_sync_dirs(const char *srcarg,
1535 char **android_srcdir_out, char **data_srcdir_out)
1536{
1537 char *android_srcdir, *data_srcdir;
1538
1539 if(srcarg == NULL) {
1540 android_srcdir = product_file("system");
1541 data_srcdir = product_file("data");
1542 } else {
1543 /* srcarg may be "data", "system" or NULL.
1544 * if srcarg is NULL, then both data and system are synced
1545 */
1546 if(strcmp(srcarg, "system") == 0) {
1547 android_srcdir = product_file("system");
1548 data_srcdir = NULL;
1549 } else if(strcmp(srcarg, "data") == 0) {
1550 android_srcdir = NULL;
1551 data_srcdir = product_file("data");
1552 } else {
1553 /* It's not "system" or "data".
1554 */
1555 return 1;
1556 }
1557 }
1558
1559 if(android_srcdir_out != NULL)
1560 *android_srcdir_out = android_srcdir;
1561 else
1562 free(android_srcdir);
1563
1564 if(data_srcdir_out != NULL)
1565 *data_srcdir_out = data_srcdir;
1566 else
1567 free(data_srcdir);
1568
1569 return 0;
1570}
1571
1572static int pm_command(transport_type transport, char* serial,
1573 int argc, char** argv)
1574{
1575 char buf[4096];
1576
1577 snprintf(buf, sizeof(buf), "shell:pm");
1578
1579 while(argc-- > 0) {
1580 char *quoted;
1581
1582 quoted = dupAndQuote(*argv++);
1583
1584 strncat(buf, " ", sizeof(buf)-1);
1585 strncat(buf, quoted, sizeof(buf)-1);
1586 free(quoted);
1587 }
1588
1589 send_shellcommand(transport, serial, buf);
1590 return 0;
1591}
1592
1593int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1594{
1595 /* if the user choose the -k option, we refuse to do it until devices are
1596 out with the option to uninstall the remaining data somehow (adb/ui) */
1597 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1598 {
1599 printf(
1600 "The -k option uninstalls the application while retaining the data/cache.\n"
1601 "At the moment, there is no way to remove the remaining data.\n"
1602 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1603 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1604 return -1;
1605 }
1606
1607 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1608 return pm_command(transport, serial, argc, argv);
1609}
1610
1611static int delete_file(transport_type transport, char* serial, char* filename)
1612{
1613 char buf[4096];
1614 char* quoted;
1615
1616 snprintf(buf, sizeof(buf), "shell:rm ");
1617 quoted = dupAndQuote(filename);
1618 strncat(buf, quoted, sizeof(buf)-1);
1619 free(quoted);
1620
1621 send_shellcommand(transport, serial, buf);
1622 return 0;
1623}
1624
Kenny Root597ea5b2011-08-05 11:19:45 -07001625static const char* get_basename(const char* filename)
1626{
1627 const char* basename = adb_dirstop(filename);
1628 if (basename) {
1629 basename++;
1630 return basename;
1631 } else {
1632 return filename;
1633 }
1634}
1635
1636static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637{
1638 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001639
Kenny Root597ea5b2011-08-05 11:19:45 -07001640 if (filename == NULL) {
1641 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001642 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001643
Kenny Root597ea5b2011-08-05 11:19:45 -07001644 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001645 fprintf(stderr, "can't find '%s' to install\n", filename);
1646 return 1;
1647 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001648
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001649 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001650 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001651 return 1;
1652 }
1653
Kenny Root597ea5b2011-08-05 11:19:45 -07001654 return 0;
1655}
1656
1657int install_app(transport_type transport, char* serial, int argc, char** argv)
1658{
1659 static const char *const DATA_DEST = "/data/local/tmp/%s";
1660 static const char *const SD_DEST = "/sdcard/tmp/%s";
1661 const char* where = DATA_DEST;
1662 char apk_dest[PATH_MAX];
1663 char verification_dest[PATH_MAX];
1664 char* apk_file;
1665 char* verification_file = NULL;
1666 int file_arg = -1;
1667 int err;
1668 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001669 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001670
1671 for (i = 1; i < argc; i++) {
1672 if (*argv[i] != '-') {
1673 file_arg = i;
1674 break;
Kenny Roota031a912011-09-23 12:46:39 -07001675 } else if (!strcmp(argv[i], "-i")) {
1676 // Skip the installer package name.
1677 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001678 } else if (!strcmp(argv[i], "-s")) {
1679 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001680 } else if (!strcmp(argv[i], "--algo")) {
1681 verify_apk = 0;
1682 i++;
1683 } else if (!strcmp(argv[i], "--iv")) {
1684 verify_apk = 0;
1685 i++;
1686 } else if (!strcmp(argv[i], "--key")) {
1687 verify_apk = 0;
1688 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001689 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 }
1691
Kenny Root597ea5b2011-08-05 11:19:45 -07001692 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001693 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001694 return 1;
1695 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001696 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001697 return 1;
1698 }
1699
1700 apk_file = argv[file_arg];
1701
1702 if (file_arg != argc - 1) {
1703 verification_file = argv[file_arg + 1];
1704 }
1705
1706 if (check_file(apk_file) || check_file(verification_file)) {
1707 return 1;
1708 }
1709
1710 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1711 if (verification_file != NULL) {
1712 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1713
1714 if (!strcmp(apk_dest, verification_dest)) {
1715 fprintf(stderr, "APK and verification file can't have the same name\n");
1716 return 1;
1717 }
1718 }
1719
Anonymous Coward4474ac42012-04-24 10:43:41 -07001720 err = do_sync_push(apk_file, apk_dest, verify_apk);
Kenny Root597ea5b2011-08-05 11:19:45 -07001721 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001722 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001723 } else {
1724 argv[file_arg] = apk_dest; /* destination name, not source location */
1725 }
1726
1727 if (verification_file != NULL) {
1728 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1729 if (err) {
1730 goto cleanup_apk;
1731 } else {
1732 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1733 }
1734 }
1735
1736 pm_command(transport, serial, argc, argv);
1737
Kenny Root60733e92012-03-26 16:14:02 -07001738cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001739 if (verification_file != NULL) {
1740 delete_file(transport, serial, verification_dest);
1741 }
1742
Kenny Root597ea5b2011-08-05 11:19:45 -07001743 delete_file(transport, serial, apk_dest);
1744
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001745 return err;
1746}