blob: a927423b49f3116641ab3a76698828e9b2a4ddb1 [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 Tate56885092011-10-03 18:27:01 -0700147 " adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
148 " - 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 Tated2f54152011-04-21 12:53:28 -0700153 " (-shared|-noshared enable/disable backup of the device's\n"
154 " shared storage / SD card contents; the default is noshared.)\n"
155 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700156 " (-system|-nosystem toggles whether -all automatically includes\n"
157 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700158 " (<packages...> is the list of applications to be backed up. If\n"
159 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700160 " list is optional. Applications explicitly given on the\n"
161 " command line will be included even if -nosystem would\n"
162 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700163 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700164 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700165 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166 " adb help - show this help message\n"
167 " adb version - show version num\n"
168 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 "scripting:\n"
170 " adb wait-for-device - block until device is online\n"
171 " adb start-server - ensure that there is a server running\n"
172 " adb kill-server - kill the server if it is running\n"
173 " adb get-state - prints: offline | bootloader | device\n"
174 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700175 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800176 " adb status-window - continuously print device status for a specified device\n"
177 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400178 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800179 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700180 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800181 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700182 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800183 "\n"
184 "networking:\n"
185 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500186 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800187 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
188 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
189 "\n"
190 "adb sync notes: adb sync [ <directory> ]\n"
191 " <localdir> can be interpreted in several ways:\n"
192 "\n"
193 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
194 "\n"
195 " - If it is \"system\" or \"data\", only the corresponding partition\n"
196 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000197 "\n"
198 "environmental variables:\n"
199 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
200 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
201 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
202 " 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 -0800203 );
204}
205
206int usage()
207{
208 help();
209 return 1;
210}
211
212#ifdef HAVE_TERMIO_H
213static struct termios tio_save;
214
215static void stdin_raw_init(int fd)
216{
217 struct termios tio;
218
219 if(tcgetattr(fd, &tio)) return;
220 if(tcgetattr(fd, &tio_save)) return;
221
222 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
223
224 /* no timeout but request at least one character per read */
225 tio.c_cc[VTIME] = 0;
226 tio.c_cc[VMIN] = 1;
227
228 tcsetattr(fd, TCSANOW, &tio);
229 tcflush(fd, TCIFLUSH);
230}
231
232static void stdin_raw_restore(int fd)
233{
234 tcsetattr(fd, TCSANOW, &tio_save);
235 tcflush(fd, TCIFLUSH);
236}
237#endif
238
239static void read_and_dump(int fd)
240{
241 char buf[4096];
242 int len;
243
244 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700245 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800246 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700247 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248 if(len == 0) {
249 break;
250 }
251
252 if(len < 0) {
253 if(errno == EINTR) continue;
254 break;
255 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400256 fwrite(buf, 1, len, stdout);
257 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258 }
259}
260
Christopher Tated2f54152011-04-21 12:53:28 -0700261static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700262 const size_t BUFSIZE = 32 * 1024;
263 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700264 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700265 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700266
267 D("copy_to_file(%d -> %d)\n", inFd, outFd);
268 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700269 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700270 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700271 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700272 break;
273 }
274 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700275 if (errno == EINTR) {
276 D("copy_to_file() : EINTR, retrying\n");
277 continue;
278 }
Christopher Tated2f54152011-04-21 12:53:28 -0700279 D("copy_to_file() : error %d\n", errno);
280 break;
281 }
282 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700283 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700284 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700285 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700286 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700287}
288
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800289static void *stdin_read_thread(void *x)
290{
291 int fd, fdi;
292 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800293 int r, n;
294 int state = 0;
295
296 int *fds = (int*) x;
297 fd = fds[0];
298 fdi = fds[1];
299 free(fds);
300
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301 for(;;) {
302 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700303 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800304 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700305 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800306 if(r == 0) break;
307 if(r < 0) {
308 if(errno == EINTR) continue;
309 break;
310 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400311 for(n = 0; n < r; n++){
312 switch(buf[n]) {
313 case '\n':
314 state = 1;
315 break;
316 case '\r':
317 state = 1;
318 break;
319 case '~':
320 if(state == 1) state++;
321 break;
322 case '.':
323 if(state == 2) {
324 fprintf(stderr,"\n* disconnect *\n");
325#ifdef HAVE_TERMIO_H
326 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800327#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400328 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800329 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400330 default:
331 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800332 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800333 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800334 r = adb_write(fd, buf, r);
335 if(r <= 0) {
336 break;
337 }
338 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800339 return 0;
340}
341
342int interactive_shell(void)
343{
344 adb_thread_t thr;
345 int fdi, fd;
346 int *fds;
347
348 fd = adb_connect("shell:");
349 if(fd < 0) {
350 fprintf(stderr,"error: %s\n", adb_error());
351 return 1;
352 }
353 fdi = 0; //dup(0);
354
355 fds = malloc(sizeof(int) * 2);
356 fds[0] = fd;
357 fds[1] = fdi;
358
359#ifdef HAVE_TERMIO_H
360 stdin_raw_init(fdi);
361#endif
362 adb_thread_create(&thr, stdin_read_thread, fds);
363 read_and_dump(fd);
364#ifdef HAVE_TERMIO_H
365 stdin_raw_restore(fdi);
366#endif
367 return 0;
368}
369
370
371static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
372{
373 if (serial) {
374 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
375 } else {
376 const char* prefix = "host";
377 if (ttype == kTransportUsb)
378 prefix = "host-usb";
379 else if (ttype == kTransportLocal)
380 prefix = "host-local";
381
382 snprintf(buffer, buflen, "%s:%s", prefix, command);
383 }
384}
385
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100386int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800387 unsigned progress)
388{
389 char buf[4096];
390 unsigned total;
391 int fd;
392 const unsigned char *ptr;
393
394 sprintf(buf,"%s:%d", service, sz);
395 fd = adb_connect(buf);
396 if(fd < 0) {
397 fprintf(stderr,"error: %s\n", adb_error());
398 return -1;
399 }
400
401 int opt = CHUNK_SIZE;
402 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
403
404 total = sz;
405 ptr = data;
406
407 if(progress) {
408 char *x = strrchr(service, ':');
409 if(x) service = x + 1;
410 }
411
412 while(sz > 0) {
413 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
414 if(writex(fd, ptr, xfer)) {
415 adb_status(fd);
416 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
417 return -1;
418 }
419 sz -= xfer;
420 ptr += xfer;
421 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100422 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800423 fflush(stdout);
424 }
425 }
426 if(progress) {
427 printf("\n");
428 }
429
430 if(readx(fd, buf, 4)){
431 fprintf(stderr,"* error reading response *\n");
432 adb_close(fd);
433 return -1;
434 }
435 if(memcmp(buf, "OKAY", 4)) {
436 buf[4] = 0;
437 fprintf(stderr,"* error response '%s' *\n", buf);
438 adb_close(fd);
439 return -1;
440 }
441
442 adb_close(fd);
443 return 0;
444}
445
446
447int adb_download(const char *service, const char *fn, unsigned progress)
448{
449 void *data;
450 unsigned sz;
451
452 data = load_file(fn, &sz);
453 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100454 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800455 return -1;
456 }
457
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100458 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800459 free(data);
460 return status;
461}
462
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800463static void status_window(transport_type ttype, const char* serial)
464{
465 char command[4096];
466 char *state = 0;
467 char *laststate = 0;
468
469 /* silence stderr */
470#ifdef _WIN32
471 /* XXX: TODO */
472#else
473 int fd;
474 fd = unix_open("/dev/null", O_WRONLY);
475 dup2(fd, 2);
476 adb_close(fd);
477#endif
478
479 format_host_command(command, sizeof command, "get-state", ttype, serial);
480
481 for(;;) {
482 adb_sleep_ms(250);
483
484 if(state) {
485 free(state);
486 state = 0;
487 }
488
489 state = adb_query(command);
490
491 if(state) {
492 if(laststate && !strcmp(state,laststate)){
493 continue;
494 } else {
495 if(laststate) free(laststate);
496 laststate = strdup(state);
497 }
498 }
499
500 printf("%c[2J%c[2H", 27, 27);
501 printf("Android Debug Bridge\n");
502 printf("State: %s\n", state ? state : "offline");
503 fflush(stdout);
504 }
505}
506
507/** duplicate string and quote all \ " ( ) chars + space character. */
508static char *
509dupAndQuote(const char *s)
510{
511 const char *ts;
512 size_t alloc_len;
513 char *ret;
514 char *dest;
515
516 ts = s;
517
518 alloc_len = 0;
519
520 for( ;*ts != '\0'; ts++) {
521 alloc_len++;
522 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
523 alloc_len++;
524 }
525 }
526
527 ret = (char *)malloc(alloc_len + 1);
528
529 ts = s;
530 dest = ret;
531
532 for ( ;*ts != '\0'; ts++) {
533 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
534 *dest++ = '\\';
535 }
536
537 *dest++ = *ts;
538 }
539
540 *dest++ = '\0';
541
542 return ret;
543}
544
545/**
546 * Run ppp in "notty" mode against a resource listed as the first parameter
547 * eg:
548 *
549 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
550 *
551 */
552int ppp(int argc, char **argv)
553{
554#ifdef HAVE_WIN32_PROC
555 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
556 return -1;
557#else
558 char *adb_service_name;
559 pid_t pid;
560 int fd;
561
562 if (argc < 2) {
563 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
564 argv[0]);
565
566 return 1;
567 }
568
569 adb_service_name = argv[1];
570
571 fd = adb_connect(adb_service_name);
572
573 if(fd < 0) {
574 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
575 adb_service_name, adb_error());
576 return 1;
577 }
578
579 pid = fork();
580
581 if (pid < 0) {
582 perror("from fork()");
583 return 1;
584 } else if (pid == 0) {
585 int err;
586 int i;
587 const char **ppp_args;
588
589 // copy args
590 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
591 ppp_args[0] = "pppd";
592 for (i = 2 ; i < argc ; i++) {
593 //argv[2] and beyond become ppp_args[1] and beyond
594 ppp_args[i - 1] = argv[i];
595 }
596 ppp_args[i-1] = NULL;
597
598 // child side
599
600 dup2(fd, STDIN_FILENO);
601 dup2(fd, STDOUT_FILENO);
602 adb_close(STDERR_FILENO);
603 adb_close(fd);
604
605 err = execvp("pppd", (char * const *)ppp_args);
606
607 if (err < 0) {
608 perror("execing pppd");
609 }
610 exit(-1);
611 } else {
612 // parent side
613
614 adb_close(fd);
615 return 0;
616 }
617#endif /* !HAVE_WIN32_PROC */
618}
619
620static int send_shellcommand(transport_type transport, char* serial, char* buf)
621{
622 int fd, ret;
623
624 for(;;) {
625 fd = adb_connect(buf);
626 if(fd >= 0)
627 break;
628 fprintf(stderr,"- waiting for device -\n");
629 adb_sleep_ms(1000);
630 do_cmd(transport, serial, "wait-for-device", 0);
631 }
632
633 read_and_dump(fd);
634 ret = adb_close(fd);
635 if (ret)
636 perror("close");
637
638 return ret;
639}
640
641static int logcat(transport_type transport, char* serial, int argc, char **argv)
642{
643 char buf[4096];
644
645 char *log_tags;
646 char *quoted_log_tags;
647
648 log_tags = getenv("ANDROID_LOG_TAGS");
649 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
650
651 snprintf(buf, sizeof(buf),
652 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
653 quoted_log_tags);
654
655 free(quoted_log_tags);
656
Christopher Tatedb0a8802011-11-30 13:00:33 -0800657 if (!strcmp(argv[0],"longcat")) {
658 strncat(buf, " -v long", sizeof(buf)-1);
659 }
660
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800661 argc -= 1;
662 argv += 1;
663 while(argc-- > 0) {
664 char *quoted;
665
666 quoted = dupAndQuote (*argv++);
667
668 strncat(buf, " ", sizeof(buf)-1);
669 strncat(buf, quoted, sizeof(buf)-1);
670 free(quoted);
671 }
672
673 send_shellcommand(transport, serial, buf);
674 return 0;
675}
676
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800677static int mkdirs(char *path)
678{
679 int ret;
680 char *x = path + 1;
681
682 for(;;) {
683 x = adb_dirstart(x);
684 if(x == 0) return 0;
685 *x = 0;
686 ret = adb_mkdir(path, 0775);
687 *x = OS_PATH_SEPARATOR;
688 if((ret < 0) && (errno != EEXIST)) {
689 return ret;
690 }
691 x++;
692 }
693 return 0;
694}
695
Christopher Tated2f54152011-04-21 12:53:28 -0700696static int backup(int argc, char** argv) {
697 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800698 char default_name[32];
699 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700700 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700701 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700702
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700703 /* find, extract, and use any -f argument */
704 for (i = 1; i < argc; i++) {
705 if (!strcmp("-f", argv[i])) {
706 if (i == argc-1) {
707 fprintf(stderr, "adb: -f passed with no filename\n");
708 return usage();
709 }
710 filename = argv[i+1];
711 for (j = i+2; j <= argc; ) {
712 argv[i++] = argv[j++];
713 }
714 argc -= 2;
715 argv[argc] = NULL;
716 }
Christopher Tated2f54152011-04-21 12:53:28 -0700717 }
718
Christopher Tatebb86bc52011-08-22 17:12:08 -0700719 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
720 if (argc < 2) return usage();
721
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800722 adb_unlink(filename);
723 mkdirs((char *)filename);
724 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700725 if (outFd < 0) {
726 fprintf(stderr, "adb: unable to open file %s\n", filename);
727 return -1;
728 }
729
730 snprintf(buf, sizeof(buf), "backup");
731 for (argc--, argv++; argc; argc--, argv++) {
732 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
733 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
734 }
735
736 D("backup. filename=%s buf=%s\n", filename, buf);
737 fd = adb_connect(buf);
738 if (fd < 0) {
739 fprintf(stderr, "adb: unable to connect for backup\n");
740 adb_close(outFd);
741 return -1;
742 }
743
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800744 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700745 copy_to_file(fd, outFd);
746
747 adb_close(fd);
748 adb_close(outFd);
749 return 0;
750}
751
Christopher Tate702967a2011-05-17 15:52:54 -0700752static int restore(int argc, char** argv) {
753 const char* filename;
754 int fd, tarFd;
755
756 if (argc != 2) return usage();
757
758 filename = argv[1];
759 tarFd = adb_open(filename, O_RDONLY);
760 if (tarFd < 0) {
761 fprintf(stderr, "adb: unable to open file %s\n", filename);
762 return -1;
763 }
764
765 fd = adb_connect("restore:");
766 if (fd < 0) {
767 fprintf(stderr, "adb: unable to connect for backup\n");
768 adb_close(tarFd);
769 return -1;
770 }
771
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800772 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700773 copy_to_file(tarFd, fd);
774
775 adb_close(fd);
776 adb_close(tarFd);
777 return 0;
778}
779
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800780#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
781static int top_works(const char *top)
782{
783 if (top != NULL && adb_is_absolute_host_path(top)) {
784 char path_buf[PATH_MAX];
785 snprintf(path_buf, sizeof(path_buf),
786 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
787 return access(path_buf, F_OK) == 0;
788 }
789 return 0;
790}
791
792static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
793{
794 strcpy(path_buf, indir);
795 while (1) {
796 if (top_works(path_buf)) {
797 return path_buf;
798 }
799 char *s = adb_dirstop(path_buf);
800 if (s != NULL) {
801 *s = '\0';
802 } else {
803 path_buf[0] = '\0';
804 return NULL;
805 }
806 }
807}
808
809static char *find_top(char path_buf[PATH_MAX])
810{
811 char *top = getenv("ANDROID_BUILD_TOP");
812 if (top != NULL && top[0] != '\0') {
813 if (!top_works(top)) {
814 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
815 return NULL;
816 }
817 } else {
818 top = getenv("TOP");
819 if (top != NULL && top[0] != '\0') {
820 if (!top_works(top)) {
821 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
822 return NULL;
823 }
824 } else {
825 top = NULL;
826 }
827 }
828
829 if (top != NULL) {
830 /* The environment pointed to a top directory that works.
831 */
832 strcpy(path_buf, top);
833 return path_buf;
834 }
835
836 /* The environment didn't help. Walk up the tree from the CWD
837 * to see if we can find the top.
838 */
839 char dir[PATH_MAX];
840 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
841 if (top == NULL) {
842 /* If the CWD isn't under a good-looking top, see if the
843 * executable is.
844 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100845 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 top = find_top_from(dir, path_buf);
847 }
848 return top;
849}
850
851/* <hint> may be:
852 * - A simple product name
853 * e.g., "sooner"
854TODO: debug? sooner-debug, sooner:debug?
855 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
856 * e.g., "out/target/product/sooner"
857 * - An absolute path to the PRODUCT_OUT dir
858 * e.g., "/src/device/out/target/product/sooner"
859 *
860 * Given <hint>, try to construct an absolute path to the
861 * ANDROID_PRODUCT_OUT dir.
862 */
863static const char *find_product_out_path(const char *hint)
864{
865 static char path_buf[PATH_MAX];
866
867 if (hint == NULL || hint[0] == '\0') {
868 return NULL;
869 }
870
871 /* If it's already absolute, don't bother doing any work.
872 */
873 if (adb_is_absolute_host_path(hint)) {
874 strcpy(path_buf, hint);
875 return path_buf;
876 }
877
878 /* If there are any slashes in it, assume it's a relative path;
879 * make it absolute.
880 */
881 if (adb_dirstart(hint) != NULL) {
882 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
883 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
884 return NULL;
885 }
886 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
887 fprintf(stderr, "adb: Couldn't assemble path\n");
888 return NULL;
889 }
890 strcat(path_buf, OS_PATH_SEPARATOR_STR);
891 strcat(path_buf, hint);
892 return path_buf;
893 }
894
895 /* It's a string without any slashes. Try to do something with it.
896 *
897 * Try to find the root of the build tree, and build a PRODUCT_OUT
898 * path from there.
899 */
900 char top_buf[PATH_MAX];
901 const char *top = find_top(top_buf);
902 if (top == NULL) {
903 fprintf(stderr, "adb: Couldn't find top of build tree\n");
904 return NULL;
905 }
906//TODO: if we have a way to indicate debug, look in out/debug/target/...
907 snprintf(path_buf, sizeof(path_buf),
908 "%s" OS_PATH_SEPARATOR_STR
909 "out" OS_PATH_SEPARATOR_STR
910 "target" OS_PATH_SEPARATOR_STR
911 "product" OS_PATH_SEPARATOR_STR
912 "%s", top_buf, hint);
913 if (access(path_buf, F_OK) < 0) {
914 fprintf(stderr, "adb: Couldn't find a product dir "
915 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
916 return NULL;
917 }
918 return path_buf;
919}
920
921int adb_commandline(int argc, char **argv)
922{
923 char buf[4096];
924 int no_daemon = 0;
925 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100926 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800927 int persist = 0;
928 int r;
929 int quote;
930 transport_type ttype = kTransportAny;
931 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100932 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800933
934 /* If defined, this should be an absolute path to
935 * the directory containing all of the various system images
936 * for a particular product. If not defined, and the adb
937 * command requires this information, then the user must
938 * specify the path using "-p".
939 */
940 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
941 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
942 gProductOutPath = NULL;
943 }
944 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
945
Nick Pellydb449262009-05-07 12:48:03 -0700946 serial = getenv("ANDROID_SERIAL");
947
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100948 /* Validate and assign the server port */
949 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
950 int server_port = DEFAULT_ADB_PORT;
951 if (server_port_str && strlen(server_port_str) > 0) {
952 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800953 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100954 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800955 "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 +0100956 server_port_str);
957 return usage();
958 }
959 }
960
961 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800962 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100963 if(!strcmp(argv[0],"server")) {
964 is_server = 1;
965 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800966 no_daemon = 1;
967 } else if (!strcmp(argv[0], "fork-server")) {
968 /* this is a special flag used only when the ADB client launches the ADB Server */
969 is_daemon = 1;
970 } else if(!strcmp(argv[0],"persist")) {
971 persist = 1;
972 } else if(!strncmp(argv[0], "-p", 2)) {
973 const char *product = NULL;
974 if (argv[0][2] == '\0') {
975 if (argc < 2) return usage();
976 product = argv[1];
977 argc--;
978 argv++;
979 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -0700980 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800981 }
982 gProductOutPath = find_product_out_path(product);
983 if (gProductOutPath == NULL) {
984 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
985 product);
986 return usage();
987 }
988 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
989 if (isdigit(argv[0][2])) {
990 serial = argv[0] + 2;
991 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100992 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800993 serial = argv[1];
994 argc--;
995 argv++;
996 }
997 } else if (!strcmp(argv[0],"-d")) {
998 ttype = kTransportUsb;
999 } else if (!strcmp(argv[0],"-e")) {
1000 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001001 } else if (!strcmp(argv[0],"-a")) {
1002 gListenAll = 1;
1003 } else if(!strncmp(argv[0], "-H", 2)) {
1004 const char *hostname = NULL;
1005 if (argv[0][2] == '\0') {
1006 if (argc < 2) return usage();
1007 hostname = argv[1];
1008 argc--;
1009 argv++;
1010 } else {
1011 hostname = argv[0] + 2;
1012 }
1013 adb_set_tcp_name(hostname);
1014
1015 } else if(!strncmp(argv[0], "-P", 2)) {
1016 if (argv[0][2] == '\0') {
1017 if (argc < 2) return usage();
1018 server_port_str = argv[1];
1019 argc--;
1020 argv++;
1021 } else {
1022 server_port_str = argv[0] + 2;
1023 }
1024 if (strlen(server_port_str) > 0) {
1025 server_port = (int) strtol(server_port_str, NULL, 0);
1026 if (server_port <= 0 || server_port > 65535) {
1027 fprintf(stderr,
1028 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1029 server_port_str);
1030 return usage();
1031 }
1032 } else {
1033 fprintf(stderr,
1034 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1035 return usage();
1036 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001037 } else {
1038 /* out of recognized modifiers and flags */
1039 break;
1040 }
1041 argc--;
1042 argv++;
1043 }
1044
1045 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001046 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001047
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001048 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001049 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001050 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001051 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001052 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001053 }
1054 if(r) {
1055 fprintf(stderr,"* could not start server *\n");
1056 }
1057 return r;
1058 }
1059
1060top:
1061 if(argc == 0) {
1062 return usage();
1063 }
1064
1065 /* adb_connect() commands */
1066
1067 if(!strcmp(argv[0], "devices")) {
1068 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001069 char *listopt;
1070 if (argc < 2)
1071 listopt = "";
1072 else if (argc == 2 && !strcmp(argv[1], "-l"))
1073 listopt = argv[1];
1074 else {
1075 fprintf(stderr, "Usage: adb devices [-l]\n");
1076 return 1;
1077 }
1078 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001079 tmp = adb_query(buf);
1080 if(tmp) {
1081 printf("List of devices attached \n");
1082 printf("%s\n", tmp);
1083 return 0;
1084 } else {
1085 return 1;
1086 }
1087 }
1088
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001089 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001090 char *tmp;
1091 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001092 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001093 return 1;
1094 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001095 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1096 tmp = adb_query(buf);
1097 if(tmp) {
1098 printf("%s\n", tmp);
1099 return 0;
1100 } else {
1101 return 1;
1102 }
1103 }
1104
1105 if(!strcmp(argv[0], "disconnect")) {
1106 char *tmp;
1107 if (argc > 2) {
1108 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1109 return 1;
1110 }
1111 if (argc == 2) {
1112 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1113 } else {
1114 snprintf(buf, sizeof buf, "host:disconnect:");
1115 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001116 tmp = adb_query(buf);
1117 if(tmp) {
1118 printf("%s\n", tmp);
1119 return 0;
1120 } else {
1121 return 1;
1122 }
1123 }
1124
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001125 if (!strcmp(argv[0], "emu")) {
1126 return adb_send_emulator_command(argc, argv);
1127 }
1128
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001129 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001130 int r;
1131 int fd;
1132
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001133 char h = (argv[0][0] == 'h');
1134
1135 if (h) {
1136 printf("\x1b[41;33m");
1137 fflush(stdout);
1138 }
1139
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001140 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001141 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001142 r = interactive_shell();
1143 if (h) {
1144 printf("\x1b[0m");
1145 fflush(stdout);
1146 }
1147 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148 }
1149
1150 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1151 argc -= 2;
1152 argv += 2;
1153 while(argc-- > 0) {
1154 strcat(buf, " ");
1155
1156 /* quote empty strings and strings with spaces */
1157 quote = (**argv == 0 || strchr(*argv, ' '));
1158 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001159 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001160 strcat(buf, *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 }
1164
1165 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001166 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001167 fd = adb_connect(buf);
1168 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001169 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001170 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001171 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001172 adb_close(fd);
1173 r = 0;
1174 } else {
1175 fprintf(stderr,"error: %s\n", adb_error());
1176 r = -1;
1177 }
1178
1179 if(persist) {
1180 fprintf(stderr,"\n- waiting for device -\n");
1181 adb_sleep_ms(1000);
1182 do_cmd(ttype, serial, "wait-for-device", 0);
1183 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001184 if (h) {
1185 printf("\x1b[0m");
1186 fflush(stdout);
1187 }
JP Abgrall408fa572011-03-16 15:57:42 -07001188 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 return r;
1190 }
1191 }
1192 }
1193
1194 if(!strcmp(argv[0], "kill-server")) {
1195 int fd;
1196 fd = _adb_connect("host:kill");
1197 if(fd == -1) {
1198 fprintf(stderr,"* server not running *\n");
1199 return 1;
1200 }
1201 return 0;
1202 }
1203
Doug Zongker447f0612012-01-09 14:54:53 -08001204 if(!strcmp(argv[0], "sideload")) {
1205 if(argc != 2) return usage();
1206 if(adb_download("sideload", argv[1], 1)) {
1207 return 1;
1208 } else {
1209 return 0;
1210 }
1211 }
1212
Mike Lockwoodff196702009-08-24 15:58:40 -07001213 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001214 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001215 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001216 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001217 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001218 if (!strcmp(argv[0], "reboot-bootloader"))
1219 snprintf(command, sizeof(command), "reboot:bootloader");
1220 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001221 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001222 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001223 snprintf(command, sizeof(command), "%s:", argv[0]);
1224 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001225 if(fd >= 0) {
1226 read_and_dump(fd);
1227 adb_close(fd);
1228 return 0;
1229 }
1230 fprintf(stderr,"error: %s\n", adb_error());
1231 return 1;
1232 }
1233
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001234 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001235 if (argc != 1) return usage();
1236 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001237 return 0;
1238 }
1239
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001240 /* adb_command() wrapper commands */
1241
1242 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1243 char* service = argv[0];
1244 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1245 if (ttype == kTransportUsb) {
1246 service = "wait-for-usb";
1247 } else if (ttype == kTransportLocal) {
1248 service = "wait-for-local";
1249 } else {
1250 service = "wait-for-any";
1251 }
1252 }
1253
1254 format_host_command(buf, sizeof buf, service, ttype, serial);
1255
1256 if (adb_command(buf)) {
1257 D("failure: %s *\n",adb_error());
1258 fprintf(stderr,"error: %s\n", adb_error());
1259 return 1;
1260 }
1261
1262 /* Allow a command to be run after wait-for-device,
1263 * e.g. 'adb wait-for-device shell'.
1264 */
1265 if(argc > 1) {
1266 argc--;
1267 argv++;
1268 goto top;
1269 }
1270 return 0;
1271 }
1272
1273 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001274 char host_prefix[64];
1275 char remove = 0;
1276 char remove_all = 0;
1277 char list = 0;
1278 char no_rebind = 0;
1279
1280 // Parse options here.
1281 while (argc > 1 && argv[1][0] == '-') {
1282 if (!strcmp(argv[1], "--list"))
1283 list = 1;
1284 else if (!strcmp(argv[1], "--remove"))
1285 remove = 1;
1286 else if (!strcmp(argv[1], "--remove-all"))
1287 remove_all = 1;
1288 else if (!strcmp(argv[1], "--no-rebind"))
1289 no_rebind = 1;
1290 else {
1291 return usage();
1292 }
1293 argc--;
1294 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001295 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001296
1297 // Ensure we can only use one option at a time.
1298 if (list + remove + remove_all + no_rebind > 1) {
1299 return usage();
1300 }
1301
1302 // Determine the <host-prefix> for this command.
1303 if (serial) {
1304 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1305 serial);
1306 } else if (ttype == kTransportUsb) {
1307 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1308 } else if (ttype == kTransportLocal) {
1309 snprintf(host_prefix, sizeof host_prefix, "host-local");
1310 } else {
1311 snprintf(host_prefix, sizeof host_prefix, "host");
1312 }
1313
1314 // Implement forward --list
1315 if (list) {
1316 if (argc != 1)
1317 return usage();
1318 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1319 char* forwards = adb_query(buf);
1320 if (forwards == NULL) {
1321 fprintf(stderr, "error: %s\n", adb_error());
1322 return 1;
1323 }
1324 printf("%s", forwards);
1325 free(forwards);
1326 return 0;
1327 }
1328
1329 // Implement forward --remove-all
1330 else if (remove_all) {
1331 if (argc != 1)
1332 return usage();
1333 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1334 }
1335
1336 // Implement forward --remove <local>
1337 else if (remove) {
1338 if (argc != 2)
1339 return usage();
1340 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1341 }
1342 // Or implement one of:
1343 // forward <local> <remote>
1344 // forward --no-rebind <local> <remote>
1345 else
1346 {
1347 if (argc != 3)
1348 return usage();
1349 const char* command = no_rebind ? "forward:norebind:" : "forward";
1350 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1351 }
1352
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001353 if(adb_command(buf)) {
1354 fprintf(stderr,"error: %s\n", adb_error());
1355 return 1;
1356 }
1357 return 0;
1358 }
1359
1360 /* do_sync_*() commands */
1361
1362 if(!strcmp(argv[0], "ls")) {
1363 if(argc != 2) return usage();
1364 return do_sync_ls(argv[1]);
1365 }
1366
1367 if(!strcmp(argv[0], "push")) {
1368 if(argc != 3) return usage();
1369 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1370 }
1371
1372 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001373 if (argc == 2) {
1374 return do_sync_pull(argv[1], ".");
1375 } else if (argc == 3) {
1376 return do_sync_pull(argv[1], argv[2]);
1377 } else {
1378 return usage();
1379 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001380 }
1381
1382 if(!strcmp(argv[0], "install")) {
1383 if (argc < 2) return usage();
1384 return install_app(ttype, serial, argc, argv);
1385 }
1386
1387 if(!strcmp(argv[0], "uninstall")) {
1388 if (argc < 2) return usage();
1389 return uninstall_app(ttype, serial, argc, argv);
1390 }
1391
1392 if(!strcmp(argv[0], "sync")) {
1393 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001394 int listonly = 0;
1395
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 int ret;
1397 if(argc < 2) {
1398 /* No local path was specified. */
1399 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001400 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1401 listonly = 1;
1402 if (argc == 3) {
1403 srcarg = argv[2];
1404 } else {
1405 srcarg = NULL;
1406 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001407 } else if(argc == 2) {
1408 /* A local path or "android"/"data" arg was specified. */
1409 srcarg = argv[1];
1410 } else {
1411 return usage();
1412 }
1413 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1414 if(ret != 0) return usage();
1415
1416 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001417 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001419 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001420
1421 free(android_srcpath);
1422 free(data_srcpath);
1423 return ret;
1424 }
1425
1426 /* passthrough commands */
1427
1428 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001429 !strcmp(argv[0],"get-serialno") ||
1430 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001431 {
1432 char *tmp;
1433
1434 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1435 tmp = adb_query(buf);
1436 if(tmp) {
1437 printf("%s\n", tmp);
1438 return 0;
1439 } else {
1440 return 1;
1441 }
1442 }
1443
1444 /* other commands */
1445
1446 if(!strcmp(argv[0],"status-window")) {
1447 status_window(ttype, serial);
1448 return 0;
1449 }
1450
Christopher Tatedb0a8802011-11-30 13:00:33 -08001451 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001452 return logcat(ttype, serial, argc, argv);
1453 }
1454
1455 if(!strcmp(argv[0],"ppp")) {
1456 return ppp(argc, argv);
1457 }
1458
1459 if (!strcmp(argv[0], "start-server")) {
1460 return adb_connect("host:start-server");
1461 }
1462
Christopher Tated2f54152011-04-21 12:53:28 -07001463 if (!strcmp(argv[0], "backup")) {
1464 return backup(argc, argv);
1465 }
1466
Christopher Tate702967a2011-05-17 15:52:54 -07001467 if (!strcmp(argv[0], "restore")) {
1468 return restore(argc, argv);
1469 }
1470
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001471 if (!strcmp(argv[0], "jdwp")) {
1472 int fd = adb_connect("jdwp");
1473 if (fd >= 0) {
1474 read_and_dump(fd);
1475 adb_close(fd);
1476 return 0;
1477 } else {
1478 fprintf(stderr, "error: %s\n", adb_error());
1479 return -1;
1480 }
1481 }
1482
1483 /* "adb /?" is a common idiom under Windows */
1484 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1485 help();
1486 return 0;
1487 }
1488
1489 if(!strcmp(argv[0], "version")) {
1490 version(stdout);
1491 return 0;
1492 }
1493
1494 usage();
1495 return 1;
1496}
1497
1498static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1499{
1500 char *argv[16];
1501 int argc;
1502 va_list ap;
1503
1504 va_start(ap, cmd);
1505 argc = 0;
1506
1507 if (serial) {
1508 argv[argc++] = "-s";
1509 argv[argc++] = serial;
1510 } else if (ttype == kTransportUsb) {
1511 argv[argc++] = "-d";
1512 } else if (ttype == kTransportLocal) {
1513 argv[argc++] = "-e";
1514 }
1515
1516 argv[argc++] = cmd;
1517 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1518 va_end(ap);
1519
1520#if 0
1521 int n;
1522 fprintf(stderr,"argc = %d\n",argc);
1523 for(n = 0; n < argc; n++) {
1524 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1525 }
1526#endif
1527
1528 return adb_commandline(argc, argv);
1529}
1530
1531int find_sync_dirs(const char *srcarg,
1532 char **android_srcdir_out, char **data_srcdir_out)
1533{
1534 char *android_srcdir, *data_srcdir;
1535
1536 if(srcarg == NULL) {
1537 android_srcdir = product_file("system");
1538 data_srcdir = product_file("data");
1539 } else {
1540 /* srcarg may be "data", "system" or NULL.
1541 * if srcarg is NULL, then both data and system are synced
1542 */
1543 if(strcmp(srcarg, "system") == 0) {
1544 android_srcdir = product_file("system");
1545 data_srcdir = NULL;
1546 } else if(strcmp(srcarg, "data") == 0) {
1547 android_srcdir = NULL;
1548 data_srcdir = product_file("data");
1549 } else {
1550 /* It's not "system" or "data".
1551 */
1552 return 1;
1553 }
1554 }
1555
1556 if(android_srcdir_out != NULL)
1557 *android_srcdir_out = android_srcdir;
1558 else
1559 free(android_srcdir);
1560
1561 if(data_srcdir_out != NULL)
1562 *data_srcdir_out = data_srcdir;
1563 else
1564 free(data_srcdir);
1565
1566 return 0;
1567}
1568
1569static int pm_command(transport_type transport, char* serial,
1570 int argc, char** argv)
1571{
1572 char buf[4096];
1573
1574 snprintf(buf, sizeof(buf), "shell:pm");
1575
1576 while(argc-- > 0) {
1577 char *quoted;
1578
1579 quoted = dupAndQuote(*argv++);
1580
1581 strncat(buf, " ", sizeof(buf)-1);
1582 strncat(buf, quoted, sizeof(buf)-1);
1583 free(quoted);
1584 }
1585
1586 send_shellcommand(transport, serial, buf);
1587 return 0;
1588}
1589
1590int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1591{
1592 /* if the user choose the -k option, we refuse to do it until devices are
1593 out with the option to uninstall the remaining data somehow (adb/ui) */
1594 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1595 {
1596 printf(
1597 "The -k option uninstalls the application while retaining the data/cache.\n"
1598 "At the moment, there is no way to remove the remaining data.\n"
1599 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1600 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1601 return -1;
1602 }
1603
1604 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1605 return pm_command(transport, serial, argc, argv);
1606}
1607
1608static int delete_file(transport_type transport, char* serial, char* filename)
1609{
1610 char buf[4096];
1611 char* quoted;
1612
1613 snprintf(buf, sizeof(buf), "shell:rm ");
1614 quoted = dupAndQuote(filename);
1615 strncat(buf, quoted, sizeof(buf)-1);
1616 free(quoted);
1617
1618 send_shellcommand(transport, serial, buf);
1619 return 0;
1620}
1621
Kenny Root597ea5b2011-08-05 11:19:45 -07001622static const char* get_basename(const char* filename)
1623{
1624 const char* basename = adb_dirstop(filename);
1625 if (basename) {
1626 basename++;
1627 return basename;
1628 } else {
1629 return filename;
1630 }
1631}
1632
1633static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001634{
1635 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001636
Kenny Root597ea5b2011-08-05 11:19:45 -07001637 if (filename == NULL) {
1638 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001639 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001640
Kenny Root597ea5b2011-08-05 11:19:45 -07001641 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001642 fprintf(stderr, "can't find '%s' to install\n", filename);
1643 return 1;
1644 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001645
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001646 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001647 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001648 return 1;
1649 }
1650
Kenny Root597ea5b2011-08-05 11:19:45 -07001651 return 0;
1652}
1653
1654int install_app(transport_type transport, char* serial, int argc, char** argv)
1655{
1656 static const char *const DATA_DEST = "/data/local/tmp/%s";
1657 static const char *const SD_DEST = "/sdcard/tmp/%s";
1658 const char* where = DATA_DEST;
1659 char apk_dest[PATH_MAX];
1660 char verification_dest[PATH_MAX];
1661 char* apk_file;
1662 char* verification_file = NULL;
1663 int file_arg = -1;
1664 int err;
1665 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001666 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001667
1668 for (i = 1; i < argc; i++) {
1669 if (*argv[i] != '-') {
1670 file_arg = i;
1671 break;
Kenny Roota031a912011-09-23 12:46:39 -07001672 } else if (!strcmp(argv[i], "-i")) {
1673 // Skip the installer package name.
1674 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001675 } else if (!strcmp(argv[i], "-s")) {
1676 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001677 } else if (!strcmp(argv[i], "--algo")) {
1678 verify_apk = 0;
1679 i++;
1680 } else if (!strcmp(argv[i], "--iv")) {
1681 verify_apk = 0;
1682 i++;
1683 } else if (!strcmp(argv[i], "--key")) {
1684 verify_apk = 0;
1685 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001686 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 }
1688
Kenny Root597ea5b2011-08-05 11:19:45 -07001689 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001690 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001691 return 1;
1692 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001693 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001694 return 1;
1695 }
1696
1697 apk_file = argv[file_arg];
1698
1699 if (file_arg != argc - 1) {
1700 verification_file = argv[file_arg + 1];
1701 }
1702
1703 if (check_file(apk_file) || check_file(verification_file)) {
1704 return 1;
1705 }
1706
1707 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1708 if (verification_file != NULL) {
1709 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1710
1711 if (!strcmp(apk_dest, verification_dest)) {
1712 fprintf(stderr, "APK and verification file can't have the same name\n");
1713 return 1;
1714 }
1715 }
1716
Anonymous Coward4474ac42012-04-24 10:43:41 -07001717 err = do_sync_push(apk_file, apk_dest, verify_apk);
Kenny Root597ea5b2011-08-05 11:19:45 -07001718 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001719 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001720 } else {
1721 argv[file_arg] = apk_dest; /* destination name, not source location */
1722 }
1723
1724 if (verification_file != NULL) {
1725 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1726 if (err) {
1727 goto cleanup_apk;
1728 } else {
1729 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1730 }
1731 }
1732
1733 pm_command(transport, serial, argc, argv);
1734
Kenny Root60733e92012-03-26 16:14:02 -07001735cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001736 if (verification_file != NULL) {
1737 delete_file(transport, serial, verification_dest);
1738 }
1739
Kenny Root597ea5b2011-08-05 11:19:45 -07001740 delete_file(transport, serial, apk_dest);
1741
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001742 return err;
1743}