blob: cee6c8c2a4d17d28761ae6174ae6f4b9d34047ad [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"
Mark Lindner76f2a932014-03-11 17:55:59 -0700110 " adb push [-p] <local> <remote>\n"
111 " - copy file/dir to device\n"
112 " ('-p' to display the transfer progress)\n"
Lajos Molnar4b35c012013-04-19 12:41:09 -0700113 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700114 " - copy file/dir from device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnar4b35c012013-04-19 12:41:09 -0700116 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800117 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600118 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119 " (see 'adb help all')\n"
120 " adb shell - run remote shell interactively\n"
121 " adb shell <command> - run remote shell command\n"
122 " adb emu <command> - run emulator console command\n"
123 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100124 " adb forward --list - list all forward socket connections.\n"
125 " the format is a list of lines with the following format:\n"
126 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800127 " adb forward <local> <remote> - forward socket connections\n"
128 " forward specs are one of: \n"
129 " tcp:<port>\n"
130 " localabstract:<unix domain socket name>\n"
131 " localreserved:<unix domain socket name>\n"
132 " localfilesystem:<unix domain socket name>\n"
133 " dev:<character device name>\n"
134 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100135 " adb forward --no-rebind <local> <remote>\n"
136 " - same as 'adb forward <local> <remote>' but fails\n"
137 " if <local> is already forwarded\n"
138 " adb forward --remove <local> - remove a specific forward socket connection\n"
139 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100140 " adb reverse --list - list all reverse socket connections from device\n"
141 " adb reverse <remote> <local> - reverse socket connections\n"
142 " reverse specs are one of:\n"
143 " tcp:<port>\n"
144 " localabstract:<unix domain socket name>\n"
145 " localreserved:<unix domain socket name>\n"
146 " localfilesystem:<unix domain socket name>\n"
147 " adb reverse --norebind <remote> <local>\n"
148 " - same as 'adb reverse <remote> <local>' but fails\n"
149 " if <remote> is already reversed.\n"
150 " adb reverse --remove <remote>\n"
151 " - remove a specific reversed socket connection\n"
152 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800153 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700154 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
155 " - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 " ('-l' means forward-lock the app)\n"
157 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500158 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800160 " adb uninstall [-k] <package> - remove this app package from the device\n"
161 " ('-k' means keep the data and cache directories)\n"
162 " adb bugreport - return all information from the device\n"
163 " that should be included in a bug report.\n"
164 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800165 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700166 " - write an archive of the device's data to <file>.\n"
167 " If no -f option is supplied then the data is written\n"
168 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700169 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700170 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800171 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
172 " (aka .obb) files associated with each application; the default\n"
173 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700174 " (-shared|-noshared enable/disable backup of the device's\n"
175 " shared storage / SD card contents; the default is noshared.)\n"
176 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700177 " (-system|-nosystem toggles whether -all automatically includes\n"
178 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700179 " (<packages...> is the list of applications to be backed up. If\n"
180 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700181 " list is optional. Applications explicitly given on the\n"
182 " command line will be included even if -nosystem would\n"
183 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700184 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700185 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700186 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800187 " adb help - show this help message\n"
188 " adb version - show version num\n"
189 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 "scripting:\n"
191 " adb wait-for-device - block until device is online\n"
192 " adb start-server - ensure that there is a server running\n"
193 " adb kill-server - kill the server if it is running\n"
194 " adb get-state - prints: offline | bootloader | device\n"
195 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700196 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 " adb status-window - continuously print device status for a specified device\n"
198 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400199 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800200 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700201 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800202 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700203 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 "\n"
205 "networking:\n"
206 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500207 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
209 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
210 "\n"
211 "adb sync notes: adb sync [ <directory> ]\n"
212 " <localdir> can be interpreted in several ways:\n"
213 "\n"
214 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
215 "\n"
216 " - If it is \"system\" or \"data\", only the corresponding partition\n"
217 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000218 "\n"
219 "environmental variables:\n"
220 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
221 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
222 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
223 " 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 -0800224 );
225}
226
227int usage()
228{
229 help();
230 return 1;
231}
232
233#ifdef HAVE_TERMIO_H
234static struct termios tio_save;
235
236static void stdin_raw_init(int fd)
237{
238 struct termios tio;
239
240 if(tcgetattr(fd, &tio)) return;
241 if(tcgetattr(fd, &tio_save)) return;
242
243 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
244
245 /* no timeout but request at least one character per read */
246 tio.c_cc[VTIME] = 0;
247 tio.c_cc[VMIN] = 1;
248
249 tcsetattr(fd, TCSANOW, &tio);
250 tcflush(fd, TCIFLUSH);
251}
252
253static void stdin_raw_restore(int fd)
254{
255 tcsetattr(fd, TCSANOW, &tio_save);
256 tcflush(fd, TCIFLUSH);
257}
258#endif
259
260static void read_and_dump(int fd)
261{
262 char buf[4096];
263 int len;
264
265 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700266 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700268 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269 if(len == 0) {
270 break;
271 }
272
273 if(len < 0) {
274 if(errno == EINTR) continue;
275 break;
276 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400277 fwrite(buf, 1, len, stdout);
278 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800279 }
280}
281
Christopher Tated2f54152011-04-21 12:53:28 -0700282static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700283 const size_t BUFSIZE = 32 * 1024;
284 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700285 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700286 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700287
288 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkeyeb979872014-05-26 18:30:43 -0700289#ifdef HAVE_TERMIO_H
290 if (inFd == STDIN_FILENO) {
291 stdin_raw_init(STDIN_FILENO);
292 }
293#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700294 for (;;) {
Jeff Sharkeyeb979872014-05-26 18:30:43 -0700295 if (inFd == STDIN_FILENO) {
296 len = unix_read(inFd, buf, BUFSIZE);
297 } else {
298 len = adb_read(inFd, buf, BUFSIZE);
299 }
Christopher Tated2f54152011-04-21 12:53:28 -0700300 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700301 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700302 break;
303 }
304 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700305 if (errno == EINTR) {
306 D("copy_to_file() : EINTR, retrying\n");
307 continue;
308 }
Christopher Tated2f54152011-04-21 12:53:28 -0700309 D("copy_to_file() : error %d\n", errno);
310 break;
311 }
Jeff Sharkeyeb979872014-05-26 18:30:43 -0700312 if (outFd == STDOUT_FILENO) {
313 fwrite(buf, 1, len, stdout);
314 fflush(stdout);
315 } else {
316 adb_write(outFd, buf, len);
317 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700318 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700319 }
Jeff Sharkeyeb979872014-05-26 18:30:43 -0700320#ifdef HAVE_TERMIO_H
321 if (inFd == STDIN_FILENO) {
322 stdin_raw_restore(STDIN_FILENO);
323 }
324#endif
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700325 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700326 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700327}
328
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800329static void *stdin_read_thread(void *x)
330{
331 int fd, fdi;
332 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800333 int r, n;
334 int state = 0;
335
336 int *fds = (int*) x;
337 fd = fds[0];
338 fdi = fds[1];
339 free(fds);
340
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800341 for(;;) {
342 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700343 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800344 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700345 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800346 if(r == 0) break;
347 if(r < 0) {
348 if(errno == EINTR) continue;
349 break;
350 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400351 for(n = 0; n < r; n++){
352 switch(buf[n]) {
353 case '\n':
354 state = 1;
355 break;
356 case '\r':
357 state = 1;
358 break;
359 case '~':
360 if(state == 1) state++;
361 break;
362 case '.':
363 if(state == 2) {
364 fprintf(stderr,"\n* disconnect *\n");
365#ifdef HAVE_TERMIO_H
366 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400368 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400370 default:
371 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 r = adb_write(fd, buf, r);
375 if(r <= 0) {
376 break;
377 }
378 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800379 return 0;
380}
381
382int interactive_shell(void)
383{
384 adb_thread_t thr;
385 int fdi, fd;
386 int *fds;
387
388 fd = adb_connect("shell:");
389 if(fd < 0) {
390 fprintf(stderr,"error: %s\n", adb_error());
391 return 1;
392 }
393 fdi = 0; //dup(0);
394
395 fds = malloc(sizeof(int) * 2);
396 fds[0] = fd;
397 fds[1] = fdi;
398
399#ifdef HAVE_TERMIO_H
400 stdin_raw_init(fdi);
401#endif
402 adb_thread_create(&thr, stdin_read_thread, fds);
403 read_and_dump(fd);
404#ifdef HAVE_TERMIO_H
405 stdin_raw_restore(fdi);
406#endif
407 return 0;
408}
409
410
411static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
412{
413 if (serial) {
414 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
415 } else {
416 const char* prefix = "host";
417 if (ttype == kTransportUsb)
418 prefix = "host-usb";
419 else if (ttype == kTransportLocal)
420 prefix = "host-local";
421
422 snprintf(buffer, buflen, "%s:%s", prefix, command);
423 }
424}
425
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100426int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800427 unsigned progress)
428{
429 char buf[4096];
430 unsigned total;
431 int fd;
432 const unsigned char *ptr;
433
434 sprintf(buf,"%s:%d", service, sz);
435 fd = adb_connect(buf);
436 if(fd < 0) {
437 fprintf(stderr,"error: %s\n", adb_error());
438 return -1;
439 }
440
441 int opt = CHUNK_SIZE;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700442 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800443
444 total = sz;
445 ptr = data;
446
447 if(progress) {
448 char *x = strrchr(service, ':');
449 if(x) service = x + 1;
450 }
451
452 while(sz > 0) {
453 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
454 if(writex(fd, ptr, xfer)) {
455 adb_status(fd);
456 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
457 return -1;
458 }
459 sz -= xfer;
460 ptr += xfer;
461 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100462 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800463 fflush(stdout);
464 }
465 }
466 if(progress) {
467 printf("\n");
468 }
469
470 if(readx(fd, buf, 4)){
471 fprintf(stderr,"* error reading response *\n");
472 adb_close(fd);
473 return -1;
474 }
475 if(memcmp(buf, "OKAY", 4)) {
476 buf[4] = 0;
477 fprintf(stderr,"* error response '%s' *\n", buf);
478 adb_close(fd);
479 return -1;
480 }
481
482 adb_close(fd);
483 return 0;
484}
485
486
487int adb_download(const char *service, const char *fn, unsigned progress)
488{
489 void *data;
490 unsigned sz;
491
492 data = load_file(fn, &sz);
493 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100494 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800495 return -1;
496 }
497
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100498 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800499 free(data);
500 return status;
501}
502
Doug Zongker8e49ae42014-06-26 15:35:36 -0700503#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
504
505/*
506 * The sideload-host protocol serves the data in a file (given on the
507 * command line) to the client, using a simple protocol:
508 *
509 * - The connect message includes the total number of bytes in the
510 * file and a block size chosen by us.
511 *
512 * - The other side sends the desired block number as eight decimal
513 * digits (eg "00000023" for block 23). Blocks are numbered from
514 * zero.
515 *
516 * - We send back the data of the requested block. The last block is
517 * likely to be partial; when the last block is requested we only
518 * send the part of the block that exists, it's not padded up to the
519 * block size.
520 *
521 * - When the other side sends "DONEDONE" instead of a block number,
522 * we hang up.
523 */
524int adb_sideload_host(const char* fn) {
525 uint8_t* data;
526 unsigned sz;
527 size_t xfer = 0;
528 int status;
529
530 printf("loading: '%s'", fn);
531 fflush(stdout);
532 data = load_file(fn, &sz);
533 if (data == 0) {
534 printf("\n");
535 fprintf(stderr, "* cannot read '%s' *\n", fn);
536 return -1;
537 }
538
539 char buf[100];
540 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
541 int fd = adb_connect(buf);
542 if (fd < 0) {
543 // Try falling back to the older sideload method. Maybe this
544 // is an older device that doesn't support sideload-host.
545 printf("\n");
546 status = adb_download_buffer("sideload", fn, data, sz, 1);
547 goto done;
548 }
549
550 int opt = SIDELOAD_HOST_BLOCK_SIZE;
551 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
552
553 int last_percent = -1;
554 while (true) {
555 if (readx(fd, buf, 8)) {
556 fprintf(stderr, "* failed to read command: %s\n", adb_error());
557 status = -1;
558 goto done;
559 }
560
561 if (strncmp("DONEDONE", buf, 8) == 0) {
562 status = 0;
563 break;
564 }
565
566 buf[8] = '\0';
567 int block = strtol(buf, NULL, 10);
568
569 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
570 if (offset >= sz) {
571 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
572 status = -1;
573 goto done;
574 }
575 uint8_t* start = data + offset;
576 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
577 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
578 if (offset_end > sz) {
579 to_write = sz - offset;
580 }
581
582 if(writex(fd, start, to_write)) {
583 adb_status(fd);
584 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
585 status = -1;
586 goto done;
587 }
588 xfer += to_write;
589
590 // For normal OTA packages, we expect to transfer every byte
591 // twice, plus a bit of overhead (one read during
592 // verification, one read of each byte for installation, plus
593 // extra access to things like the zip central directory).
594 // This estimate of the completion becomes 100% when we've
595 // transferred ~2.13 (=100/47) times the package size.
596 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
597 if (percent != last_percent) {
598 printf("\rserving: '%s' (~%d%%) ", fn, percent);
599 fflush(stdout);
600 last_percent = percent;
601 }
602 }
603
604 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), strlen(fn)+10, "");
605
606 done:
607 if (fd >= 0) adb_close(fd);
608 free(data);
609 return status;
610}
611
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800612static void status_window(transport_type ttype, const char* serial)
613{
614 char command[4096];
615 char *state = 0;
616 char *laststate = 0;
617
618 /* silence stderr */
619#ifdef _WIN32
620 /* XXX: TODO */
621#else
622 int fd;
623 fd = unix_open("/dev/null", O_WRONLY);
624 dup2(fd, 2);
625 adb_close(fd);
626#endif
627
628 format_host_command(command, sizeof command, "get-state", ttype, serial);
629
630 for(;;) {
631 adb_sleep_ms(250);
632
633 if(state) {
634 free(state);
635 state = 0;
636 }
637
638 state = adb_query(command);
639
640 if(state) {
641 if(laststate && !strcmp(state,laststate)){
642 continue;
643 } else {
644 if(laststate) free(laststate);
645 laststate = strdup(state);
646 }
647 }
648
649 printf("%c[2J%c[2H", 27, 27);
650 printf("Android Debug Bridge\n");
651 printf("State: %s\n", state ? state : "offline");
652 fflush(stdout);
653 }
654}
655
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700656/** Duplicate and escape given argument. */
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700657static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800658{
659 const char *ts;
660 size_t alloc_len;
661 char *ret;
662 char *dest;
663
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700664 alloc_len = 0;
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700665 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800666 alloc_len++;
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700667 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800668 alloc_len++;
669 }
670 }
671
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700672 if (alloc_len == 0) {
673 // Preserve empty arguments
674 ret = (char *) malloc(3);
675 ret[0] = '\"';
676 ret[1] = '\"';
677 ret[2] = '\0';
678 return ret;
679 }
680
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700681 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 dest = ret;
683
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700684 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700685 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800686 *dest++ = '\\';
687 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800688 *dest++ = *ts;
689 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800690 *dest++ = '\0';
691
692 return ret;
693}
694
695/**
696 * Run ppp in "notty" mode against a resource listed as the first parameter
697 * eg:
698 *
699 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
700 *
701 */
702int ppp(int argc, char **argv)
703{
704#ifdef HAVE_WIN32_PROC
705 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
706 return -1;
707#else
708 char *adb_service_name;
709 pid_t pid;
710 int fd;
711
712 if (argc < 2) {
713 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
714 argv[0]);
715
716 return 1;
717 }
718
719 adb_service_name = argv[1];
720
721 fd = adb_connect(adb_service_name);
722
723 if(fd < 0) {
724 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
725 adb_service_name, adb_error());
726 return 1;
727 }
728
729 pid = fork();
730
731 if (pid < 0) {
732 perror("from fork()");
733 return 1;
734 } else if (pid == 0) {
735 int err;
736 int i;
737 const char **ppp_args;
738
739 // copy args
740 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
741 ppp_args[0] = "pppd";
742 for (i = 2 ; i < argc ; i++) {
743 //argv[2] and beyond become ppp_args[1] and beyond
744 ppp_args[i - 1] = argv[i];
745 }
746 ppp_args[i-1] = NULL;
747
748 // child side
749
750 dup2(fd, STDIN_FILENO);
751 dup2(fd, STDOUT_FILENO);
752 adb_close(STDERR_FILENO);
753 adb_close(fd);
754
755 err = execvp("pppd", (char * const *)ppp_args);
756
757 if (err < 0) {
758 perror("execing pppd");
759 }
760 exit(-1);
761 } else {
762 // parent side
763
764 adb_close(fd);
765 return 0;
766 }
767#endif /* !HAVE_WIN32_PROC */
768}
769
770static int send_shellcommand(transport_type transport, char* serial, char* buf)
771{
772 int fd, ret;
773
774 for(;;) {
775 fd = adb_connect(buf);
776 if(fd >= 0)
777 break;
778 fprintf(stderr,"- waiting for device -\n");
779 adb_sleep_ms(1000);
780 do_cmd(transport, serial, "wait-for-device", 0);
781 }
782
783 read_and_dump(fd);
784 ret = adb_close(fd);
785 if (ret)
786 perror("close");
787
788 return ret;
789}
790
791static int logcat(transport_type transport, char* serial, int argc, char **argv)
792{
793 char buf[4096];
794
795 char *log_tags;
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700796 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800797
798 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700799 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800800 snprintf(buf, sizeof(buf),
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700801 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700802 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800803
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700804 if (!strcmp(argv[0], "longcat")) {
805 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800806 }
807
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800808 argc -= 1;
809 argv += 1;
810 while(argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700811 quoted = escape_arg(*argv++);
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700812 strncat(buf, " ", sizeof(buf) - 1);
813 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800814 free(quoted);
815 }
816
817 send_shellcommand(transport, serial, buf);
818 return 0;
819}
820
Mark Salyzyn60299df2014-04-30 09:10:31 -0700821static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800822{
823 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700824 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800825
826 for(;;) {
827 x = adb_dirstart(x);
828 if(x == 0) return 0;
829 *x = 0;
830 ret = adb_mkdir(path, 0775);
831 *x = OS_PATH_SEPARATOR;
832 if((ret < 0) && (errno != EEXIST)) {
833 return ret;
834 }
835 x++;
836 }
837 return 0;
838}
839
Christopher Tated2f54152011-04-21 12:53:28 -0700840static int backup(int argc, char** argv) {
841 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800842 char default_name[32];
843 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700844 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700845 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700846
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700847 /* find, extract, and use any -f argument */
848 for (i = 1; i < argc; i++) {
849 if (!strcmp("-f", argv[i])) {
850 if (i == argc-1) {
851 fprintf(stderr, "adb: -f passed with no filename\n");
852 return usage();
853 }
854 filename = argv[i+1];
855 for (j = i+2; j <= argc; ) {
856 argv[i++] = argv[j++];
857 }
858 argc -= 2;
859 argv[argc] = NULL;
860 }
Christopher Tated2f54152011-04-21 12:53:28 -0700861 }
862
Christopher Tatebb86bc52011-08-22 17:12:08 -0700863 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
864 if (argc < 2) return usage();
865
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800866 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700867 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800868 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700869 if (outFd < 0) {
870 fprintf(stderr, "adb: unable to open file %s\n", filename);
871 return -1;
872 }
873
874 snprintf(buf, sizeof(buf), "backup");
875 for (argc--, argv++; argc; argc--, argv++) {
876 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
877 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
878 }
879
880 D("backup. filename=%s buf=%s\n", filename, buf);
881 fd = adb_connect(buf);
882 if (fd < 0) {
883 fprintf(stderr, "adb: unable to connect for backup\n");
884 adb_close(outFd);
885 return -1;
886 }
887
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800888 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700889 copy_to_file(fd, outFd);
890
891 adb_close(fd);
892 adb_close(outFd);
893 return 0;
894}
895
Christopher Tate702967a2011-05-17 15:52:54 -0700896static int restore(int argc, char** argv) {
897 const char* filename;
898 int fd, tarFd;
899
900 if (argc != 2) return usage();
901
902 filename = argv[1];
903 tarFd = adb_open(filename, O_RDONLY);
904 if (tarFd < 0) {
905 fprintf(stderr, "adb: unable to open file %s\n", filename);
906 return -1;
907 }
908
909 fd = adb_connect("restore:");
910 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700911 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700912 adb_close(tarFd);
913 return -1;
914 }
915
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800916 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700917 copy_to_file(tarFd, fd);
918
919 adb_close(fd);
920 adb_close(tarFd);
921 return 0;
922}
923
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800924#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
925static int top_works(const char *top)
926{
927 if (top != NULL && adb_is_absolute_host_path(top)) {
928 char path_buf[PATH_MAX];
929 snprintf(path_buf, sizeof(path_buf),
930 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
931 return access(path_buf, F_OK) == 0;
932 }
933 return 0;
934}
935
936static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
937{
938 strcpy(path_buf, indir);
939 while (1) {
940 if (top_works(path_buf)) {
941 return path_buf;
942 }
943 char *s = adb_dirstop(path_buf);
944 if (s != NULL) {
945 *s = '\0';
946 } else {
947 path_buf[0] = '\0';
948 return NULL;
949 }
950 }
951}
952
953static char *find_top(char path_buf[PATH_MAX])
954{
955 char *top = getenv("ANDROID_BUILD_TOP");
956 if (top != NULL && top[0] != '\0') {
957 if (!top_works(top)) {
958 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
959 return NULL;
960 }
961 } else {
962 top = getenv("TOP");
963 if (top != NULL && top[0] != '\0') {
964 if (!top_works(top)) {
965 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
966 return NULL;
967 }
968 } else {
969 top = NULL;
970 }
971 }
972
973 if (top != NULL) {
974 /* The environment pointed to a top directory that works.
975 */
976 strcpy(path_buf, top);
977 return path_buf;
978 }
979
980 /* The environment didn't help. Walk up the tree from the CWD
981 * to see if we can find the top.
982 */
983 char dir[PATH_MAX];
984 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
985 if (top == NULL) {
986 /* If the CWD isn't under a good-looking top, see if the
987 * executable is.
988 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100989 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800990 top = find_top_from(dir, path_buf);
991 }
992 return top;
993}
994
995/* <hint> may be:
996 * - A simple product name
997 * e.g., "sooner"
998TODO: debug? sooner-debug, sooner:debug?
999 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1000 * e.g., "out/target/product/sooner"
1001 * - An absolute path to the PRODUCT_OUT dir
1002 * e.g., "/src/device/out/target/product/sooner"
1003 *
1004 * Given <hint>, try to construct an absolute path to the
1005 * ANDROID_PRODUCT_OUT dir.
1006 */
1007static const char *find_product_out_path(const char *hint)
1008{
1009 static char path_buf[PATH_MAX];
1010
1011 if (hint == NULL || hint[0] == '\0') {
1012 return NULL;
1013 }
1014
1015 /* If it's already absolute, don't bother doing any work.
1016 */
1017 if (adb_is_absolute_host_path(hint)) {
1018 strcpy(path_buf, hint);
1019 return path_buf;
1020 }
1021
1022 /* If there are any slashes in it, assume it's a relative path;
1023 * make it absolute.
1024 */
1025 if (adb_dirstart(hint) != NULL) {
1026 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1027 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1028 return NULL;
1029 }
1030 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1031 fprintf(stderr, "adb: Couldn't assemble path\n");
1032 return NULL;
1033 }
1034 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1035 strcat(path_buf, hint);
1036 return path_buf;
1037 }
1038
1039 /* It's a string without any slashes. Try to do something with it.
1040 *
1041 * Try to find the root of the build tree, and build a PRODUCT_OUT
1042 * path from there.
1043 */
1044 char top_buf[PATH_MAX];
1045 const char *top = find_top(top_buf);
1046 if (top == NULL) {
1047 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1048 return NULL;
1049 }
1050//TODO: if we have a way to indicate debug, look in out/debug/target/...
1051 snprintf(path_buf, sizeof(path_buf),
1052 "%s" OS_PATH_SEPARATOR_STR
1053 "out" OS_PATH_SEPARATOR_STR
1054 "target" OS_PATH_SEPARATOR_STR
1055 "product" OS_PATH_SEPARATOR_STR
1056 "%s", top_buf, hint);
1057 if (access(path_buf, F_OK) < 0) {
1058 fprintf(stderr, "adb: Couldn't find a product dir "
1059 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1060 return NULL;
1061 }
1062 return path_buf;
1063}
1064
Lajos Molnar4b35c012013-04-19 12:41:09 -07001065static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1066 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001067 *show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001068 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001069
Lajos Molnar4b35c012013-04-19 12:41:09 -07001070 while (narg > 0) {
1071 if (!strcmp(*arg, "-p")) {
1072 *show_progress = 1;
1073 } else if (!strcmp(*arg, "-a")) {
1074 *copy_attrs = 1;
1075 } else {
1076 break;
1077 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001078 ++arg;
1079 --narg;
1080 }
1081
1082 if (narg > 0) {
1083 *path1 = *arg;
1084 ++arg;
1085 --narg;
1086 }
1087
1088 if (narg > 0) {
1089 *path2 = *arg;
1090 }
1091}
1092
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001093int adb_commandline(int argc, char **argv)
1094{
1095 char buf[4096];
1096 int no_daemon = 0;
1097 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001098 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001099 int persist = 0;
1100 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001101 transport_type ttype = kTransportAny;
1102 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001103 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104
1105 /* If defined, this should be an absolute path to
1106 * the directory containing all of the various system images
1107 * for a particular product. If not defined, and the adb
1108 * command requires this information, then the user must
1109 * specify the path using "-p".
1110 */
1111 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1112 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1113 gProductOutPath = NULL;
1114 }
1115 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1116
Nick Pellydb449262009-05-07 12:48:03 -07001117 serial = getenv("ANDROID_SERIAL");
1118
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001119 /* Validate and assign the server port */
1120 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1121 int server_port = DEFAULT_ADB_PORT;
1122 if (server_port_str && strlen(server_port_str) > 0) {
1123 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001124 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001125 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001126 "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 +01001127 server_port_str);
1128 return usage();
1129 }
1130 }
1131
1132 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001134 if(!strcmp(argv[0],"server")) {
1135 is_server = 1;
1136 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137 no_daemon = 1;
1138 } else if (!strcmp(argv[0], "fork-server")) {
1139 /* this is a special flag used only when the ADB client launches the ADB Server */
1140 is_daemon = 1;
1141 } else if(!strcmp(argv[0],"persist")) {
1142 persist = 1;
1143 } else if(!strncmp(argv[0], "-p", 2)) {
1144 const char *product = NULL;
1145 if (argv[0][2] == '\0') {
1146 if (argc < 2) return usage();
1147 product = argv[1];
1148 argc--;
1149 argv++;
1150 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001151 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001152 }
1153 gProductOutPath = find_product_out_path(product);
1154 if (gProductOutPath == NULL) {
1155 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1156 product);
1157 return usage();
1158 }
1159 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1160 if (isdigit(argv[0][2])) {
1161 serial = argv[0] + 2;
1162 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001163 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001164 serial = argv[1];
1165 argc--;
1166 argv++;
1167 }
1168 } else if (!strcmp(argv[0],"-d")) {
1169 ttype = kTransportUsb;
1170 } else if (!strcmp(argv[0],"-e")) {
1171 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001172 } else if (!strcmp(argv[0],"-a")) {
1173 gListenAll = 1;
1174 } else if(!strncmp(argv[0], "-H", 2)) {
1175 const char *hostname = NULL;
1176 if (argv[0][2] == '\0') {
1177 if (argc < 2) return usage();
1178 hostname = argv[1];
1179 argc--;
1180 argv++;
1181 } else {
1182 hostname = argv[0] + 2;
1183 }
1184 adb_set_tcp_name(hostname);
1185
1186 } else if(!strncmp(argv[0], "-P", 2)) {
1187 if (argv[0][2] == '\0') {
1188 if (argc < 2) return usage();
1189 server_port_str = argv[1];
1190 argc--;
1191 argv++;
1192 } else {
1193 server_port_str = argv[0] + 2;
1194 }
1195 if (strlen(server_port_str) > 0) {
1196 server_port = (int) strtol(server_port_str, NULL, 0);
1197 if (server_port <= 0 || server_port > 65535) {
1198 fprintf(stderr,
1199 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1200 server_port_str);
1201 return usage();
1202 }
1203 } else {
1204 fprintf(stderr,
1205 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1206 return usage();
1207 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001208 } else {
1209 /* out of recognized modifiers and flags */
1210 break;
1211 }
1212 argc--;
1213 argv++;
1214 }
1215
1216 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001217 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001218
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001219 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001221 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001222 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001223 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001224 }
1225 if(r) {
1226 fprintf(stderr,"* could not start server *\n");
1227 }
1228 return r;
1229 }
1230
1231top:
1232 if(argc == 0) {
1233 return usage();
1234 }
1235
1236 /* adb_connect() commands */
1237
1238 if(!strcmp(argv[0], "devices")) {
1239 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001240 char *listopt;
1241 if (argc < 2)
1242 listopt = "";
1243 else if (argc == 2 && !strcmp(argv[1], "-l"))
1244 listopt = argv[1];
1245 else {
1246 fprintf(stderr, "Usage: adb devices [-l]\n");
1247 return 1;
1248 }
1249 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001250 tmp = adb_query(buf);
1251 if(tmp) {
1252 printf("List of devices attached \n");
1253 printf("%s\n", tmp);
1254 return 0;
1255 } else {
1256 return 1;
1257 }
1258 }
1259
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001260 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001261 char *tmp;
1262 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001263 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001264 return 1;
1265 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001266 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1267 tmp = adb_query(buf);
1268 if(tmp) {
1269 printf("%s\n", tmp);
1270 return 0;
1271 } else {
1272 return 1;
1273 }
1274 }
1275
1276 if(!strcmp(argv[0], "disconnect")) {
1277 char *tmp;
1278 if (argc > 2) {
1279 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1280 return 1;
1281 }
1282 if (argc == 2) {
1283 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1284 } else {
1285 snprintf(buf, sizeof buf, "host:disconnect:");
1286 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001287 tmp = adb_query(buf);
1288 if(tmp) {
1289 printf("%s\n", tmp);
1290 return 0;
1291 } else {
1292 return 1;
1293 }
1294 }
1295
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001296 if (!strcmp(argv[0], "emu")) {
1297 return adb_send_emulator_command(argc, argv);
1298 }
1299
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001300 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001301 int r;
1302 int fd;
1303
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001304 char h = (argv[0][0] == 'h');
1305
1306 if (h) {
1307 printf("\x1b[41;33m");
1308 fflush(stdout);
1309 }
1310
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001311 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001312 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001313 r = interactive_shell();
1314 if (h) {
1315 printf("\x1b[0m");
1316 fflush(stdout);
1317 }
1318 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001319 }
1320
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001321 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001322 argc -= 2;
1323 argv += 2;
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001324 while (argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001325 char *quoted = escape_arg(*argv++);
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001326 strncat(buf, " ", sizeof(buf) - 1);
1327 strncat(buf, quoted, sizeof(buf) - 1);
1328 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001329 }
1330
1331 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001332 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001333 fd = adb_connect(buf);
1334 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001335 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001336 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001337 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001338 adb_close(fd);
1339 r = 0;
1340 } else {
1341 fprintf(stderr,"error: %s\n", adb_error());
1342 r = -1;
1343 }
1344
1345 if(persist) {
1346 fprintf(stderr,"\n- waiting for device -\n");
1347 adb_sleep_ms(1000);
1348 do_cmd(ttype, serial, "wait-for-device", 0);
1349 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001350 if (h) {
1351 printf("\x1b[0m");
1352 fflush(stdout);
1353 }
JP Abgrall408fa572011-03-16 15:57:42 -07001354 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001355 return r;
1356 }
1357 }
1358 }
1359
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001360 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1361 int exec_in = !strcmp(argv[0], "exec-in");
1362 int fd;
1363
1364 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1365 argc -= 2;
1366 argv += 2;
1367 while (argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001368 char *quoted = escape_arg(*argv++);
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001369 strncat(buf, " ", sizeof(buf) - 1);
1370 strncat(buf, quoted, sizeof(buf) - 1);
1371 free(quoted);
1372 }
1373
1374 fd = adb_connect(buf);
1375 if (fd < 0) {
1376 fprintf(stderr, "error: %s\n", adb_error());
1377 return -1;
1378 }
1379
1380 if (exec_in) {
1381 copy_to_file(STDIN_FILENO, fd);
1382 } else {
1383 copy_to_file(fd, STDOUT_FILENO);
1384 }
1385
1386 adb_close(fd);
1387 return 0;
1388 }
1389
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 if(!strcmp(argv[0], "kill-server")) {
1391 int fd;
1392 fd = _adb_connect("host:kill");
1393 if(fd == -1) {
1394 fprintf(stderr,"* server not running *\n");
1395 return 1;
1396 }
1397 return 0;
1398 }
1399
Doug Zongker447f0612012-01-09 14:54:53 -08001400 if(!strcmp(argv[0], "sideload")) {
1401 if(argc != 2) return usage();
Doug Zongker8e49ae42014-06-26 15:35:36 -07001402 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001403 return 1;
1404 } else {
1405 return 0;
1406 }
1407 }
1408
Mike Lockwoodff196702009-08-24 15:58:40 -07001409 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001410 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001411 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001412 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001413 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001414 if (!strcmp(argv[0], "reboot-bootloader"))
1415 snprintf(command, sizeof(command), "reboot:bootloader");
1416 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001417 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001418 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001419 snprintf(command, sizeof(command), "%s:", argv[0]);
1420 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001421 if(fd >= 0) {
1422 read_and_dump(fd);
1423 adb_close(fd);
1424 return 0;
1425 }
1426 fprintf(stderr,"error: %s\n", adb_error());
1427 return 1;
1428 }
1429
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001430 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001431 if (argc != 1) return usage();
1432 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001433 return 0;
1434 }
1435
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001436 /* adb_command() wrapper commands */
1437
1438 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1439 char* service = argv[0];
1440 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1441 if (ttype == kTransportUsb) {
1442 service = "wait-for-usb";
1443 } else if (ttype == kTransportLocal) {
1444 service = "wait-for-local";
1445 } else {
1446 service = "wait-for-any";
1447 }
1448 }
1449
1450 format_host_command(buf, sizeof buf, service, ttype, serial);
1451
1452 if (adb_command(buf)) {
1453 D("failure: %s *\n",adb_error());
1454 fprintf(stderr,"error: %s\n", adb_error());
1455 return 1;
1456 }
1457
1458 /* Allow a command to be run after wait-for-device,
1459 * e.g. 'adb wait-for-device shell'.
1460 */
1461 if(argc > 1) {
1462 argc--;
1463 argv++;
1464 goto top;
1465 }
1466 return 0;
1467 }
1468
David 'Digit' Turner25258692013-03-21 21:07:42 +01001469 if(!strcmp(argv[0], "forward") ||
1470 !strcmp(argv[0], "reverse"))
1471 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001472 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001473 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001474 char remove = 0;
1475 char remove_all = 0;
1476 char list = 0;
1477 char no_rebind = 0;
1478
1479 // Parse options here.
1480 while (argc > 1 && argv[1][0] == '-') {
1481 if (!strcmp(argv[1], "--list"))
1482 list = 1;
1483 else if (!strcmp(argv[1], "--remove"))
1484 remove = 1;
1485 else if (!strcmp(argv[1], "--remove-all"))
1486 remove_all = 1;
1487 else if (!strcmp(argv[1], "--no-rebind"))
1488 no_rebind = 1;
1489 else {
1490 return usage();
1491 }
1492 argc--;
1493 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001494 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001495
1496 // Ensure we can only use one option at a time.
1497 if (list + remove + remove_all + no_rebind > 1) {
1498 return usage();
1499 }
1500
1501 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001502 if (reverse) {
1503 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001504 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001505 if (serial) {
1506 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1507 serial);
1508 } else if (ttype == kTransportUsb) {
1509 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1510 } else if (ttype == kTransportLocal) {
1511 snprintf(host_prefix, sizeof host_prefix, "host-local");
1512 } else {
1513 snprintf(host_prefix, sizeof host_prefix, "host");
1514 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001515 }
1516
1517 // Implement forward --list
1518 if (list) {
1519 if (argc != 1)
1520 return usage();
1521 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1522 char* forwards = adb_query(buf);
1523 if (forwards == NULL) {
1524 fprintf(stderr, "error: %s\n", adb_error());
1525 return 1;
1526 }
1527 printf("%s", forwards);
1528 free(forwards);
1529 return 0;
1530 }
1531
1532 // Implement forward --remove-all
1533 else if (remove_all) {
1534 if (argc != 1)
1535 return usage();
1536 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1537 }
1538
1539 // Implement forward --remove <local>
1540 else if (remove) {
1541 if (argc != 2)
1542 return usage();
1543 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1544 }
1545 // Or implement one of:
1546 // forward <local> <remote>
1547 // forward --no-rebind <local> <remote>
1548 else
1549 {
1550 if (argc != 3)
1551 return usage();
1552 const char* command = no_rebind ? "forward:norebind:" : "forward";
1553 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1554 }
1555
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001556 if(adb_command(buf)) {
1557 fprintf(stderr,"error: %s\n", adb_error());
1558 return 1;
1559 }
1560 return 0;
1561 }
1562
1563 /* do_sync_*() commands */
1564
1565 if(!strcmp(argv[0], "ls")) {
1566 if(argc != 2) return usage();
1567 return do_sync_ls(argv[1]);
1568 }
1569
1570 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001571 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001572 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001573 const char* lpath = NULL, *rpath = NULL;
1574
Lajos Molnar4b35c012013-04-19 12:41:09 -07001575 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001576
1577 if ((lpath != NULL) && (rpath != NULL)) {
1578 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1579 }
1580
1581 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001582 }
1583
1584 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001585 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001586 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001587 const char* rpath = NULL, *lpath = ".";
1588
Lajos Molnar4b35c012013-04-19 12:41:09 -07001589 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001590
1591 if (rpath != NULL) {
Lajos Molnar4b35c012013-04-19 12:41:09 -07001592 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001593 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001594
1595 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001596 }
1597
1598 if(!strcmp(argv[0], "install")) {
1599 if (argc < 2) return usage();
1600 return install_app(ttype, serial, argc, argv);
1601 }
1602
1603 if(!strcmp(argv[0], "uninstall")) {
1604 if (argc < 2) return usage();
1605 return uninstall_app(ttype, serial, argc, argv);
1606 }
1607
1608 if(!strcmp(argv[0], "sync")) {
1609 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001610 int listonly = 0;
1611
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001612 int ret;
1613 if(argc < 2) {
1614 /* No local path was specified. */
1615 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001616 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1617 listonly = 1;
1618 if (argc == 3) {
1619 srcarg = argv[2];
1620 } else {
1621 srcarg = NULL;
1622 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 } else if(argc == 2) {
1624 /* A local path or "android"/"data" arg was specified. */
1625 srcarg = argv[1];
1626 } else {
1627 return usage();
1628 }
1629 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1630 if(ret != 0) return usage();
1631
1632 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001633 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001634 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001635 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001636
1637 free(android_srcpath);
1638 free(data_srcpath);
1639 return ret;
1640 }
1641
1642 /* passthrough commands */
1643
1644 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001645 !strcmp(argv[0],"get-serialno") ||
1646 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001647 {
1648 char *tmp;
1649
1650 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1651 tmp = adb_query(buf);
1652 if(tmp) {
1653 printf("%s\n", tmp);
1654 return 0;
1655 } else {
1656 return 1;
1657 }
1658 }
1659
1660 /* other commands */
1661
1662 if(!strcmp(argv[0],"status-window")) {
1663 status_window(ttype, serial);
1664 return 0;
1665 }
1666
Christopher Tatedb0a8802011-11-30 13:00:33 -08001667 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001668 return logcat(ttype, serial, argc, argv);
1669 }
1670
1671 if(!strcmp(argv[0],"ppp")) {
1672 return ppp(argc, argv);
1673 }
1674
1675 if (!strcmp(argv[0], "start-server")) {
1676 return adb_connect("host:start-server");
1677 }
1678
Christopher Tated2f54152011-04-21 12:53:28 -07001679 if (!strcmp(argv[0], "backup")) {
1680 return backup(argc, argv);
1681 }
1682
Christopher Tate702967a2011-05-17 15:52:54 -07001683 if (!strcmp(argv[0], "restore")) {
1684 return restore(argc, argv);
1685 }
1686
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 if (!strcmp(argv[0], "jdwp")) {
1688 int fd = adb_connect("jdwp");
1689 if (fd >= 0) {
1690 read_and_dump(fd);
1691 adb_close(fd);
1692 return 0;
1693 } else {
1694 fprintf(stderr, "error: %s\n", adb_error());
1695 return -1;
1696 }
1697 }
1698
1699 /* "adb /?" is a common idiom under Windows */
1700 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1701 help();
1702 return 0;
1703 }
1704
1705 if(!strcmp(argv[0], "version")) {
1706 version(stdout);
1707 return 0;
1708 }
1709
1710 usage();
1711 return 1;
1712}
1713
Alexander Ivchenko53723332014-08-06 14:51:40 +04001714#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001715static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1716{
Alexander Ivchenko53723332014-08-06 14:51:40 +04001717 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001718 int argc;
1719 va_list ap;
1720
1721 va_start(ap, cmd);
1722 argc = 0;
1723
1724 if (serial) {
1725 argv[argc++] = "-s";
1726 argv[argc++] = serial;
1727 } else if (ttype == kTransportUsb) {
1728 argv[argc++] = "-d";
1729 } else if (ttype == kTransportLocal) {
1730 argv[argc++] = "-e";
1731 }
1732
1733 argv[argc++] = cmd;
Alexander Ivchenko53723332014-08-06 14:51:40 +04001734 while(argc < MAX_ARGV_LENGTH &&
1735 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1736 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001737 va_end(ap);
1738
1739#if 0
1740 int n;
1741 fprintf(stderr,"argc = %d\n",argc);
1742 for(n = 0; n < argc; n++) {
1743 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1744 }
1745#endif
1746
1747 return adb_commandline(argc, argv);
1748}
1749
1750int find_sync_dirs(const char *srcarg,
1751 char **android_srcdir_out, char **data_srcdir_out)
1752{
1753 char *android_srcdir, *data_srcdir;
1754
1755 if(srcarg == NULL) {
1756 android_srcdir = product_file("system");
1757 data_srcdir = product_file("data");
1758 } else {
1759 /* srcarg may be "data", "system" or NULL.
1760 * if srcarg is NULL, then both data and system are synced
1761 */
1762 if(strcmp(srcarg, "system") == 0) {
1763 android_srcdir = product_file("system");
1764 data_srcdir = NULL;
1765 } else if(strcmp(srcarg, "data") == 0) {
1766 android_srcdir = NULL;
1767 data_srcdir = product_file("data");
1768 } else {
1769 /* It's not "system" or "data".
1770 */
1771 return 1;
1772 }
1773 }
1774
1775 if(android_srcdir_out != NULL)
1776 *android_srcdir_out = android_srcdir;
1777 else
1778 free(android_srcdir);
1779
1780 if(data_srcdir_out != NULL)
1781 *data_srcdir_out = data_srcdir;
1782 else
1783 free(data_srcdir);
1784
1785 return 0;
1786}
1787
1788static int pm_command(transport_type transport, char* serial,
1789 int argc, char** argv)
1790{
1791 char buf[4096];
1792
1793 snprintf(buf, sizeof(buf), "shell:pm");
1794
1795 while(argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001796 char *quoted = escape_arg(*argv++);
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -07001797 strncat(buf, " ", sizeof(buf) - 1);
1798 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001799 free(quoted);
1800 }
1801
1802 send_shellcommand(transport, serial, buf);
1803 return 0;
1804}
1805
1806int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1807{
1808 /* if the user choose the -k option, we refuse to do it until devices are
1809 out with the option to uninstall the remaining data somehow (adb/ui) */
1810 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1811 {
1812 printf(
1813 "The -k option uninstalls the application while retaining the data/cache.\n"
1814 "At the moment, there is no way to remove the remaining data.\n"
1815 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1816 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1817 return -1;
1818 }
1819
1820 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1821 return pm_command(transport, serial, argc, argv);
1822}
1823
1824static int delete_file(transport_type transport, char* serial, char* filename)
1825{
1826 char buf[4096];
1827 char* quoted;
1828
1829 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001830 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001831 strncat(buf, quoted, sizeof(buf)-1);
1832 free(quoted);
1833
1834 send_shellcommand(transport, serial, buf);
1835 return 0;
1836}
1837
Kenny Root597ea5b2011-08-05 11:19:45 -07001838static const char* get_basename(const char* filename)
1839{
1840 const char* basename = adb_dirstop(filename);
1841 if (basename) {
1842 basename++;
1843 return basename;
1844 } else {
1845 return filename;
1846 }
1847}
1848
1849static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001850{
1851 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001852
Kenny Root597ea5b2011-08-05 11:19:45 -07001853 if (filename == NULL) {
1854 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001855 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001856
Kenny Root597ea5b2011-08-05 11:19:45 -07001857 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001858 fprintf(stderr, "can't find '%s' to install\n", filename);
1859 return 1;
1860 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001861
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001862 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001863 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001864 return 1;
1865 }
1866
Kenny Root597ea5b2011-08-05 11:19:45 -07001867 return 0;
1868}
1869
1870int install_app(transport_type transport, char* serial, int argc, char** argv)
1871{
1872 static const char *const DATA_DEST = "/data/local/tmp/%s";
1873 static const char *const SD_DEST = "/sdcard/tmp/%s";
1874 const char* where = DATA_DEST;
1875 char apk_dest[PATH_MAX];
1876 char verification_dest[PATH_MAX];
1877 char* apk_file;
1878 char* verification_file = NULL;
1879 int file_arg = -1;
1880 int err;
1881 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001882 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001883
1884 for (i = 1; i < argc; i++) {
1885 if (*argv[i] != '-') {
1886 file_arg = i;
1887 break;
Kenny Roota031a912011-09-23 12:46:39 -07001888 } else if (!strcmp(argv[i], "-i")) {
1889 // Skip the installer package name.
1890 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001891 } else if (!strcmp(argv[i], "-s")) {
1892 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001893 } else if (!strcmp(argv[i], "--algo")) {
1894 verify_apk = 0;
1895 i++;
1896 } else if (!strcmp(argv[i], "--iv")) {
1897 verify_apk = 0;
1898 i++;
1899 } else if (!strcmp(argv[i], "--key")) {
1900 verify_apk = 0;
1901 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001902 } else if (!strcmp(argv[i], "--abi")) {
1903 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001904 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001905 }
1906
Kenny Root597ea5b2011-08-05 11:19:45 -07001907 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001908 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001909 return 1;
1910 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001911 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001912 return 1;
1913 }
1914
1915 apk_file = argv[file_arg];
1916
1917 if (file_arg != argc - 1) {
1918 verification_file = argv[file_arg + 1];
1919 }
1920
1921 if (check_file(apk_file) || check_file(verification_file)) {
1922 return 1;
1923 }
1924
1925 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1926 if (verification_file != NULL) {
1927 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1928
1929 if (!strcmp(apk_dest, verification_dest)) {
1930 fprintf(stderr, "APK and verification file can't have the same name\n");
1931 return 1;
1932 }
1933 }
1934
Mark Lindner76f2a932014-03-11 17:55:59 -07001935 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001937 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001938 } else {
1939 argv[file_arg] = apk_dest; /* destination name, not source location */
1940 }
1941
1942 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001943 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1944 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001945 if (err) {
1946 goto cleanup_apk;
1947 } else {
1948 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1949 }
1950 }
1951
1952 pm_command(transport, serial, argc, argv);
1953
Kenny Root60733e92012-03-26 16:14:02 -07001954cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001955 if (verification_file != NULL) {
1956 delete_file(transport, serial, verification_dest);
1957 }
1958
Kenny Root597ea5b2011-08-05 11:19:45 -07001959 delete_file(transport, serial, apk_dest);
1960
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001961 return err;
1962}