blob: 1ba60499c0bbfc1b85283f19bafeea7a300eb931 [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
547/** duplicate string and quote all \ " ( ) chars + space character. */
548static char *
549dupAndQuote(const char *s)
550{
551 const char *ts;
552 size_t alloc_len;
553 char *ret;
554 char *dest;
555
556 ts = s;
557
558 alloc_len = 0;
559
560 for( ;*ts != '\0'; ts++) {
561 alloc_len++;
562 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
563 alloc_len++;
564 }
565 }
566
567 ret = (char *)malloc(alloc_len + 1);
568
569 ts = s;
570 dest = ret;
571
572 for ( ;*ts != '\0'; ts++) {
573 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
574 *dest++ = '\\';
575 }
576
577 *dest++ = *ts;
578 }
579
580 *dest++ = '\0';
581
582 return ret;
583}
584
585/**
586 * Run ppp in "notty" mode against a resource listed as the first parameter
587 * eg:
588 *
589 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
590 *
591 */
592int ppp(int argc, char **argv)
593{
594#ifdef HAVE_WIN32_PROC
595 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
596 return -1;
597#else
598 char *adb_service_name;
599 pid_t pid;
600 int fd;
601
602 if (argc < 2) {
603 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
604 argv[0]);
605
606 return 1;
607 }
608
609 adb_service_name = argv[1];
610
611 fd = adb_connect(adb_service_name);
612
613 if(fd < 0) {
614 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
615 adb_service_name, adb_error());
616 return 1;
617 }
618
619 pid = fork();
620
621 if (pid < 0) {
622 perror("from fork()");
623 return 1;
624 } else if (pid == 0) {
625 int err;
626 int i;
627 const char **ppp_args;
628
629 // copy args
630 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
631 ppp_args[0] = "pppd";
632 for (i = 2 ; i < argc ; i++) {
633 //argv[2] and beyond become ppp_args[1] and beyond
634 ppp_args[i - 1] = argv[i];
635 }
636 ppp_args[i-1] = NULL;
637
638 // child side
639
640 dup2(fd, STDIN_FILENO);
641 dup2(fd, STDOUT_FILENO);
642 adb_close(STDERR_FILENO);
643 adb_close(fd);
644
645 err = execvp("pppd", (char * const *)ppp_args);
646
647 if (err < 0) {
648 perror("execing pppd");
649 }
650 exit(-1);
651 } else {
652 // parent side
653
654 adb_close(fd);
655 return 0;
656 }
657#endif /* !HAVE_WIN32_PROC */
658}
659
660static int send_shellcommand(transport_type transport, char* serial, char* buf)
661{
662 int fd, ret;
663
664 for(;;) {
665 fd = adb_connect(buf);
666 if(fd >= 0)
667 break;
668 fprintf(stderr,"- waiting for device -\n");
669 adb_sleep_ms(1000);
670 do_cmd(transport, serial, "wait-for-device", 0);
671 }
672
673 read_and_dump(fd);
674 ret = adb_close(fd);
675 if (ret)
676 perror("close");
677
678 return ret;
679}
680
681static int logcat(transport_type transport, char* serial, int argc, char **argv)
682{
683 char buf[4096];
684
685 char *log_tags;
686 char *quoted_log_tags;
687
688 log_tags = getenv("ANDROID_LOG_TAGS");
689 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
690
691 snprintf(buf, sizeof(buf),
692 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
693 quoted_log_tags);
694
695 free(quoted_log_tags);
696
Christopher Tatedb0a8802011-11-30 13:00:33 -0800697 if (!strcmp(argv[0],"longcat")) {
698 strncat(buf, " -v long", sizeof(buf)-1);
699 }
700
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 argc -= 1;
702 argv += 1;
703 while(argc-- > 0) {
704 char *quoted;
705
706 quoted = dupAndQuote (*argv++);
707
708 strncat(buf, " ", sizeof(buf)-1);
709 strncat(buf, quoted, sizeof(buf)-1);
710 free(quoted);
711 }
712
713 send_shellcommand(transport, serial, buf);
714 return 0;
715}
716
Mark Salyzyn60299df2014-04-30 09:10:31 -0700717static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800718{
719 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700720 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800721
722 for(;;) {
723 x = adb_dirstart(x);
724 if(x == 0) return 0;
725 *x = 0;
726 ret = adb_mkdir(path, 0775);
727 *x = OS_PATH_SEPARATOR;
728 if((ret < 0) && (errno != EEXIST)) {
729 return ret;
730 }
731 x++;
732 }
733 return 0;
734}
735
Christopher Tated2f54152011-04-21 12:53:28 -0700736static int backup(int argc, char** argv) {
737 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800738 char default_name[32];
739 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700740 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700741 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700742
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700743 /* find, extract, and use any -f argument */
744 for (i = 1; i < argc; i++) {
745 if (!strcmp("-f", argv[i])) {
746 if (i == argc-1) {
747 fprintf(stderr, "adb: -f passed with no filename\n");
748 return usage();
749 }
750 filename = argv[i+1];
751 for (j = i+2; j <= argc; ) {
752 argv[i++] = argv[j++];
753 }
754 argc -= 2;
755 argv[argc] = NULL;
756 }
Christopher Tated2f54152011-04-21 12:53:28 -0700757 }
758
Christopher Tatebb86bc52011-08-22 17:12:08 -0700759 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
760 if (argc < 2) return usage();
761
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800762 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700763 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800764 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700765 if (outFd < 0) {
766 fprintf(stderr, "adb: unable to open file %s\n", filename);
767 return -1;
768 }
769
770 snprintf(buf, sizeof(buf), "backup");
771 for (argc--, argv++; argc; argc--, argv++) {
772 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
773 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
774 }
775
776 D("backup. filename=%s buf=%s\n", filename, buf);
777 fd = adb_connect(buf);
778 if (fd < 0) {
779 fprintf(stderr, "adb: unable to connect for backup\n");
780 adb_close(outFd);
781 return -1;
782 }
783
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800784 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700785 copy_to_file(fd, outFd);
786
787 adb_close(fd);
788 adb_close(outFd);
789 return 0;
790}
791
Christopher Tate702967a2011-05-17 15:52:54 -0700792static int restore(int argc, char** argv) {
793 const char* filename;
794 int fd, tarFd;
795
796 if (argc != 2) return usage();
797
798 filename = argv[1];
799 tarFd = adb_open(filename, O_RDONLY);
800 if (tarFd < 0) {
801 fprintf(stderr, "adb: unable to open file %s\n", filename);
802 return -1;
803 }
804
805 fd = adb_connect("restore:");
806 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700807 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700808 adb_close(tarFd);
809 return -1;
810 }
811
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800812 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700813 copy_to_file(tarFd, fd);
814
815 adb_close(fd);
816 adb_close(tarFd);
817 return 0;
818}
819
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800820#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
821static int top_works(const char *top)
822{
823 if (top != NULL && adb_is_absolute_host_path(top)) {
824 char path_buf[PATH_MAX];
825 snprintf(path_buf, sizeof(path_buf),
826 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
827 return access(path_buf, F_OK) == 0;
828 }
829 return 0;
830}
831
832static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
833{
834 strcpy(path_buf, indir);
835 while (1) {
836 if (top_works(path_buf)) {
837 return path_buf;
838 }
839 char *s = adb_dirstop(path_buf);
840 if (s != NULL) {
841 *s = '\0';
842 } else {
843 path_buf[0] = '\0';
844 return NULL;
845 }
846 }
847}
848
849static char *find_top(char path_buf[PATH_MAX])
850{
851 char *top = getenv("ANDROID_BUILD_TOP");
852 if (top != NULL && top[0] != '\0') {
853 if (!top_works(top)) {
854 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
855 return NULL;
856 }
857 } else {
858 top = getenv("TOP");
859 if (top != NULL && top[0] != '\0') {
860 if (!top_works(top)) {
861 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
862 return NULL;
863 }
864 } else {
865 top = NULL;
866 }
867 }
868
869 if (top != NULL) {
870 /* The environment pointed to a top directory that works.
871 */
872 strcpy(path_buf, top);
873 return path_buf;
874 }
875
876 /* The environment didn't help. Walk up the tree from the CWD
877 * to see if we can find the top.
878 */
879 char dir[PATH_MAX];
880 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
881 if (top == NULL) {
882 /* If the CWD isn't under a good-looking top, see if the
883 * executable is.
884 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100885 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800886 top = find_top_from(dir, path_buf);
887 }
888 return top;
889}
890
891/* <hint> may be:
892 * - A simple product name
893 * e.g., "sooner"
894TODO: debug? sooner-debug, sooner:debug?
895 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
896 * e.g., "out/target/product/sooner"
897 * - An absolute path to the PRODUCT_OUT dir
898 * e.g., "/src/device/out/target/product/sooner"
899 *
900 * Given <hint>, try to construct an absolute path to the
901 * ANDROID_PRODUCT_OUT dir.
902 */
903static const char *find_product_out_path(const char *hint)
904{
905 static char path_buf[PATH_MAX];
906
907 if (hint == NULL || hint[0] == '\0') {
908 return NULL;
909 }
910
911 /* If it's already absolute, don't bother doing any work.
912 */
913 if (adb_is_absolute_host_path(hint)) {
914 strcpy(path_buf, hint);
915 return path_buf;
916 }
917
918 /* If there are any slashes in it, assume it's a relative path;
919 * make it absolute.
920 */
921 if (adb_dirstart(hint) != NULL) {
922 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
923 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
924 return NULL;
925 }
926 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
927 fprintf(stderr, "adb: Couldn't assemble path\n");
928 return NULL;
929 }
930 strcat(path_buf, OS_PATH_SEPARATOR_STR);
931 strcat(path_buf, hint);
932 return path_buf;
933 }
934
935 /* It's a string without any slashes. Try to do something with it.
936 *
937 * Try to find the root of the build tree, and build a PRODUCT_OUT
938 * path from there.
939 */
940 char top_buf[PATH_MAX];
941 const char *top = find_top(top_buf);
942 if (top == NULL) {
943 fprintf(stderr, "adb: Couldn't find top of build tree\n");
944 return NULL;
945 }
946//TODO: if we have a way to indicate debug, look in out/debug/target/...
947 snprintf(path_buf, sizeof(path_buf),
948 "%s" OS_PATH_SEPARATOR_STR
949 "out" OS_PATH_SEPARATOR_STR
950 "target" OS_PATH_SEPARATOR_STR
951 "product" OS_PATH_SEPARATOR_STR
952 "%s", top_buf, hint);
953 if (access(path_buf, F_OK) < 0) {
954 fprintf(stderr, "adb: Couldn't find a product dir "
955 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
956 return NULL;
957 }
958 return path_buf;
959}
960
Lajos Molnar4b35c012013-04-19 12:41:09 -0700961static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
962 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700963 *show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -0700964 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700965
Lajos Molnar4b35c012013-04-19 12:41:09 -0700966 while (narg > 0) {
967 if (!strcmp(*arg, "-p")) {
968 *show_progress = 1;
969 } else if (!strcmp(*arg, "-a")) {
970 *copy_attrs = 1;
971 } else {
972 break;
973 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700974 ++arg;
975 --narg;
976 }
977
978 if (narg > 0) {
979 *path1 = *arg;
980 ++arg;
981 --narg;
982 }
983
984 if (narg > 0) {
985 *path2 = *arg;
986 }
987}
988
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800989int adb_commandline(int argc, char **argv)
990{
991 char buf[4096];
992 int no_daemon = 0;
993 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100994 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800995 int persist = 0;
996 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800997 transport_type ttype = kTransportAny;
998 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100999 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000
1001 /* If defined, this should be an absolute path to
1002 * the directory containing all of the various system images
1003 * for a particular product. If not defined, and the adb
1004 * command requires this information, then the user must
1005 * specify the path using "-p".
1006 */
1007 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1008 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1009 gProductOutPath = NULL;
1010 }
1011 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1012
Nick Pellydb449262009-05-07 12:48:03 -07001013 serial = getenv("ANDROID_SERIAL");
1014
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001015 /* Validate and assign the server port */
1016 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1017 int server_port = DEFAULT_ADB_PORT;
1018 if (server_port_str && strlen(server_port_str) > 0) {
1019 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001020 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001021 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001022 "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 +01001023 server_port_str);
1024 return usage();
1025 }
1026 }
1027
1028 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001029 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001030 if(!strcmp(argv[0],"server")) {
1031 is_server = 1;
1032 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001033 no_daemon = 1;
1034 } else if (!strcmp(argv[0], "fork-server")) {
1035 /* this is a special flag used only when the ADB client launches the ADB Server */
1036 is_daemon = 1;
1037 } else if(!strcmp(argv[0],"persist")) {
1038 persist = 1;
1039 } else if(!strncmp(argv[0], "-p", 2)) {
1040 const char *product = NULL;
1041 if (argv[0][2] == '\0') {
1042 if (argc < 2) return usage();
1043 product = argv[1];
1044 argc--;
1045 argv++;
1046 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001047 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001048 }
1049 gProductOutPath = find_product_out_path(product);
1050 if (gProductOutPath == NULL) {
1051 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1052 product);
1053 return usage();
1054 }
1055 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1056 if (isdigit(argv[0][2])) {
1057 serial = argv[0] + 2;
1058 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001059 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001060 serial = argv[1];
1061 argc--;
1062 argv++;
1063 }
1064 } else if (!strcmp(argv[0],"-d")) {
1065 ttype = kTransportUsb;
1066 } else if (!strcmp(argv[0],"-e")) {
1067 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001068 } else if (!strcmp(argv[0],"-a")) {
1069 gListenAll = 1;
1070 } else if(!strncmp(argv[0], "-H", 2)) {
1071 const char *hostname = NULL;
1072 if (argv[0][2] == '\0') {
1073 if (argc < 2) return usage();
1074 hostname = argv[1];
1075 argc--;
1076 argv++;
1077 } else {
1078 hostname = argv[0] + 2;
1079 }
1080 adb_set_tcp_name(hostname);
1081
1082 } else if(!strncmp(argv[0], "-P", 2)) {
1083 if (argv[0][2] == '\0') {
1084 if (argc < 2) return usage();
1085 server_port_str = argv[1];
1086 argc--;
1087 argv++;
1088 } else {
1089 server_port_str = argv[0] + 2;
1090 }
1091 if (strlen(server_port_str) > 0) {
1092 server_port = (int) strtol(server_port_str, NULL, 0);
1093 if (server_port <= 0 || server_port > 65535) {
1094 fprintf(stderr,
1095 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1096 server_port_str);
1097 return usage();
1098 }
1099 } else {
1100 fprintf(stderr,
1101 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1102 return usage();
1103 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104 } else {
1105 /* out of recognized modifiers and flags */
1106 break;
1107 }
1108 argc--;
1109 argv++;
1110 }
1111
1112 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001113 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001114
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001115 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001116 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001117 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001118 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001119 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001120 }
1121 if(r) {
1122 fprintf(stderr,"* could not start server *\n");
1123 }
1124 return r;
1125 }
1126
1127top:
1128 if(argc == 0) {
1129 return usage();
1130 }
1131
1132 /* adb_connect() commands */
1133
1134 if(!strcmp(argv[0], "devices")) {
1135 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001136 char *listopt;
1137 if (argc < 2)
1138 listopt = "";
1139 else if (argc == 2 && !strcmp(argv[1], "-l"))
1140 listopt = argv[1];
1141 else {
1142 fprintf(stderr, "Usage: adb devices [-l]\n");
1143 return 1;
1144 }
1145 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001146 tmp = adb_query(buf);
1147 if(tmp) {
1148 printf("List of devices attached \n");
1149 printf("%s\n", tmp);
1150 return 0;
1151 } else {
1152 return 1;
1153 }
1154 }
1155
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001156 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001157 char *tmp;
1158 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001159 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001160 return 1;
1161 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001162 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1163 tmp = adb_query(buf);
1164 if(tmp) {
1165 printf("%s\n", tmp);
1166 return 0;
1167 } else {
1168 return 1;
1169 }
1170 }
1171
1172 if(!strcmp(argv[0], "disconnect")) {
1173 char *tmp;
1174 if (argc > 2) {
1175 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1176 return 1;
1177 }
1178 if (argc == 2) {
1179 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1180 } else {
1181 snprintf(buf, sizeof buf, "host:disconnect:");
1182 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001183 tmp = adb_query(buf);
1184 if(tmp) {
1185 printf("%s\n", tmp);
1186 return 0;
1187 } else {
1188 return 1;
1189 }
1190 }
1191
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 if (!strcmp(argv[0], "emu")) {
1193 return adb_send_emulator_command(argc, argv);
1194 }
1195
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001196 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001197 int r;
1198 int fd;
1199
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001200 char h = (argv[0][0] == 'h');
1201
1202 if (h) {
1203 printf("\x1b[41;33m");
1204 fflush(stdout);
1205 }
1206
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001207 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001208 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001209 r = interactive_shell();
1210 if (h) {
1211 printf("\x1b[0m");
1212 fflush(stdout);
1213 }
1214 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001215 }
1216
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001217 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001218 argc -= 2;
1219 argv += 2;
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001220 while (argc-- > 0) {
1221 char *quoted = dupAndQuote(*argv++);
1222 strncat(buf, " ", sizeof(buf) - 1);
1223 strncat(buf, quoted, sizeof(buf) - 1);
1224 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001225 }
1226
1227 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001228 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001229 fd = adb_connect(buf);
1230 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001231 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001232 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001233 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001234 adb_close(fd);
1235 r = 0;
1236 } else {
1237 fprintf(stderr,"error: %s\n", adb_error());
1238 r = -1;
1239 }
1240
1241 if(persist) {
1242 fprintf(stderr,"\n- waiting for device -\n");
1243 adb_sleep_ms(1000);
1244 do_cmd(ttype, serial, "wait-for-device", 0);
1245 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001246 if (h) {
1247 printf("\x1b[0m");
1248 fflush(stdout);
1249 }
JP Abgrall408fa572011-03-16 15:57:42 -07001250 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001251 return r;
1252 }
1253 }
1254 }
1255
Jeff Sharkeyeb979872014-05-26 18:30:43 -07001256 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1257 int exec_in = !strcmp(argv[0], "exec-in");
1258 int fd;
1259
1260 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1261 argc -= 2;
1262 argv += 2;
1263 while (argc-- > 0) {
1264 char *quoted = dupAndQuote(*argv++);
1265 strncat(buf, " ", sizeof(buf) - 1);
1266 strncat(buf, quoted, sizeof(buf) - 1);
1267 free(quoted);
1268 }
1269
1270 fd = adb_connect(buf);
1271 if (fd < 0) {
1272 fprintf(stderr, "error: %s\n", adb_error());
1273 return -1;
1274 }
1275
1276 if (exec_in) {
1277 copy_to_file(STDIN_FILENO, fd);
1278 } else {
1279 copy_to_file(fd, STDOUT_FILENO);
1280 }
1281
1282 adb_close(fd);
1283 return 0;
1284 }
1285
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001286 if(!strcmp(argv[0], "kill-server")) {
1287 int fd;
1288 fd = _adb_connect("host:kill");
1289 if(fd == -1) {
1290 fprintf(stderr,"* server not running *\n");
1291 return 1;
1292 }
1293 return 0;
1294 }
1295
Doug Zongker447f0612012-01-09 14:54:53 -08001296 if(!strcmp(argv[0], "sideload")) {
1297 if(argc != 2) return usage();
1298 if(adb_download("sideload", argv[1], 1)) {
1299 return 1;
1300 } else {
1301 return 0;
1302 }
1303 }
1304
Mike Lockwoodff196702009-08-24 15:58:40 -07001305 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001306 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001307 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001308 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001309 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001310 if (!strcmp(argv[0], "reboot-bootloader"))
1311 snprintf(command, sizeof(command), "reboot:bootloader");
1312 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001313 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001314 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001315 snprintf(command, sizeof(command), "%s:", argv[0]);
1316 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001317 if(fd >= 0) {
1318 read_and_dump(fd);
1319 adb_close(fd);
1320 return 0;
1321 }
1322 fprintf(stderr,"error: %s\n", adb_error());
1323 return 1;
1324 }
1325
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001326 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001327 if (argc != 1) return usage();
1328 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001329 return 0;
1330 }
1331
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001332 /* adb_command() wrapper commands */
1333
1334 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1335 char* service = argv[0];
1336 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1337 if (ttype == kTransportUsb) {
1338 service = "wait-for-usb";
1339 } else if (ttype == kTransportLocal) {
1340 service = "wait-for-local";
1341 } else {
1342 service = "wait-for-any";
1343 }
1344 }
1345
1346 format_host_command(buf, sizeof buf, service, ttype, serial);
1347
1348 if (adb_command(buf)) {
1349 D("failure: %s *\n",adb_error());
1350 fprintf(stderr,"error: %s\n", adb_error());
1351 return 1;
1352 }
1353
1354 /* Allow a command to be run after wait-for-device,
1355 * e.g. 'adb wait-for-device shell'.
1356 */
1357 if(argc > 1) {
1358 argc--;
1359 argv++;
1360 goto top;
1361 }
1362 return 0;
1363 }
1364
David 'Digit' Turner25258692013-03-21 21:07:42 +01001365 if(!strcmp(argv[0], "forward") ||
1366 !strcmp(argv[0], "reverse"))
1367 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001368 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001369 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001370 char remove = 0;
1371 char remove_all = 0;
1372 char list = 0;
1373 char no_rebind = 0;
1374
1375 // Parse options here.
1376 while (argc > 1 && argv[1][0] == '-') {
1377 if (!strcmp(argv[1], "--list"))
1378 list = 1;
1379 else if (!strcmp(argv[1], "--remove"))
1380 remove = 1;
1381 else if (!strcmp(argv[1], "--remove-all"))
1382 remove_all = 1;
1383 else if (!strcmp(argv[1], "--no-rebind"))
1384 no_rebind = 1;
1385 else {
1386 return usage();
1387 }
1388 argc--;
1389 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001391
1392 // Ensure we can only use one option at a time.
1393 if (list + remove + remove_all + no_rebind > 1) {
1394 return usage();
1395 }
1396
1397 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001398 if (reverse) {
1399 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001400 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001401 if (serial) {
1402 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1403 serial);
1404 } else if (ttype == kTransportUsb) {
1405 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1406 } else if (ttype == kTransportLocal) {
1407 snprintf(host_prefix, sizeof host_prefix, "host-local");
1408 } else {
1409 snprintf(host_prefix, sizeof host_prefix, "host");
1410 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001411 }
1412
1413 // Implement forward --list
1414 if (list) {
1415 if (argc != 1)
1416 return usage();
1417 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1418 char* forwards = adb_query(buf);
1419 if (forwards == NULL) {
1420 fprintf(stderr, "error: %s\n", adb_error());
1421 return 1;
1422 }
1423 printf("%s", forwards);
1424 free(forwards);
1425 return 0;
1426 }
1427
1428 // Implement forward --remove-all
1429 else if (remove_all) {
1430 if (argc != 1)
1431 return usage();
1432 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1433 }
1434
1435 // Implement forward --remove <local>
1436 else if (remove) {
1437 if (argc != 2)
1438 return usage();
1439 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1440 }
1441 // Or implement one of:
1442 // forward <local> <remote>
1443 // forward --no-rebind <local> <remote>
1444 else
1445 {
1446 if (argc != 3)
1447 return usage();
1448 const char* command = no_rebind ? "forward:norebind:" : "forward";
1449 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1450 }
1451
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001452 if(adb_command(buf)) {
1453 fprintf(stderr,"error: %s\n", adb_error());
1454 return 1;
1455 }
1456 return 0;
1457 }
1458
1459 /* do_sync_*() commands */
1460
1461 if(!strcmp(argv[0], "ls")) {
1462 if(argc != 2) return usage();
1463 return do_sync_ls(argv[1]);
1464 }
1465
1466 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001467 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001468 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001469 const char* lpath = NULL, *rpath = NULL;
1470
Lajos Molnar4b35c012013-04-19 12:41:09 -07001471 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001472
1473 if ((lpath != NULL) && (rpath != NULL)) {
1474 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1475 }
1476
1477 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001478 }
1479
1480 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001481 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001482 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001483 const char* rpath = NULL, *lpath = ".";
1484
Lajos Molnar4b35c012013-04-19 12:41:09 -07001485 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001486
1487 if (rpath != NULL) {
Lajos Molnar4b35c012013-04-19 12:41:09 -07001488 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001489 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001490
1491 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001492 }
1493
1494 if(!strcmp(argv[0], "install")) {
1495 if (argc < 2) return usage();
1496 return install_app(ttype, serial, argc, argv);
1497 }
1498
1499 if(!strcmp(argv[0], "uninstall")) {
1500 if (argc < 2) return usage();
1501 return uninstall_app(ttype, serial, argc, argv);
1502 }
1503
1504 if(!strcmp(argv[0], "sync")) {
1505 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001506 int listonly = 0;
1507
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001508 int ret;
1509 if(argc < 2) {
1510 /* No local path was specified. */
1511 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001512 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1513 listonly = 1;
1514 if (argc == 3) {
1515 srcarg = argv[2];
1516 } else {
1517 srcarg = NULL;
1518 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001519 } else if(argc == 2) {
1520 /* A local path or "android"/"data" arg was specified. */
1521 srcarg = argv[1];
1522 } else {
1523 return usage();
1524 }
1525 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1526 if(ret != 0) return usage();
1527
1528 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001529 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001530 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001531 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001532
1533 free(android_srcpath);
1534 free(data_srcpath);
1535 return ret;
1536 }
1537
1538 /* passthrough commands */
1539
1540 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001541 !strcmp(argv[0],"get-serialno") ||
1542 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001543 {
1544 char *tmp;
1545
1546 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1547 tmp = adb_query(buf);
1548 if(tmp) {
1549 printf("%s\n", tmp);
1550 return 0;
1551 } else {
1552 return 1;
1553 }
1554 }
1555
1556 /* other commands */
1557
1558 if(!strcmp(argv[0],"status-window")) {
1559 status_window(ttype, serial);
1560 return 0;
1561 }
1562
Christopher Tatedb0a8802011-11-30 13:00:33 -08001563 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001564 return logcat(ttype, serial, argc, argv);
1565 }
1566
1567 if(!strcmp(argv[0],"ppp")) {
1568 return ppp(argc, argv);
1569 }
1570
1571 if (!strcmp(argv[0], "start-server")) {
1572 return adb_connect("host:start-server");
1573 }
1574
Christopher Tated2f54152011-04-21 12:53:28 -07001575 if (!strcmp(argv[0], "backup")) {
1576 return backup(argc, argv);
1577 }
1578
Christopher Tate702967a2011-05-17 15:52:54 -07001579 if (!strcmp(argv[0], "restore")) {
1580 return restore(argc, argv);
1581 }
1582
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001583 if (!strcmp(argv[0], "jdwp")) {
1584 int fd = adb_connect("jdwp");
1585 if (fd >= 0) {
1586 read_and_dump(fd);
1587 adb_close(fd);
1588 return 0;
1589 } else {
1590 fprintf(stderr, "error: %s\n", adb_error());
1591 return -1;
1592 }
1593 }
1594
1595 /* "adb /?" is a common idiom under Windows */
1596 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1597 help();
1598 return 0;
1599 }
1600
1601 if(!strcmp(argv[0], "version")) {
1602 version(stdout);
1603 return 0;
1604 }
1605
1606 usage();
1607 return 1;
1608}
1609
1610static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1611{
1612 char *argv[16];
1613 int argc;
1614 va_list ap;
1615
1616 va_start(ap, cmd);
1617 argc = 0;
1618
1619 if (serial) {
1620 argv[argc++] = "-s";
1621 argv[argc++] = serial;
1622 } else if (ttype == kTransportUsb) {
1623 argv[argc++] = "-d";
1624 } else if (ttype == kTransportLocal) {
1625 argv[argc++] = "-e";
1626 }
1627
1628 argv[argc++] = cmd;
1629 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1630 va_end(ap);
1631
1632#if 0
1633 int n;
1634 fprintf(stderr,"argc = %d\n",argc);
1635 for(n = 0; n < argc; n++) {
1636 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1637 }
1638#endif
1639
1640 return adb_commandline(argc, argv);
1641}
1642
1643int find_sync_dirs(const char *srcarg,
1644 char **android_srcdir_out, char **data_srcdir_out)
1645{
1646 char *android_srcdir, *data_srcdir;
1647
1648 if(srcarg == NULL) {
1649 android_srcdir = product_file("system");
1650 data_srcdir = product_file("data");
1651 } else {
1652 /* srcarg may be "data", "system" or NULL.
1653 * if srcarg is NULL, then both data and system are synced
1654 */
1655 if(strcmp(srcarg, "system") == 0) {
1656 android_srcdir = product_file("system");
1657 data_srcdir = NULL;
1658 } else if(strcmp(srcarg, "data") == 0) {
1659 android_srcdir = NULL;
1660 data_srcdir = product_file("data");
1661 } else {
1662 /* It's not "system" or "data".
1663 */
1664 return 1;
1665 }
1666 }
1667
1668 if(android_srcdir_out != NULL)
1669 *android_srcdir_out = android_srcdir;
1670 else
1671 free(android_srcdir);
1672
1673 if(data_srcdir_out != NULL)
1674 *data_srcdir_out = data_srcdir;
1675 else
1676 free(data_srcdir);
1677
1678 return 0;
1679}
1680
1681static int pm_command(transport_type transport, char* serial,
1682 int argc, char** argv)
1683{
1684 char buf[4096];
1685
1686 snprintf(buf, sizeof(buf), "shell:pm");
1687
1688 while(argc-- > 0) {
1689 char *quoted;
1690
1691 quoted = dupAndQuote(*argv++);
1692
1693 strncat(buf, " ", sizeof(buf)-1);
1694 strncat(buf, quoted, sizeof(buf)-1);
1695 free(quoted);
1696 }
1697
1698 send_shellcommand(transport, serial, buf);
1699 return 0;
1700}
1701
1702int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1703{
1704 /* if the user choose the -k option, we refuse to do it until devices are
1705 out with the option to uninstall the remaining data somehow (adb/ui) */
1706 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1707 {
1708 printf(
1709 "The -k option uninstalls the application while retaining the data/cache.\n"
1710 "At the moment, there is no way to remove the remaining data.\n"
1711 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1712 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1713 return -1;
1714 }
1715
1716 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1717 return pm_command(transport, serial, argc, argv);
1718}
1719
1720static int delete_file(transport_type transport, char* serial, char* filename)
1721{
1722 char buf[4096];
1723 char* quoted;
1724
1725 snprintf(buf, sizeof(buf), "shell:rm ");
1726 quoted = dupAndQuote(filename);
1727 strncat(buf, quoted, sizeof(buf)-1);
1728 free(quoted);
1729
1730 send_shellcommand(transport, serial, buf);
1731 return 0;
1732}
1733
Kenny Root597ea5b2011-08-05 11:19:45 -07001734static const char* get_basename(const char* filename)
1735{
1736 const char* basename = adb_dirstop(filename);
1737 if (basename) {
1738 basename++;
1739 return basename;
1740 } else {
1741 return filename;
1742 }
1743}
1744
1745static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001746{
1747 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001748
Kenny Root597ea5b2011-08-05 11:19:45 -07001749 if (filename == NULL) {
1750 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001751 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001752
Kenny Root597ea5b2011-08-05 11:19:45 -07001753 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001754 fprintf(stderr, "can't find '%s' to install\n", filename);
1755 return 1;
1756 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001757
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001758 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001759 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001760 return 1;
1761 }
1762
Kenny Root597ea5b2011-08-05 11:19:45 -07001763 return 0;
1764}
1765
1766int install_app(transport_type transport, char* serial, int argc, char** argv)
1767{
1768 static const char *const DATA_DEST = "/data/local/tmp/%s";
1769 static const char *const SD_DEST = "/sdcard/tmp/%s";
1770 const char* where = DATA_DEST;
1771 char apk_dest[PATH_MAX];
1772 char verification_dest[PATH_MAX];
1773 char* apk_file;
1774 char* verification_file = NULL;
1775 int file_arg = -1;
1776 int err;
1777 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001778 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001779
1780 for (i = 1; i < argc; i++) {
1781 if (*argv[i] != '-') {
1782 file_arg = i;
1783 break;
Kenny Roota031a912011-09-23 12:46:39 -07001784 } else if (!strcmp(argv[i], "-i")) {
1785 // Skip the installer package name.
1786 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001787 } else if (!strcmp(argv[i], "-s")) {
1788 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001789 } else if (!strcmp(argv[i], "--algo")) {
1790 verify_apk = 0;
1791 i++;
1792 } else if (!strcmp(argv[i], "--iv")) {
1793 verify_apk = 0;
1794 i++;
1795 } else if (!strcmp(argv[i], "--key")) {
1796 verify_apk = 0;
1797 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001798 } else if (!strcmp(argv[i], "--abi")) {
1799 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001800 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001801 }
1802
Kenny Root597ea5b2011-08-05 11:19:45 -07001803 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001804 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001805 return 1;
1806 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001807 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001808 return 1;
1809 }
1810
1811 apk_file = argv[file_arg];
1812
1813 if (file_arg != argc - 1) {
1814 verification_file = argv[file_arg + 1];
1815 }
1816
1817 if (check_file(apk_file) || check_file(verification_file)) {
1818 return 1;
1819 }
1820
1821 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1822 if (verification_file != NULL) {
1823 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1824
1825 if (!strcmp(apk_dest, verification_dest)) {
1826 fprintf(stderr, "APK and verification file can't have the same name\n");
1827 return 1;
1828 }
1829 }
1830
Mark Lindner76f2a932014-03-11 17:55:59 -07001831 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001832 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001833 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001834 } else {
1835 argv[file_arg] = apk_dest; /* destination name, not source location */
1836 }
1837
1838 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001839 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1840 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001841 if (err) {
1842 goto cleanup_apk;
1843 } else {
1844 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1845 }
1846 }
1847
1848 pm_command(transport, serial, argc, argv);
1849
Kenny Root60733e92012-03-26 16:14:02 -07001850cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001851 if (verification_file != NULL) {
1852 delete_file(transport, serial, verification_dest);
1853 }
1854
Kenny Root597ea5b2011-08-05 11:19:45 -07001855 delete_file(transport, serial, apk_dest);
1856
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001857 return err;
1858}