blob: 8189a710ad8e83e5021167213b0844c790813d89 [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. */
548static char *escape_argv(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 Sharkeydcd2f0e2014-06-10 11:31:24 -0700555 alloc_len = 2;
556 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800557 alloc_len++;
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700558 if (*ts == '"' || *ts == '\\') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800559 alloc_len++;
560 }
561 }
562
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700563 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800564 dest = ret;
565
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700566 *dest++ = '"';
567 for (ts = s; *ts != '\0'; ts++) {
568 if (*ts == '"' || *ts == '\\') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800569 *dest++ = '\\';
570 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800571 *dest++ = *ts;
572 }
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700573 *dest++ = '"';
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800574 *dest++ = '\0';
575
576 return ret;
577}
578
579/**
580 * Run ppp in "notty" mode against a resource listed as the first parameter
581 * eg:
582 *
583 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
584 *
585 */
586int ppp(int argc, char **argv)
587{
588#ifdef HAVE_WIN32_PROC
589 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
590 return -1;
591#else
592 char *adb_service_name;
593 pid_t pid;
594 int fd;
595
596 if (argc < 2) {
597 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
598 argv[0]);
599
600 return 1;
601 }
602
603 adb_service_name = argv[1];
604
605 fd = adb_connect(adb_service_name);
606
607 if(fd < 0) {
608 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
609 adb_service_name, adb_error());
610 return 1;
611 }
612
613 pid = fork();
614
615 if (pid < 0) {
616 perror("from fork()");
617 return 1;
618 } else if (pid == 0) {
619 int err;
620 int i;
621 const char **ppp_args;
622
623 // copy args
624 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
625 ppp_args[0] = "pppd";
626 for (i = 2 ; i < argc ; i++) {
627 //argv[2] and beyond become ppp_args[1] and beyond
628 ppp_args[i - 1] = argv[i];
629 }
630 ppp_args[i-1] = NULL;
631
632 // child side
633
634 dup2(fd, STDIN_FILENO);
635 dup2(fd, STDOUT_FILENO);
636 adb_close(STDERR_FILENO);
637 adb_close(fd);
638
639 err = execvp("pppd", (char * const *)ppp_args);
640
641 if (err < 0) {
642 perror("execing pppd");
643 }
644 exit(-1);
645 } else {
646 // parent side
647
648 adb_close(fd);
649 return 0;
650 }
651#endif /* !HAVE_WIN32_PROC */
652}
653
654static int send_shellcommand(transport_type transport, char* serial, char* buf)
655{
656 int fd, ret;
657
658 for(;;) {
659 fd = adb_connect(buf);
660 if(fd >= 0)
661 break;
662 fprintf(stderr,"- waiting for device -\n");
663 adb_sleep_ms(1000);
664 do_cmd(transport, serial, "wait-for-device", 0);
665 }
666
667 read_and_dump(fd);
668 ret = adb_close(fd);
669 if (ret)
670 perror("close");
671
672 return ret;
673}
674
675static int logcat(transport_type transport, char* serial, int argc, char **argv)
676{
677 char buf[4096];
678
679 char *log_tags;
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700680 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800681
682 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700683 quoted = escape_argv(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800684 snprintf(buf, sizeof(buf),
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700685 "shell:export ANDROID_LOG_TAGS=%s ; exec logcat", quoted);
686 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800687
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700688 if (!strcmp(argv[0], "longcat")) {
689 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800690 }
691
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800692 argc -= 1;
693 argv += 1;
694 while(argc-- > 0) {
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -0700695 quoted = escape_argv(*argv++);
696 strncat(buf, " ", sizeof(buf) - 1);
697 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800698 free(quoted);
699 }
700
701 send_shellcommand(transport, serial, buf);
702 return 0;
703}
704
Mark Salyzyn60299df2014-04-30 09:10:31 -0700705static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800706{
707 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700708 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800709
710 for(;;) {
711 x = adb_dirstart(x);
712 if(x == 0) return 0;
713 *x = 0;
714 ret = adb_mkdir(path, 0775);
715 *x = OS_PATH_SEPARATOR;
716 if((ret < 0) && (errno != EEXIST)) {
717 return ret;
718 }
719 x++;
720 }
721 return 0;
722}
723
Christopher Tated2f54152011-04-21 12:53:28 -0700724static int backup(int argc, char** argv) {
725 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800726 char default_name[32];
727 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700728 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700729 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700730
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700731 /* find, extract, and use any -f argument */
732 for (i = 1; i < argc; i++) {
733 if (!strcmp("-f", argv[i])) {
734 if (i == argc-1) {
735 fprintf(stderr, "adb: -f passed with no filename\n");
736 return usage();
737 }
738 filename = argv[i+1];
739 for (j = i+2; j <= argc; ) {
740 argv[i++] = argv[j++];
741 }
742 argc -= 2;
743 argv[argc] = NULL;
744 }
Christopher Tated2f54152011-04-21 12:53:28 -0700745 }
746
Christopher Tatebb86bc52011-08-22 17:12:08 -0700747 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
748 if (argc < 2) return usage();
749
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800750 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700751 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800752 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700753 if (outFd < 0) {
754 fprintf(stderr, "adb: unable to open file %s\n", filename);
755 return -1;
756 }
757
758 snprintf(buf, sizeof(buf), "backup");
759 for (argc--, argv++; argc; argc--, argv++) {
760 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
761 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
762 }
763
764 D("backup. filename=%s buf=%s\n", filename, buf);
765 fd = adb_connect(buf);
766 if (fd < 0) {
767 fprintf(stderr, "adb: unable to connect for backup\n");
768 adb_close(outFd);
769 return -1;
770 }
771
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800772 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700773 copy_to_file(fd, outFd);
774
775 adb_close(fd);
776 adb_close(outFd);
777 return 0;
778}
779
Christopher Tate702967a2011-05-17 15:52:54 -0700780static int restore(int argc, char** argv) {
781 const char* filename;
782 int fd, tarFd;
783
784 if (argc != 2) return usage();
785
786 filename = argv[1];
787 tarFd = adb_open(filename, O_RDONLY);
788 if (tarFd < 0) {
789 fprintf(stderr, "adb: unable to open file %s\n", filename);
790 return -1;
791 }
792
793 fd = adb_connect("restore:");
794 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700795 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700796 adb_close(tarFd);
797 return -1;
798 }
799
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800800 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700801 copy_to_file(tarFd, fd);
802
803 adb_close(fd);
804 adb_close(tarFd);
805 return 0;
806}
807
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800808#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
809static int top_works(const char *top)
810{
811 if (top != NULL && adb_is_absolute_host_path(top)) {
812 char path_buf[PATH_MAX];
813 snprintf(path_buf, sizeof(path_buf),
814 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
815 return access(path_buf, F_OK) == 0;
816 }
817 return 0;
818}
819
820static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
821{
822 strcpy(path_buf, indir);
823 while (1) {
824 if (top_works(path_buf)) {
825 return path_buf;
826 }
827 char *s = adb_dirstop(path_buf);
828 if (s != NULL) {
829 *s = '\0';
830 } else {
831 path_buf[0] = '\0';
832 return NULL;
833 }
834 }
835}
836
837static char *find_top(char path_buf[PATH_MAX])
838{
839 char *top = getenv("ANDROID_BUILD_TOP");
840 if (top != NULL && top[0] != '\0') {
841 if (!top_works(top)) {
842 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
843 return NULL;
844 }
845 } else {
846 top = getenv("TOP");
847 if (top != NULL && top[0] != '\0') {
848 if (!top_works(top)) {
849 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
850 return NULL;
851 }
852 } else {
853 top = NULL;
854 }
855 }
856
857 if (top != NULL) {
858 /* The environment pointed to a top directory that works.
859 */
860 strcpy(path_buf, top);
861 return path_buf;
862 }
863
864 /* The environment didn't help. Walk up the tree from the CWD
865 * to see if we can find the top.
866 */
867 char dir[PATH_MAX];
868 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
869 if (top == NULL) {
870 /* If the CWD isn't under a good-looking top, see if the
871 * executable is.
872 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100873 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800874 top = find_top_from(dir, path_buf);
875 }
876 return top;
877}
878
879/* <hint> may be:
880 * - A simple product name
881 * e.g., "sooner"
882TODO: debug? sooner-debug, sooner:debug?
883 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
884 * e.g., "out/target/product/sooner"
885 * - An absolute path to the PRODUCT_OUT dir
886 * e.g., "/src/device/out/target/product/sooner"
887 *
888 * Given <hint>, try to construct an absolute path to the
889 * ANDROID_PRODUCT_OUT dir.
890 */
891static const char *find_product_out_path(const char *hint)
892{
893 static char path_buf[PATH_MAX];
894
895 if (hint == NULL || hint[0] == '\0') {
896 return NULL;
897 }
898
899 /* If it's already absolute, don't bother doing any work.
900 */
901 if (adb_is_absolute_host_path(hint)) {
902 strcpy(path_buf, hint);
903 return path_buf;
904 }
905
906 /* If there are any slashes in it, assume it's a relative path;
907 * make it absolute.
908 */
909 if (adb_dirstart(hint) != NULL) {
910 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
911 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
912 return NULL;
913 }
914 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
915 fprintf(stderr, "adb: Couldn't assemble path\n");
916 return NULL;
917 }
918 strcat(path_buf, OS_PATH_SEPARATOR_STR);
919 strcat(path_buf, hint);
920 return path_buf;
921 }
922
923 /* It's a string without any slashes. Try to do something with it.
924 *
925 * Try to find the root of the build tree, and build a PRODUCT_OUT
926 * path from there.
927 */
928 char top_buf[PATH_MAX];
929 const char *top = find_top(top_buf);
930 if (top == NULL) {
931 fprintf(stderr, "adb: Couldn't find top of build tree\n");
932 return NULL;
933 }
934//TODO: if we have a way to indicate debug, look in out/debug/target/...
935 snprintf(path_buf, sizeof(path_buf),
936 "%s" OS_PATH_SEPARATOR_STR
937 "out" OS_PATH_SEPARATOR_STR
938 "target" OS_PATH_SEPARATOR_STR
939 "product" OS_PATH_SEPARATOR_STR
940 "%s", top_buf, hint);
941 if (access(path_buf, F_OK) < 0) {
942 fprintf(stderr, "adb: Couldn't find a product dir "
943 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
944 return NULL;
945 }
946 return path_buf;
947}
948
Lajos Molnar4b35c012013-04-19 12:41:09 -0700949static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
950 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700951 *show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -0700952 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700953
Lajos Molnar4b35c012013-04-19 12:41:09 -0700954 while (narg > 0) {
955 if (!strcmp(*arg, "-p")) {
956 *show_progress = 1;
957 } else if (!strcmp(*arg, "-a")) {
958 *copy_attrs = 1;
959 } else {
960 break;
961 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700962 ++arg;
963 --narg;
964 }
965
966 if (narg > 0) {
967 *path1 = *arg;
968 ++arg;
969 --narg;
970 }
971
972 if (narg > 0) {
973 *path2 = *arg;
974 }
975}
976
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800977int adb_commandline(int argc, char **argv)
978{
979 char buf[4096];
980 int no_daemon = 0;
981 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100982 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800983 int persist = 0;
984 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800985 transport_type ttype = kTransportAny;
986 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100987 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800988
989 /* If defined, this should be an absolute path to
990 * the directory containing all of the various system images
991 * for a particular product. If not defined, and the adb
992 * command requires this information, then the user must
993 * specify the path using "-p".
994 */
995 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
996 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
997 gProductOutPath = NULL;
998 }
999 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1000
Nick Pellydb449262009-05-07 12:48:03 -07001001 serial = getenv("ANDROID_SERIAL");
1002
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001003 /* Validate and assign the server port */
1004 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1005 int server_port = DEFAULT_ADB_PORT;
1006 if (server_port_str && strlen(server_port_str) > 0) {
1007 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001008 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001009 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001010 "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 +01001011 server_port_str);
1012 return usage();
1013 }
1014 }
1015
1016 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001017 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001018 if(!strcmp(argv[0],"server")) {
1019 is_server = 1;
1020 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001021 no_daemon = 1;
1022 } else if (!strcmp(argv[0], "fork-server")) {
1023 /* this is a special flag used only when the ADB client launches the ADB Server */
1024 is_daemon = 1;
1025 } else if(!strcmp(argv[0],"persist")) {
1026 persist = 1;
1027 } else if(!strncmp(argv[0], "-p", 2)) {
1028 const char *product = NULL;
1029 if (argv[0][2] == '\0') {
1030 if (argc < 2) return usage();
1031 product = argv[1];
1032 argc--;
1033 argv++;
1034 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001035 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001036 }
1037 gProductOutPath = find_product_out_path(product);
1038 if (gProductOutPath == NULL) {
1039 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1040 product);
1041 return usage();
1042 }
1043 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1044 if (isdigit(argv[0][2])) {
1045 serial = argv[0] + 2;
1046 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001047 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001048 serial = argv[1];
1049 argc--;
1050 argv++;
1051 }
1052 } else if (!strcmp(argv[0],"-d")) {
1053 ttype = kTransportUsb;
1054 } else if (!strcmp(argv[0],"-e")) {
1055 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001056 } else if (!strcmp(argv[0],"-a")) {
1057 gListenAll = 1;
1058 } else if(!strncmp(argv[0], "-H", 2)) {
1059 const char *hostname = NULL;
1060 if (argv[0][2] == '\0') {
1061 if (argc < 2) return usage();
1062 hostname = argv[1];
1063 argc--;
1064 argv++;
1065 } else {
1066 hostname = argv[0] + 2;
1067 }
1068 adb_set_tcp_name(hostname);
1069
1070 } else if(!strncmp(argv[0], "-P", 2)) {
1071 if (argv[0][2] == '\0') {
1072 if (argc < 2) return usage();
1073 server_port_str = argv[1];
1074 argc--;
1075 argv++;
1076 } else {
1077 server_port_str = argv[0] + 2;
1078 }
1079 if (strlen(server_port_str) > 0) {
1080 server_port = (int) strtol(server_port_str, NULL, 0);
1081 if (server_port <= 0 || server_port > 65535) {
1082 fprintf(stderr,
1083 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1084 server_port_str);
1085 return usage();
1086 }
1087 } else {
1088 fprintf(stderr,
1089 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1090 return usage();
1091 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001092 } else {
1093 /* out of recognized modifiers and flags */
1094 break;
1095 }
1096 argc--;
1097 argv++;
1098 }
1099
1100 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001101 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001102
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001103 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001105 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001106 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001107 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001108 }
1109 if(r) {
1110 fprintf(stderr,"* could not start server *\n");
1111 }
1112 return r;
1113 }
1114
1115top:
1116 if(argc == 0) {
1117 return usage();
1118 }
1119
1120 /* adb_connect() commands */
1121
1122 if(!strcmp(argv[0], "devices")) {
1123 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001124 char *listopt;
1125 if (argc < 2)
1126 listopt = "";
1127 else if (argc == 2 && !strcmp(argv[1], "-l"))
1128 listopt = argv[1];
1129 else {
1130 fprintf(stderr, "Usage: adb devices [-l]\n");
1131 return 1;
1132 }
1133 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001134 tmp = adb_query(buf);
1135 if(tmp) {
1136 printf("List of devices attached \n");
1137 printf("%s\n", tmp);
1138 return 0;
1139 } else {
1140 return 1;
1141 }
1142 }
1143
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001144 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001145 char *tmp;
1146 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001147 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001148 return 1;
1149 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001150 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1151 tmp = adb_query(buf);
1152 if(tmp) {
1153 printf("%s\n", tmp);
1154 return 0;
1155 } else {
1156 return 1;
1157 }
1158 }
1159
1160 if(!strcmp(argv[0], "disconnect")) {
1161 char *tmp;
1162 if (argc > 2) {
1163 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1164 return 1;
1165 }
1166 if (argc == 2) {
1167 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1168 } else {
1169 snprintf(buf, sizeof buf, "host:disconnect:");
1170 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001171 tmp = adb_query(buf);
1172 if(tmp) {
1173 printf("%s\n", tmp);
1174 return 0;
1175 } else {
1176 return 1;
1177 }
1178 }
1179
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001180 if (!strcmp(argv[0], "emu")) {
1181 return adb_send_emulator_command(argc, argv);
1182 }
1183
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001184 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001185 int r;
1186 int fd;
1187
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001188 char h = (argv[0][0] == 'h');
1189
1190 if (h) {
1191 printf("\x1b[41;33m");
1192 fflush(stdout);
1193 }
1194
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001195 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001196 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001197 r = interactive_shell();
1198 if (h) {
1199 printf("\x1b[0m");
1200 fflush(stdout);
1201 }
1202 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001203 }
1204
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001205 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001206 argc -= 2;
1207 argv += 2;
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001208 while (argc-- > 0) {
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -07001209 char *quoted = escape_argv(*argv++);
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001210 strncat(buf, " ", sizeof(buf) - 1);
1211 strncat(buf, quoted, sizeof(buf) - 1);
1212 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001213 }
1214
1215 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001216 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001217 fd = adb_connect(buf);
1218 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001219 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001221 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001222 adb_close(fd);
1223 r = 0;
1224 } else {
1225 fprintf(stderr,"error: %s\n", adb_error());
1226 r = -1;
1227 }
1228
1229 if(persist) {
1230 fprintf(stderr,"\n- waiting for device -\n");
1231 adb_sleep_ms(1000);
1232 do_cmd(ttype, serial, "wait-for-device", 0);
1233 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001234 if (h) {
1235 printf("\x1b[0m");
1236 fflush(stdout);
1237 }
JP Abgrall408fa572011-03-16 15:57:42 -07001238 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001239 return r;
1240 }
1241 }
1242 }
1243
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001244 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1245 int exec_in = !strcmp(argv[0], "exec-in");
1246 int fd;
1247
1248 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1249 argc -= 2;
1250 argv += 2;
1251 while (argc-- > 0) {
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -07001252 char *quoted = escape_argv(*argv++);
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001253 strncat(buf, " ", sizeof(buf) - 1);
1254 strncat(buf, quoted, sizeof(buf) - 1);
1255 free(quoted);
1256 }
1257
1258 fd = adb_connect(buf);
1259 if (fd < 0) {
1260 fprintf(stderr, "error: %s\n", adb_error());
1261 return -1;
1262 }
1263
1264 if (exec_in) {
1265 copy_to_file(STDIN_FILENO, fd);
1266 } else {
1267 copy_to_file(fd, STDOUT_FILENO);
1268 }
1269
1270 adb_close(fd);
1271 return 0;
1272 }
1273
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001274 if(!strcmp(argv[0], "kill-server")) {
1275 int fd;
1276 fd = _adb_connect("host:kill");
1277 if(fd == -1) {
1278 fprintf(stderr,"* server not running *\n");
1279 return 1;
1280 }
1281 return 0;
1282 }
1283
Doug Zongker447f0612012-01-09 14:54:53 -08001284 if(!strcmp(argv[0], "sideload")) {
1285 if(argc != 2) return usage();
1286 if(adb_download("sideload", argv[1], 1)) {
1287 return 1;
1288 } else {
1289 return 0;
1290 }
1291 }
1292
Mike Lockwoodff196702009-08-24 15:58:40 -07001293 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001294 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001295 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001296 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001297 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001298 if (!strcmp(argv[0], "reboot-bootloader"))
1299 snprintf(command, sizeof(command), "reboot:bootloader");
1300 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001301 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001302 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001303 snprintf(command, sizeof(command), "%s:", argv[0]);
1304 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001305 if(fd >= 0) {
1306 read_and_dump(fd);
1307 adb_close(fd);
1308 return 0;
1309 }
1310 fprintf(stderr,"error: %s\n", adb_error());
1311 return 1;
1312 }
1313
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001314 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001315 if (argc != 1) return usage();
1316 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001317 return 0;
1318 }
1319
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 /* adb_command() wrapper commands */
1321
1322 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1323 char* service = argv[0];
1324 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1325 if (ttype == kTransportUsb) {
1326 service = "wait-for-usb";
1327 } else if (ttype == kTransportLocal) {
1328 service = "wait-for-local";
1329 } else {
1330 service = "wait-for-any";
1331 }
1332 }
1333
1334 format_host_command(buf, sizeof buf, service, ttype, serial);
1335
1336 if (adb_command(buf)) {
1337 D("failure: %s *\n",adb_error());
1338 fprintf(stderr,"error: %s\n", adb_error());
1339 return 1;
1340 }
1341
1342 /* Allow a command to be run after wait-for-device,
1343 * e.g. 'adb wait-for-device shell'.
1344 */
1345 if(argc > 1) {
1346 argc--;
1347 argv++;
1348 goto top;
1349 }
1350 return 0;
1351 }
1352
David 'Digit' Turner25258692013-03-21 21:07:42 +01001353 if(!strcmp(argv[0], "forward") ||
1354 !strcmp(argv[0], "reverse"))
1355 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001356 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001357 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001358 char remove = 0;
1359 char remove_all = 0;
1360 char list = 0;
1361 char no_rebind = 0;
1362
1363 // Parse options here.
1364 while (argc > 1 && argv[1][0] == '-') {
1365 if (!strcmp(argv[1], "--list"))
1366 list = 1;
1367 else if (!strcmp(argv[1], "--remove"))
1368 remove = 1;
1369 else if (!strcmp(argv[1], "--remove-all"))
1370 remove_all = 1;
1371 else if (!strcmp(argv[1], "--no-rebind"))
1372 no_rebind = 1;
1373 else {
1374 return usage();
1375 }
1376 argc--;
1377 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001378 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001379
1380 // Ensure we can only use one option at a time.
1381 if (list + remove + remove_all + no_rebind > 1) {
1382 return usage();
1383 }
1384
1385 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001386 if (reverse) {
1387 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001388 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001389 if (serial) {
1390 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1391 serial);
1392 } else if (ttype == kTransportUsb) {
1393 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1394 } else if (ttype == kTransportLocal) {
1395 snprintf(host_prefix, sizeof host_prefix, "host-local");
1396 } else {
1397 snprintf(host_prefix, sizeof host_prefix, "host");
1398 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001399 }
1400
1401 // Implement forward --list
1402 if (list) {
1403 if (argc != 1)
1404 return usage();
1405 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1406 char* forwards = adb_query(buf);
1407 if (forwards == NULL) {
1408 fprintf(stderr, "error: %s\n", adb_error());
1409 return 1;
1410 }
1411 printf("%s", forwards);
1412 free(forwards);
1413 return 0;
1414 }
1415
1416 // Implement forward --remove-all
1417 else if (remove_all) {
1418 if (argc != 1)
1419 return usage();
1420 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1421 }
1422
1423 // Implement forward --remove <local>
1424 else if (remove) {
1425 if (argc != 2)
1426 return usage();
1427 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1428 }
1429 // Or implement one of:
1430 // forward <local> <remote>
1431 // forward --no-rebind <local> <remote>
1432 else
1433 {
1434 if (argc != 3)
1435 return usage();
1436 const char* command = no_rebind ? "forward:norebind:" : "forward";
1437 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1438 }
1439
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001440 if(adb_command(buf)) {
1441 fprintf(stderr,"error: %s\n", adb_error());
1442 return 1;
1443 }
1444 return 0;
1445 }
1446
1447 /* do_sync_*() commands */
1448
1449 if(!strcmp(argv[0], "ls")) {
1450 if(argc != 2) return usage();
1451 return do_sync_ls(argv[1]);
1452 }
1453
1454 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001455 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001456 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001457 const char* lpath = NULL, *rpath = NULL;
1458
Lajos Molnar4b35c012013-04-19 12:41:09 -07001459 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001460
1461 if ((lpath != NULL) && (rpath != NULL)) {
1462 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1463 }
1464
1465 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001466 }
1467
1468 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001469 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001470 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001471 const char* rpath = NULL, *lpath = ".";
1472
Lajos Molnar4b35c012013-04-19 12:41:09 -07001473 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001474
1475 if (rpath != NULL) {
Lajos Molnar4b35c012013-04-19 12:41:09 -07001476 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001477 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001478
1479 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001480 }
1481
1482 if(!strcmp(argv[0], "install")) {
1483 if (argc < 2) return usage();
1484 return install_app(ttype, serial, argc, argv);
1485 }
1486
1487 if(!strcmp(argv[0], "uninstall")) {
1488 if (argc < 2) return usage();
1489 return uninstall_app(ttype, serial, argc, argv);
1490 }
1491
1492 if(!strcmp(argv[0], "sync")) {
1493 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001494 int listonly = 0;
1495
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001496 int ret;
1497 if(argc < 2) {
1498 /* No local path was specified. */
1499 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001500 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1501 listonly = 1;
1502 if (argc == 3) {
1503 srcarg = argv[2];
1504 } else {
1505 srcarg = NULL;
1506 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001507 } else if(argc == 2) {
1508 /* A local path or "android"/"data" arg was specified. */
1509 srcarg = argv[1];
1510 } else {
1511 return usage();
1512 }
1513 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1514 if(ret != 0) return usage();
1515
1516 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001517 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001518 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001519 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001520
1521 free(android_srcpath);
1522 free(data_srcpath);
1523 return ret;
1524 }
1525
1526 /* passthrough commands */
1527
1528 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001529 !strcmp(argv[0],"get-serialno") ||
1530 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 {
1532 char *tmp;
1533
1534 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1535 tmp = adb_query(buf);
1536 if(tmp) {
1537 printf("%s\n", tmp);
1538 return 0;
1539 } else {
1540 return 1;
1541 }
1542 }
1543
1544 /* other commands */
1545
1546 if(!strcmp(argv[0],"status-window")) {
1547 status_window(ttype, serial);
1548 return 0;
1549 }
1550
Christopher Tatedb0a8802011-11-30 13:00:33 -08001551 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001552 return logcat(ttype, serial, argc, argv);
1553 }
1554
1555 if(!strcmp(argv[0],"ppp")) {
1556 return ppp(argc, argv);
1557 }
1558
1559 if (!strcmp(argv[0], "start-server")) {
1560 return adb_connect("host:start-server");
1561 }
1562
Christopher Tated2f54152011-04-21 12:53:28 -07001563 if (!strcmp(argv[0], "backup")) {
1564 return backup(argc, argv);
1565 }
1566
Christopher Tate702967a2011-05-17 15:52:54 -07001567 if (!strcmp(argv[0], "restore")) {
1568 return restore(argc, argv);
1569 }
1570
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001571 if (!strcmp(argv[0], "jdwp")) {
1572 int fd = adb_connect("jdwp");
1573 if (fd >= 0) {
1574 read_and_dump(fd);
1575 adb_close(fd);
1576 return 0;
1577 } else {
1578 fprintf(stderr, "error: %s\n", adb_error());
1579 return -1;
1580 }
1581 }
1582
1583 /* "adb /?" is a common idiom under Windows */
1584 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1585 help();
1586 return 0;
1587 }
1588
1589 if(!strcmp(argv[0], "version")) {
1590 version(stdout);
1591 return 0;
1592 }
1593
1594 usage();
1595 return 1;
1596}
1597
1598static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1599{
1600 char *argv[16];
1601 int argc;
1602 va_list ap;
1603
1604 va_start(ap, cmd);
1605 argc = 0;
1606
1607 if (serial) {
1608 argv[argc++] = "-s";
1609 argv[argc++] = serial;
1610 } else if (ttype == kTransportUsb) {
1611 argv[argc++] = "-d";
1612 } else if (ttype == kTransportLocal) {
1613 argv[argc++] = "-e";
1614 }
1615
1616 argv[argc++] = cmd;
1617 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1618 va_end(ap);
1619
1620#if 0
1621 int n;
1622 fprintf(stderr,"argc = %d\n",argc);
1623 for(n = 0; n < argc; n++) {
1624 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1625 }
1626#endif
1627
1628 return adb_commandline(argc, argv);
1629}
1630
1631int find_sync_dirs(const char *srcarg,
1632 char **android_srcdir_out, char **data_srcdir_out)
1633{
1634 char *android_srcdir, *data_srcdir;
1635
1636 if(srcarg == NULL) {
1637 android_srcdir = product_file("system");
1638 data_srcdir = product_file("data");
1639 } else {
1640 /* srcarg may be "data", "system" or NULL.
1641 * if srcarg is NULL, then both data and system are synced
1642 */
1643 if(strcmp(srcarg, "system") == 0) {
1644 android_srcdir = product_file("system");
1645 data_srcdir = NULL;
1646 } else if(strcmp(srcarg, "data") == 0) {
1647 android_srcdir = NULL;
1648 data_srcdir = product_file("data");
1649 } else {
1650 /* It's not "system" or "data".
1651 */
1652 return 1;
1653 }
1654 }
1655
1656 if(android_srcdir_out != NULL)
1657 *android_srcdir_out = android_srcdir;
1658 else
1659 free(android_srcdir);
1660
1661 if(data_srcdir_out != NULL)
1662 *data_srcdir_out = data_srcdir;
1663 else
1664 free(data_srcdir);
1665
1666 return 0;
1667}
1668
1669static int pm_command(transport_type transport, char* serial,
1670 int argc, char** argv)
1671{
1672 char buf[4096];
1673
1674 snprintf(buf, sizeof(buf), "shell:pm");
1675
1676 while(argc-- > 0) {
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -07001677 char *quoted = escape_argv(*argv++);
1678 strncat(buf, " ", sizeof(buf) - 1);
1679 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680 free(quoted);
1681 }
1682
1683 send_shellcommand(transport, serial, buf);
1684 return 0;
1685}
1686
1687int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1688{
1689 /* if the user choose the -k option, we refuse to do it until devices are
1690 out with the option to uninstall the remaining data somehow (adb/ui) */
1691 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1692 {
1693 printf(
1694 "The -k option uninstalls the application while retaining the data/cache.\n"
1695 "At the moment, there is no way to remove the remaining data.\n"
1696 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1697 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1698 return -1;
1699 }
1700
1701 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1702 return pm_command(transport, serial, argc, argv);
1703}
1704
1705static int delete_file(transport_type transport, char* serial, char* filename)
1706{
1707 char buf[4096];
1708 char* quoted;
1709
1710 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkeydcd2f0e2014-06-10 11:31:24 -07001711 quoted = escape_argv(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001712 strncat(buf, quoted, sizeof(buf)-1);
1713 free(quoted);
1714
1715 send_shellcommand(transport, serial, buf);
1716 return 0;
1717}
1718
Kenny Root597ea5b2011-08-05 11:19:45 -07001719static const char* get_basename(const char* filename)
1720{
1721 const char* basename = adb_dirstop(filename);
1722 if (basename) {
1723 basename++;
1724 return basename;
1725 } else {
1726 return filename;
1727 }
1728}
1729
1730static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001731{
1732 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001733
Kenny Root597ea5b2011-08-05 11:19:45 -07001734 if (filename == NULL) {
1735 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001736 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001737
Kenny Root597ea5b2011-08-05 11:19:45 -07001738 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001739 fprintf(stderr, "can't find '%s' to install\n", filename);
1740 return 1;
1741 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001742
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001743 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001744 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001745 return 1;
1746 }
1747
Kenny Root597ea5b2011-08-05 11:19:45 -07001748 return 0;
1749}
1750
1751int install_app(transport_type transport, char* serial, int argc, char** argv)
1752{
1753 static const char *const DATA_DEST = "/data/local/tmp/%s";
1754 static const char *const SD_DEST = "/sdcard/tmp/%s";
1755 const char* where = DATA_DEST;
1756 char apk_dest[PATH_MAX];
1757 char verification_dest[PATH_MAX];
1758 char* apk_file;
1759 char* verification_file = NULL;
1760 int file_arg = -1;
1761 int err;
1762 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001763 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001764
1765 for (i = 1; i < argc; i++) {
1766 if (*argv[i] != '-') {
1767 file_arg = i;
1768 break;
Kenny Roota031a912011-09-23 12:46:39 -07001769 } else if (!strcmp(argv[i], "-i")) {
1770 // Skip the installer package name.
1771 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001772 } else if (!strcmp(argv[i], "-s")) {
1773 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001774 } else if (!strcmp(argv[i], "--algo")) {
1775 verify_apk = 0;
1776 i++;
1777 } else if (!strcmp(argv[i], "--iv")) {
1778 verify_apk = 0;
1779 i++;
1780 } else if (!strcmp(argv[i], "--key")) {
1781 verify_apk = 0;
1782 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001783 } else if (!strcmp(argv[i], "--abi")) {
1784 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001785 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001786 }
1787
Kenny Root597ea5b2011-08-05 11:19:45 -07001788 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001789 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001790 return 1;
1791 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001792 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001793 return 1;
1794 }
1795
1796 apk_file = argv[file_arg];
1797
1798 if (file_arg != argc - 1) {
1799 verification_file = argv[file_arg + 1];
1800 }
1801
1802 if (check_file(apk_file) || check_file(verification_file)) {
1803 return 1;
1804 }
1805
1806 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1807 if (verification_file != NULL) {
1808 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1809
1810 if (!strcmp(apk_dest, verification_dest)) {
1811 fprintf(stderr, "APK and verification file can't have the same name\n");
1812 return 1;
1813 }
1814 }
1815
Mark Lindner76f2a932014-03-11 17:55:59 -07001816 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001817 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001818 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001819 } else {
1820 argv[file_arg] = apk_dest; /* destination name, not source location */
1821 }
1822
1823 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001824 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1825 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001826 if (err) {
1827 goto cleanup_apk;
1828 } else {
1829 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1830 }
1831 }
1832
1833 pm_command(transport, serial, argc, argv);
1834
Kenny Root60733e92012-03-26 16:14:02 -07001835cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001836 if (verification_file != NULL) {
1837 delete_file(transport, serial, verification_dest);
1838 }
1839
Kenny Root597ea5b2011-08-05 11:19:45 -07001840 delete_file(transport, serial, apk_dest);
1841
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001842 return err;
1843}