blob: 356c0db3e5c5db4e3f95814cdbb71d66a9d01788 [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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800503static void status_window(transport_type ttype, const char* serial)
504{
505 char command[4096];
506 char *state = 0;
507 char *laststate = 0;
508
509 /* silence stderr */
510#ifdef _WIN32
511 /* XXX: TODO */
512#else
513 int fd;
514 fd = unix_open("/dev/null", O_WRONLY);
515 dup2(fd, 2);
516 adb_close(fd);
517#endif
518
519 format_host_command(command, sizeof command, "get-state", ttype, serial);
520
521 for(;;) {
522 adb_sleep_ms(250);
523
524 if(state) {
525 free(state);
526 state = 0;
527 }
528
529 state = adb_query(command);
530
531 if(state) {
532 if(laststate && !strcmp(state,laststate)){
533 continue;
534 } else {
535 if(laststate) free(laststate);
536 laststate = strdup(state);
537 }
538 }
539
540 printf("%c[2J%c[2H", 27, 27);
541 printf("Android Debug Bridge\n");
542 printf("State: %s\n", state ? state : "offline");
543 fflush(stdout);
544 }
545}
546
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700547/** Duplicate and escape given argument. */
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700548static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800549{
550 const char *ts;
551 size_t alloc_len;
552 char *ret;
553 char *dest;
554
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700555 alloc_len = 0;
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700556 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800557 alloc_len++;
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700558 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800559 alloc_len++;
560 }
561 }
562
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700563 if (alloc_len == 0) {
564 // Preserve empty arguments
565 ret = (char *) malloc(3);
566 ret[0] = '\"';
567 ret[1] = '\"';
568 ret[2] = '\0';
569 return ret;
570 }
571
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700572 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800573 dest = ret;
574
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700575 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700576 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800577 *dest++ = '\\';
578 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800579 *dest++ = *ts;
580 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800581 *dest++ = '\0';
582
583 return ret;
584}
585
586/**
587 * Run ppp in "notty" mode against a resource listed as the first parameter
588 * eg:
589 *
590 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
591 *
592 */
593int ppp(int argc, char **argv)
594{
595#ifdef HAVE_WIN32_PROC
596 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
597 return -1;
598#else
599 char *adb_service_name;
600 pid_t pid;
601 int fd;
602
603 if (argc < 2) {
604 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
605 argv[0]);
606
607 return 1;
608 }
609
610 adb_service_name = argv[1];
611
612 fd = adb_connect(adb_service_name);
613
614 if(fd < 0) {
615 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
616 adb_service_name, adb_error());
617 return 1;
618 }
619
620 pid = fork();
621
622 if (pid < 0) {
623 perror("from fork()");
624 return 1;
625 } else if (pid == 0) {
626 int err;
627 int i;
628 const char **ppp_args;
629
630 // copy args
631 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
632 ppp_args[0] = "pppd";
633 for (i = 2 ; i < argc ; i++) {
634 //argv[2] and beyond become ppp_args[1] and beyond
635 ppp_args[i - 1] = argv[i];
636 }
637 ppp_args[i-1] = NULL;
638
639 // child side
640
641 dup2(fd, STDIN_FILENO);
642 dup2(fd, STDOUT_FILENO);
643 adb_close(STDERR_FILENO);
644 adb_close(fd);
645
646 err = execvp("pppd", (char * const *)ppp_args);
647
648 if (err < 0) {
649 perror("execing pppd");
650 }
651 exit(-1);
652 } else {
653 // parent side
654
655 adb_close(fd);
656 return 0;
657 }
658#endif /* !HAVE_WIN32_PROC */
659}
660
661static int send_shellcommand(transport_type transport, char* serial, char* buf)
662{
663 int fd, ret;
664
665 for(;;) {
666 fd = adb_connect(buf);
667 if(fd >= 0)
668 break;
669 fprintf(stderr,"- waiting for device -\n");
670 adb_sleep_ms(1000);
671 do_cmd(transport, serial, "wait-for-device", 0);
672 }
673
674 read_and_dump(fd);
675 ret = adb_close(fd);
676 if (ret)
677 perror("close");
678
679 return ret;
680}
681
682static int logcat(transport_type transport, char* serial, int argc, char **argv)
683{
684 char buf[4096];
685
686 char *log_tags;
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700687 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800688
689 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700690 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800691 snprintf(buf, sizeof(buf),
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700692 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700693 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800694
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700695 if (!strcmp(argv[0], "longcat")) {
696 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800697 }
698
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800699 argc -= 1;
700 argv += 1;
701 while(argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -0700702 quoted = escape_arg(*argv++);
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700703 strncat(buf, " ", sizeof(buf) - 1);
704 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800705 free(quoted);
706 }
707
708 send_shellcommand(transport, serial, buf);
709 return 0;
710}
711
Mark Salyzyn60299df2014-04-30 09:10:31 -0700712static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800713{
714 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700715 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800716
717 for(;;) {
718 x = adb_dirstart(x);
719 if(x == 0) return 0;
720 *x = 0;
721 ret = adb_mkdir(path, 0775);
722 *x = OS_PATH_SEPARATOR;
723 if((ret < 0) && (errno != EEXIST)) {
724 return ret;
725 }
726 x++;
727 }
728 return 0;
729}
730
Christopher Tated2f54152011-04-21 12:53:28 -0700731static int backup(int argc, char** argv) {
732 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800733 char default_name[32];
734 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700735 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700736 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700737
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700738 /* find, extract, and use any -f argument */
739 for (i = 1; i < argc; i++) {
740 if (!strcmp("-f", argv[i])) {
741 if (i == argc-1) {
742 fprintf(stderr, "adb: -f passed with no filename\n");
743 return usage();
744 }
745 filename = argv[i+1];
746 for (j = i+2; j <= argc; ) {
747 argv[i++] = argv[j++];
748 }
749 argc -= 2;
750 argv[argc] = NULL;
751 }
Christopher Tated2f54152011-04-21 12:53:28 -0700752 }
753
Christopher Tatebb86bc52011-08-22 17:12:08 -0700754 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
755 if (argc < 2) return usage();
756
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800757 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700758 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800759 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700760 if (outFd < 0) {
761 fprintf(stderr, "adb: unable to open file %s\n", filename);
762 return -1;
763 }
764
765 snprintf(buf, sizeof(buf), "backup");
766 for (argc--, argv++; argc; argc--, argv++) {
767 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
768 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
769 }
770
771 D("backup. filename=%s buf=%s\n", filename, buf);
772 fd = adb_connect(buf);
773 if (fd < 0) {
774 fprintf(stderr, "adb: unable to connect for backup\n");
775 adb_close(outFd);
776 return -1;
777 }
778
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800779 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700780 copy_to_file(fd, outFd);
781
782 adb_close(fd);
783 adb_close(outFd);
784 return 0;
785}
786
Christopher Tate702967a2011-05-17 15:52:54 -0700787static int restore(int argc, char** argv) {
788 const char* filename;
789 int fd, tarFd;
790
791 if (argc != 2) return usage();
792
793 filename = argv[1];
794 tarFd = adb_open(filename, O_RDONLY);
795 if (tarFd < 0) {
796 fprintf(stderr, "adb: unable to open file %s\n", filename);
797 return -1;
798 }
799
800 fd = adb_connect("restore:");
801 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700802 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700803 adb_close(tarFd);
804 return -1;
805 }
806
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800807 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700808 copy_to_file(tarFd, fd);
809
810 adb_close(fd);
811 adb_close(tarFd);
812 return 0;
813}
814
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800815#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
816static int top_works(const char *top)
817{
818 if (top != NULL && adb_is_absolute_host_path(top)) {
819 char path_buf[PATH_MAX];
820 snprintf(path_buf, sizeof(path_buf),
821 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
822 return access(path_buf, F_OK) == 0;
823 }
824 return 0;
825}
826
827static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
828{
829 strcpy(path_buf, indir);
830 while (1) {
831 if (top_works(path_buf)) {
832 return path_buf;
833 }
834 char *s = adb_dirstop(path_buf);
835 if (s != NULL) {
836 *s = '\0';
837 } else {
838 path_buf[0] = '\0';
839 return NULL;
840 }
841 }
842}
843
844static char *find_top(char path_buf[PATH_MAX])
845{
846 char *top = getenv("ANDROID_BUILD_TOP");
847 if (top != NULL && top[0] != '\0') {
848 if (!top_works(top)) {
849 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
850 return NULL;
851 }
852 } else {
853 top = getenv("TOP");
854 if (top != NULL && top[0] != '\0') {
855 if (!top_works(top)) {
856 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
857 return NULL;
858 }
859 } else {
860 top = NULL;
861 }
862 }
863
864 if (top != NULL) {
865 /* The environment pointed to a top directory that works.
866 */
867 strcpy(path_buf, top);
868 return path_buf;
869 }
870
871 /* The environment didn't help. Walk up the tree from the CWD
872 * to see if we can find the top.
873 */
874 char dir[PATH_MAX];
875 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
876 if (top == NULL) {
877 /* If the CWD isn't under a good-looking top, see if the
878 * executable is.
879 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100880 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800881 top = find_top_from(dir, path_buf);
882 }
883 return top;
884}
885
886/* <hint> may be:
887 * - A simple product name
888 * e.g., "sooner"
889TODO: debug? sooner-debug, sooner:debug?
890 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
891 * e.g., "out/target/product/sooner"
892 * - An absolute path to the PRODUCT_OUT dir
893 * e.g., "/src/device/out/target/product/sooner"
894 *
895 * Given <hint>, try to construct an absolute path to the
896 * ANDROID_PRODUCT_OUT dir.
897 */
898static const char *find_product_out_path(const char *hint)
899{
900 static char path_buf[PATH_MAX];
901
902 if (hint == NULL || hint[0] == '\0') {
903 return NULL;
904 }
905
906 /* If it's already absolute, don't bother doing any work.
907 */
908 if (adb_is_absolute_host_path(hint)) {
909 strcpy(path_buf, hint);
910 return path_buf;
911 }
912
913 /* If there are any slashes in it, assume it's a relative path;
914 * make it absolute.
915 */
916 if (adb_dirstart(hint) != NULL) {
917 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
918 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
919 return NULL;
920 }
921 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
922 fprintf(stderr, "adb: Couldn't assemble path\n");
923 return NULL;
924 }
925 strcat(path_buf, OS_PATH_SEPARATOR_STR);
926 strcat(path_buf, hint);
927 return path_buf;
928 }
929
930 /* It's a string without any slashes. Try to do something with it.
931 *
932 * Try to find the root of the build tree, and build a PRODUCT_OUT
933 * path from there.
934 */
935 char top_buf[PATH_MAX];
936 const char *top = find_top(top_buf);
937 if (top == NULL) {
938 fprintf(stderr, "adb: Couldn't find top of build tree\n");
939 return NULL;
940 }
941//TODO: if we have a way to indicate debug, look in out/debug/target/...
942 snprintf(path_buf, sizeof(path_buf),
943 "%s" OS_PATH_SEPARATOR_STR
944 "out" OS_PATH_SEPARATOR_STR
945 "target" OS_PATH_SEPARATOR_STR
946 "product" OS_PATH_SEPARATOR_STR
947 "%s", top_buf, hint);
948 if (access(path_buf, F_OK) < 0) {
949 fprintf(stderr, "adb: Couldn't find a product dir "
950 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
951 return NULL;
952 }
953 return path_buf;
954}
955
Lajos Molnar4b35c012013-04-19 12:41:09 -0700956static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
957 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700958 *show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -0700959 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700960
Lajos Molnar4b35c012013-04-19 12:41:09 -0700961 while (narg > 0) {
962 if (!strcmp(*arg, "-p")) {
963 *show_progress = 1;
964 } else if (!strcmp(*arg, "-a")) {
965 *copy_attrs = 1;
966 } else {
967 break;
968 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700969 ++arg;
970 --narg;
971 }
972
973 if (narg > 0) {
974 *path1 = *arg;
975 ++arg;
976 --narg;
977 }
978
979 if (narg > 0) {
980 *path2 = *arg;
981 }
982}
983
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800984int adb_commandline(int argc, char **argv)
985{
986 char buf[4096];
987 int no_daemon = 0;
988 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100989 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800990 int persist = 0;
991 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992 transport_type ttype = kTransportAny;
993 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100994 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800995
996 /* If defined, this should be an absolute path to
997 * the directory containing all of the various system images
998 * for a particular product. If not defined, and the adb
999 * command requires this information, then the user must
1000 * specify the path using "-p".
1001 */
1002 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1003 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1004 gProductOutPath = NULL;
1005 }
1006 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1007
Nick Pellydb449262009-05-07 12:48:03 -07001008 serial = getenv("ANDROID_SERIAL");
1009
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001010 /* Validate and assign the server port */
1011 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1012 int server_port = DEFAULT_ADB_PORT;
1013 if (server_port_str && strlen(server_port_str) > 0) {
1014 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001015 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001016 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001017 "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 +01001018 server_port_str);
1019 return usage();
1020 }
1021 }
1022
1023 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001024 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001025 if(!strcmp(argv[0],"server")) {
1026 is_server = 1;
1027 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 no_daemon = 1;
1029 } else if (!strcmp(argv[0], "fork-server")) {
1030 /* this is a special flag used only when the ADB client launches the ADB Server */
1031 is_daemon = 1;
1032 } else if(!strcmp(argv[0],"persist")) {
1033 persist = 1;
1034 } else if(!strncmp(argv[0], "-p", 2)) {
1035 const char *product = NULL;
1036 if (argv[0][2] == '\0') {
1037 if (argc < 2) return usage();
1038 product = argv[1];
1039 argc--;
1040 argv++;
1041 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001042 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001043 }
1044 gProductOutPath = find_product_out_path(product);
1045 if (gProductOutPath == NULL) {
1046 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1047 product);
1048 return usage();
1049 }
1050 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1051 if (isdigit(argv[0][2])) {
1052 serial = argv[0] + 2;
1053 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001054 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001055 serial = argv[1];
1056 argc--;
1057 argv++;
1058 }
1059 } else if (!strcmp(argv[0],"-d")) {
1060 ttype = kTransportUsb;
1061 } else if (!strcmp(argv[0],"-e")) {
1062 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001063 } else if (!strcmp(argv[0],"-a")) {
1064 gListenAll = 1;
1065 } else if(!strncmp(argv[0], "-H", 2)) {
1066 const char *hostname = NULL;
1067 if (argv[0][2] == '\0') {
1068 if (argc < 2) return usage();
1069 hostname = argv[1];
1070 argc--;
1071 argv++;
1072 } else {
1073 hostname = argv[0] + 2;
1074 }
1075 adb_set_tcp_name(hostname);
1076
1077 } else if(!strncmp(argv[0], "-P", 2)) {
1078 if (argv[0][2] == '\0') {
1079 if (argc < 2) return usage();
1080 server_port_str = argv[1];
1081 argc--;
1082 argv++;
1083 } else {
1084 server_port_str = argv[0] + 2;
1085 }
1086 if (strlen(server_port_str) > 0) {
1087 server_port = (int) strtol(server_port_str, NULL, 0);
1088 if (server_port <= 0 || server_port > 65535) {
1089 fprintf(stderr,
1090 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1091 server_port_str);
1092 return usage();
1093 }
1094 } else {
1095 fprintf(stderr,
1096 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1097 return usage();
1098 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001099 } else {
1100 /* out of recognized modifiers and flags */
1101 break;
1102 }
1103 argc--;
1104 argv++;
1105 }
1106
1107 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001108 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001109
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001110 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001111 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001112 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001113 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001114 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001115 }
1116 if(r) {
1117 fprintf(stderr,"* could not start server *\n");
1118 }
1119 return r;
1120 }
1121
1122top:
1123 if(argc == 0) {
1124 return usage();
1125 }
1126
1127 /* adb_connect() commands */
1128
1129 if(!strcmp(argv[0], "devices")) {
1130 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001131 char *listopt;
1132 if (argc < 2)
1133 listopt = "";
1134 else if (argc == 2 && !strcmp(argv[1], "-l"))
1135 listopt = argv[1];
1136 else {
1137 fprintf(stderr, "Usage: adb devices [-l]\n");
1138 return 1;
1139 }
1140 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141 tmp = adb_query(buf);
1142 if(tmp) {
1143 printf("List of devices attached \n");
1144 printf("%s\n", tmp);
1145 return 0;
1146 } else {
1147 return 1;
1148 }
1149 }
1150
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001151 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001152 char *tmp;
1153 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001154 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001155 return 1;
1156 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001157 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1158 tmp = adb_query(buf);
1159 if(tmp) {
1160 printf("%s\n", tmp);
1161 return 0;
1162 } else {
1163 return 1;
1164 }
1165 }
1166
1167 if(!strcmp(argv[0], "disconnect")) {
1168 char *tmp;
1169 if (argc > 2) {
1170 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1171 return 1;
1172 }
1173 if (argc == 2) {
1174 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1175 } else {
1176 snprintf(buf, sizeof buf, "host:disconnect:");
1177 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001178 tmp = adb_query(buf);
1179 if(tmp) {
1180 printf("%s\n", tmp);
1181 return 0;
1182 } else {
1183 return 1;
1184 }
1185 }
1186
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001187 if (!strcmp(argv[0], "emu")) {
1188 return adb_send_emulator_command(argc, argv);
1189 }
1190
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001191 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 int r;
1193 int fd;
1194
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001195 char h = (argv[0][0] == 'h');
1196
1197 if (h) {
1198 printf("\x1b[41;33m");
1199 fflush(stdout);
1200 }
1201
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001202 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001203 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001204 r = interactive_shell();
1205 if (h) {
1206 printf("\x1b[0m");
1207 fflush(stdout);
1208 }
1209 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001210 }
1211
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001212 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001213 argc -= 2;
1214 argv += 2;
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001215 while (argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001216 char *quoted = escape_arg(*argv++);
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001217 strncat(buf, " ", sizeof(buf) - 1);
1218 strncat(buf, quoted, sizeof(buf) - 1);
1219 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 }
1221
1222 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001223 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001224 fd = adb_connect(buf);
1225 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001226 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001227 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001228 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001229 adb_close(fd);
1230 r = 0;
1231 } else {
1232 fprintf(stderr,"error: %s\n", adb_error());
1233 r = -1;
1234 }
1235
1236 if(persist) {
1237 fprintf(stderr,"\n- waiting for device -\n");
1238 adb_sleep_ms(1000);
1239 do_cmd(ttype, serial, "wait-for-device", 0);
1240 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001241 if (h) {
1242 printf("\x1b[0m");
1243 fflush(stdout);
1244 }
JP Abgrall408fa572011-03-16 15:57:42 -07001245 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001246 return r;
1247 }
1248 }
1249 }
1250
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001251 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1252 int exec_in = !strcmp(argv[0], "exec-in");
1253 int fd;
1254
1255 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1256 argc -= 2;
1257 argv += 2;
1258 while (argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001259 char *quoted = escape_arg(*argv++);
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001260 strncat(buf, " ", sizeof(buf) - 1);
1261 strncat(buf, quoted, sizeof(buf) - 1);
1262 free(quoted);
1263 }
1264
1265 fd = adb_connect(buf);
1266 if (fd < 0) {
1267 fprintf(stderr, "error: %s\n", adb_error());
1268 return -1;
1269 }
1270
1271 if (exec_in) {
1272 copy_to_file(STDIN_FILENO, fd);
1273 } else {
1274 copy_to_file(fd, STDOUT_FILENO);
1275 }
1276
1277 adb_close(fd);
1278 return 0;
1279 }
1280
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001281 if(!strcmp(argv[0], "kill-server")) {
1282 int fd;
1283 fd = _adb_connect("host:kill");
1284 if(fd == -1) {
1285 fprintf(stderr,"* server not running *\n");
1286 return 1;
1287 }
1288 return 0;
1289 }
1290
Doug Zongker447f0612012-01-09 14:54:53 -08001291 if(!strcmp(argv[0], "sideload")) {
1292 if(argc != 2) return usage();
1293 if(adb_download("sideload", argv[1], 1)) {
1294 return 1;
1295 } else {
1296 return 0;
1297 }
1298 }
1299
Mike Lockwoodff196702009-08-24 15:58:40 -07001300 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001301 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001302 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001303 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001304 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001305 if (!strcmp(argv[0], "reboot-bootloader"))
1306 snprintf(command, sizeof(command), "reboot:bootloader");
1307 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001308 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001309 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001310 snprintf(command, sizeof(command), "%s:", argv[0]);
1311 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001312 if(fd >= 0) {
1313 read_and_dump(fd);
1314 adb_close(fd);
1315 return 0;
1316 }
1317 fprintf(stderr,"error: %s\n", adb_error());
1318 return 1;
1319 }
1320
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001321 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001322 if (argc != 1) return usage();
1323 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001324 return 0;
1325 }
1326
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001327 /* adb_command() wrapper commands */
1328
1329 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1330 char* service = argv[0];
1331 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1332 if (ttype == kTransportUsb) {
1333 service = "wait-for-usb";
1334 } else if (ttype == kTransportLocal) {
1335 service = "wait-for-local";
1336 } else {
1337 service = "wait-for-any";
1338 }
1339 }
1340
1341 format_host_command(buf, sizeof buf, service, ttype, serial);
1342
1343 if (adb_command(buf)) {
1344 D("failure: %s *\n",adb_error());
1345 fprintf(stderr,"error: %s\n", adb_error());
1346 return 1;
1347 }
1348
1349 /* Allow a command to be run after wait-for-device,
1350 * e.g. 'adb wait-for-device shell'.
1351 */
1352 if(argc > 1) {
1353 argc--;
1354 argv++;
1355 goto top;
1356 }
1357 return 0;
1358 }
1359
David 'Digit' Turner25258692013-03-21 21:07:42 +01001360 if(!strcmp(argv[0], "forward") ||
1361 !strcmp(argv[0], "reverse"))
1362 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001363 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001364 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001365 char remove = 0;
1366 char remove_all = 0;
1367 char list = 0;
1368 char no_rebind = 0;
1369
1370 // Parse options here.
1371 while (argc > 1 && argv[1][0] == '-') {
1372 if (!strcmp(argv[1], "--list"))
1373 list = 1;
1374 else if (!strcmp(argv[1], "--remove"))
1375 remove = 1;
1376 else if (!strcmp(argv[1], "--remove-all"))
1377 remove_all = 1;
1378 else if (!strcmp(argv[1], "--no-rebind"))
1379 no_rebind = 1;
1380 else {
1381 return usage();
1382 }
1383 argc--;
1384 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001386
1387 // Ensure we can only use one option at a time.
1388 if (list + remove + remove_all + no_rebind > 1) {
1389 return usage();
1390 }
1391
1392 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001393 if (reverse) {
1394 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001395 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001396 if (serial) {
1397 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1398 serial);
1399 } else if (ttype == kTransportUsb) {
1400 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1401 } else if (ttype == kTransportLocal) {
1402 snprintf(host_prefix, sizeof host_prefix, "host-local");
1403 } else {
1404 snprintf(host_prefix, sizeof host_prefix, "host");
1405 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001406 }
1407
1408 // Implement forward --list
1409 if (list) {
1410 if (argc != 1)
1411 return usage();
1412 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1413 char* forwards = adb_query(buf);
1414 if (forwards == NULL) {
1415 fprintf(stderr, "error: %s\n", adb_error());
1416 return 1;
1417 }
1418 printf("%s", forwards);
1419 free(forwards);
1420 return 0;
1421 }
1422
1423 // Implement forward --remove-all
1424 else if (remove_all) {
1425 if (argc != 1)
1426 return usage();
1427 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1428 }
1429
1430 // Implement forward --remove <local>
1431 else if (remove) {
1432 if (argc != 2)
1433 return usage();
1434 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1435 }
1436 // Or implement one of:
1437 // forward <local> <remote>
1438 // forward --no-rebind <local> <remote>
1439 else
1440 {
1441 if (argc != 3)
1442 return usage();
1443 const char* command = no_rebind ? "forward:norebind:" : "forward";
1444 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1445 }
1446
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001447 if(adb_command(buf)) {
1448 fprintf(stderr,"error: %s\n", adb_error());
1449 return 1;
1450 }
1451 return 0;
1452 }
1453
1454 /* do_sync_*() commands */
1455
1456 if(!strcmp(argv[0], "ls")) {
1457 if(argc != 2) return usage();
1458 return do_sync_ls(argv[1]);
1459 }
1460
1461 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001462 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001463 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001464 const char* lpath = NULL, *rpath = NULL;
1465
Lajos Molnar4b35c012013-04-19 12:41:09 -07001466 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001467
1468 if ((lpath != NULL) && (rpath != NULL)) {
1469 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1470 }
1471
1472 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001473 }
1474
1475 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001476 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001477 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001478 const char* rpath = NULL, *lpath = ".";
1479
Lajos Molnar4b35c012013-04-19 12:41:09 -07001480 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001481
1482 if (rpath != NULL) {
Lajos Molnar4b35c012013-04-19 12:41:09 -07001483 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001484 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001485
1486 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001487 }
1488
1489 if(!strcmp(argv[0], "install")) {
1490 if (argc < 2) return usage();
1491 return install_app(ttype, serial, argc, argv);
1492 }
1493
1494 if(!strcmp(argv[0], "uninstall")) {
1495 if (argc < 2) return usage();
1496 return uninstall_app(ttype, serial, argc, argv);
1497 }
1498
1499 if(!strcmp(argv[0], "sync")) {
1500 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001501 int listonly = 0;
1502
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503 int ret;
1504 if(argc < 2) {
1505 /* No local path was specified. */
1506 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001507 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1508 listonly = 1;
1509 if (argc == 3) {
1510 srcarg = argv[2];
1511 } else {
1512 srcarg = NULL;
1513 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001514 } else if(argc == 2) {
1515 /* A local path or "android"/"data" arg was specified. */
1516 srcarg = argv[1];
1517 } else {
1518 return usage();
1519 }
1520 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1521 if(ret != 0) return usage();
1522
1523 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001524 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001526 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001527
1528 free(android_srcpath);
1529 free(data_srcpath);
1530 return ret;
1531 }
1532
1533 /* passthrough commands */
1534
1535 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001536 !strcmp(argv[0],"get-serialno") ||
1537 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001538 {
1539 char *tmp;
1540
1541 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1542 tmp = adb_query(buf);
1543 if(tmp) {
1544 printf("%s\n", tmp);
1545 return 0;
1546 } else {
1547 return 1;
1548 }
1549 }
1550
1551 /* other commands */
1552
1553 if(!strcmp(argv[0],"status-window")) {
1554 status_window(ttype, serial);
1555 return 0;
1556 }
1557
Christopher Tatedb0a8802011-11-30 13:00:33 -08001558 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001559 return logcat(ttype, serial, argc, argv);
1560 }
1561
1562 if(!strcmp(argv[0],"ppp")) {
1563 return ppp(argc, argv);
1564 }
1565
1566 if (!strcmp(argv[0], "start-server")) {
1567 return adb_connect("host:start-server");
1568 }
1569
Christopher Tated2f54152011-04-21 12:53:28 -07001570 if (!strcmp(argv[0], "backup")) {
1571 return backup(argc, argv);
1572 }
1573
Christopher Tate702967a2011-05-17 15:52:54 -07001574 if (!strcmp(argv[0], "restore")) {
1575 return restore(argc, argv);
1576 }
1577
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001578 if (!strcmp(argv[0], "jdwp")) {
1579 int fd = adb_connect("jdwp");
1580 if (fd >= 0) {
1581 read_and_dump(fd);
1582 adb_close(fd);
1583 return 0;
1584 } else {
1585 fprintf(stderr, "error: %s\n", adb_error());
1586 return -1;
1587 }
1588 }
1589
1590 /* "adb /?" is a common idiom under Windows */
1591 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1592 help();
1593 return 0;
1594 }
1595
1596 if(!strcmp(argv[0], "version")) {
1597 version(stdout);
1598 return 0;
1599 }
1600
1601 usage();
1602 return 1;
1603}
1604
Alexander Ivchenko53723332014-08-06 14:51:40 +04001605#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001606static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1607{
Alexander Ivchenko53723332014-08-06 14:51:40 +04001608 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001609 int argc;
1610 va_list ap;
1611
1612 va_start(ap, cmd);
1613 argc = 0;
1614
1615 if (serial) {
1616 argv[argc++] = "-s";
1617 argv[argc++] = serial;
1618 } else if (ttype == kTransportUsb) {
1619 argv[argc++] = "-d";
1620 } else if (ttype == kTransportLocal) {
1621 argv[argc++] = "-e";
1622 }
1623
1624 argv[argc++] = cmd;
Alexander Ivchenko53723332014-08-06 14:51:40 +04001625 while(argc < MAX_ARGV_LENGTH &&
1626 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1627 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001628 va_end(ap);
1629
1630#if 0
1631 int n;
1632 fprintf(stderr,"argc = %d\n",argc);
1633 for(n = 0; n < argc; n++) {
1634 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1635 }
1636#endif
1637
1638 return adb_commandline(argc, argv);
1639}
1640
1641int find_sync_dirs(const char *srcarg,
1642 char **android_srcdir_out, char **data_srcdir_out)
1643{
1644 char *android_srcdir, *data_srcdir;
1645
1646 if(srcarg == NULL) {
1647 android_srcdir = product_file("system");
1648 data_srcdir = product_file("data");
1649 } else {
1650 /* srcarg may be "data", "system" or NULL.
1651 * if srcarg is NULL, then both data and system are synced
1652 */
1653 if(strcmp(srcarg, "system") == 0) {
1654 android_srcdir = product_file("system");
1655 data_srcdir = NULL;
1656 } else if(strcmp(srcarg, "data") == 0) {
1657 android_srcdir = NULL;
1658 data_srcdir = product_file("data");
1659 } else {
1660 /* It's not "system" or "data".
1661 */
1662 return 1;
1663 }
1664 }
1665
1666 if(android_srcdir_out != NULL)
1667 *android_srcdir_out = android_srcdir;
1668 else
1669 free(android_srcdir);
1670
1671 if(data_srcdir_out != NULL)
1672 *data_srcdir_out = data_srcdir;
1673 else
1674 free(data_srcdir);
1675
1676 return 0;
1677}
1678
1679static int pm_command(transport_type transport, char* serial,
1680 int argc, char** argv)
1681{
1682 char buf[4096];
1683
1684 snprintf(buf, sizeof(buf), "shell:pm");
1685
1686 while(argc-- > 0) {
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001687 char *quoted = escape_arg(*argv++);
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -07001688 strncat(buf, " ", sizeof(buf) - 1);
1689 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 free(quoted);
1691 }
1692
1693 send_shellcommand(transport, serial, buf);
1694 return 0;
1695}
1696
1697int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1698{
1699 /* if the user choose the -k option, we refuse to do it until devices are
1700 out with the option to uninstall the remaining data somehow (adb/ui) */
1701 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1702 {
1703 printf(
1704 "The -k option uninstalls the application while retaining the data/cache.\n"
1705 "At the moment, there is no way to remove the remaining data.\n"
1706 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1707 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1708 return -1;
1709 }
1710
1711 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1712 return pm_command(transport, serial, argc, argv);
1713}
1714
1715static int delete_file(transport_type transport, char* serial, char* filename)
1716{
1717 char buf[4096];
1718 char* quoted;
1719
1720 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey0cc642c2014-06-10 16:22:17 -07001721 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001722 strncat(buf, quoted, sizeof(buf)-1);
1723 free(quoted);
1724
1725 send_shellcommand(transport, serial, buf);
1726 return 0;
1727}
1728
Kenny Root597ea5b2011-08-05 11:19:45 -07001729static const char* get_basename(const char* filename)
1730{
1731 const char* basename = adb_dirstop(filename);
1732 if (basename) {
1733 basename++;
1734 return basename;
1735 } else {
1736 return filename;
1737 }
1738}
1739
1740static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001741{
1742 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001743
Kenny Root597ea5b2011-08-05 11:19:45 -07001744 if (filename == NULL) {
1745 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001746 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001747
Kenny Root597ea5b2011-08-05 11:19:45 -07001748 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001749 fprintf(stderr, "can't find '%s' to install\n", filename);
1750 return 1;
1751 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001752
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001753 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001754 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001755 return 1;
1756 }
1757
Kenny Root597ea5b2011-08-05 11:19:45 -07001758 return 0;
1759}
1760
1761int install_app(transport_type transport, char* serial, int argc, char** argv)
1762{
1763 static const char *const DATA_DEST = "/data/local/tmp/%s";
1764 static const char *const SD_DEST = "/sdcard/tmp/%s";
1765 const char* where = DATA_DEST;
1766 char apk_dest[PATH_MAX];
1767 char verification_dest[PATH_MAX];
1768 char* apk_file;
1769 char* verification_file = NULL;
1770 int file_arg = -1;
1771 int err;
1772 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001773 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001774
1775 for (i = 1; i < argc; i++) {
1776 if (*argv[i] != '-') {
1777 file_arg = i;
1778 break;
Kenny Roota031a912011-09-23 12:46:39 -07001779 } else if (!strcmp(argv[i], "-i")) {
1780 // Skip the installer package name.
1781 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001782 } else if (!strcmp(argv[i], "-s")) {
1783 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001784 } else if (!strcmp(argv[i], "--algo")) {
1785 verify_apk = 0;
1786 i++;
1787 } else if (!strcmp(argv[i], "--iv")) {
1788 verify_apk = 0;
1789 i++;
1790 } else if (!strcmp(argv[i], "--key")) {
1791 verify_apk = 0;
1792 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001793 } else if (!strcmp(argv[i], "--abi")) {
1794 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001795 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001796 }
1797
Kenny Root597ea5b2011-08-05 11:19:45 -07001798 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001799 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001800 return 1;
1801 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001802 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001803 return 1;
1804 }
1805
1806 apk_file = argv[file_arg];
1807
1808 if (file_arg != argc - 1) {
1809 verification_file = argv[file_arg + 1];
1810 }
1811
1812 if (check_file(apk_file) || check_file(verification_file)) {
1813 return 1;
1814 }
1815
1816 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1817 if (verification_file != NULL) {
1818 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1819
1820 if (!strcmp(apk_dest, verification_dest)) {
1821 fprintf(stderr, "APK and verification file can't have the same name\n");
1822 return 1;
1823 }
1824 }
1825
Mark Lindner76f2a932014-03-11 17:55:59 -07001826 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001827 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001828 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001829 } else {
1830 argv[file_arg] = apk_dest; /* destination name, not source location */
1831 }
1832
1833 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001834 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1835 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001836 if (err) {
1837 goto cleanup_apk;
1838 } else {
1839 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1840 }
1841 }
1842
1843 pm_command(transport, serial, argc, argv);
1844
Kenny Root60733e92012-03-26 16:14:02 -07001845cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001846 if (verification_file != NULL) {
1847 delete_file(transport, serial, verification_dest);
1848 }
1849
Kenny Root597ea5b2011-08-05 11:19:45 -07001850 delete_file(transport, serial, apk_dest);
1851
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001852 return err;
1853}