blob: e0345a82f6e5cdb8c5915026de4bceb588ab3334 [file] [log] [blame]
The Android Open Source Project9ca14dc2009-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 Project9ca14dc2009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov857f17a2009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-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 Gumbel411775c2012-11-14 10:16:17 -080049extern int gListenAll;
The Android Open Source Project9ca14dc2009-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 Gumbel411775c2012-11-14 10:16:17 -080084 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Project9ca14dc2009-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 Anderson6dfaf4b2012-04-20 11:21:14 -070089 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson27042382012-05-30 18:11:27 -070090 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughesec424ad2009-10-07 15:38:53 -070091 " environment variable.\n"
The Android Open Source Project9ca14dc2009-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 Gumbel411775c2012-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 Anderson6dfaf4b2012-04-20 11:21:14 -0700100 " devices [-l] - list all connected devices\n"
Scott Anderson27042382012-05-30 18:11:27 -0700101 " ('-l' will also list device qualifiers)\n"
Mike Lockwood01c2c302010-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-Fischerc3e82b82011-04-26 12:46:05 +0200106 " Using this command with no additional arguments\n"
Mike Lockwood01c2c302010-05-24 10:44:35 -0400107 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800108 "\n"
109 "device commands:\n"
Mark Lindner9f9d1452014-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"
113 " adb pull [-p] <remote> [<local>]\n"
114 " - copy file/dir from device\n"
115 " ('-p' to display the transfer progress)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800116 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600117 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800118 " (see 'adb help all')\n"
119 " adb shell - run remote shell interactively\n"
120 " adb shell <command> - run remote shell command\n"
121 " adb emu <command> - run emulator console command\n"
122 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100123 " adb forward --list - list all forward socket connections.\n"
124 " the format is a list of lines with the following format:\n"
125 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800126 " adb forward <local> <remote> - forward socket connections\n"
127 " forward specs are one of: \n"
128 " tcp:<port>\n"
129 " localabstract:<unix domain socket name>\n"
130 " localreserved:<unix domain socket name>\n"
131 " localfilesystem:<unix domain socket name>\n"
132 " dev:<character device name>\n"
133 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100134 " adb forward --no-rebind <local> <remote>\n"
135 " - same as 'adb forward <local> <remote>' but fails\n"
136 " if <local> is already forwarded\n"
137 " adb forward --remove <local> - remove a specific forward socket connection\n"
138 " adb forward --remove-all - remove all forward socket connections\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800139 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700140 " adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700141 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800142 " ('-l' means forward-lock the app)\n"
143 " ('-r' means reinstall the app, keeping its data)\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700144 " ('-d' means allow version code downgrade)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500145 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700146 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800147 " adb uninstall [-k] <package> - remove this app package from the device\n"
148 " ('-k' means keep the data and cache directories)\n"
149 " adb bugreport - return all information from the device\n"
150 " that should be included in a bug report.\n"
151 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800152 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700153 " - write an archive of the device's data to <file>.\n"
154 " If no -f option is supplied then the data is written\n"
155 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700156 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700157 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800158 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
159 " (aka .obb) files associated with each application; the default\n"
160 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700161 " (-shared|-noshared enable/disable backup of the device's\n"
162 " shared storage / SD card contents; the default is noshared.)\n"
163 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700164 " (-system|-nosystem toggles whether -all automatically includes\n"
165 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700166 " (<packages...> is the list of applications to be backed up. If\n"
167 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700168 " list is optional. Applications explicitly given on the\n"
169 " command line will be included even if -nosystem would\n"
170 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700171 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700172 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700173 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800174 " adb help - show this help message\n"
175 " adb version - show version num\n"
176 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800177 "scripting:\n"
178 " adb wait-for-device - block until device is online\n"
179 " adb start-server - ensure that there is a server running\n"
180 " adb kill-server - kill the server if it is running\n"
181 " adb get-state - prints: offline | bootloader | device\n"
182 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700183 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800184 " adb status-window - continuously print device status for a specified device\n"
185 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400186 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800187 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700188 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800189 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700190 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800191 "\n"
192 "networking:\n"
193 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500194 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800195 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
196 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
197 "\n"
198 "adb sync notes: adb sync [ <directory> ]\n"
199 " <localdir> can be interpreted in several ways:\n"
200 "\n"
201 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
202 "\n"
203 " - If it is \"system\" or \"data\", only the corresponding partition\n"
204 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000205 "\n"
206 "environmental variables:\n"
207 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
208 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
209 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
210 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800211 );
212}
213
214int usage()
215{
216 help();
217 return 1;
218}
219
220#ifdef HAVE_TERMIO_H
221static struct termios tio_save;
222
223static void stdin_raw_init(int fd)
224{
225 struct termios tio;
226
227 if(tcgetattr(fd, &tio)) return;
228 if(tcgetattr(fd, &tio_save)) return;
229
230 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
231
232 /* no timeout but request at least one character per read */
233 tio.c_cc[VTIME] = 0;
234 tio.c_cc[VMIN] = 1;
235
236 tcsetattr(fd, TCSANOW, &tio);
237 tcflush(fd, TCIFLUSH);
238}
239
240static void stdin_raw_restore(int fd)
241{
242 tcsetattr(fd, TCSANOW, &tio_save);
243 tcflush(fd, TCIFLUSH);
244}
245#endif
246
247static void read_and_dump(int fd)
248{
249 char buf[4096];
250 int len;
251
252 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700253 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800254 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700255 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800256 if(len == 0) {
257 break;
258 }
259
260 if(len < 0) {
261 if(errno == EINTR) continue;
262 break;
263 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400264 fwrite(buf, 1, len, stdout);
265 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800266 }
267}
268
Christopher Tate73779122011-04-21 12:53:28 -0700269static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700270 const size_t BUFSIZE = 32 * 1024;
271 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700272 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700273 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700274
275 D("copy_to_file(%d -> %d)\n", inFd, outFd);
276 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700277 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700278 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700279 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700280 break;
281 }
282 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700283 if (errno == EINTR) {
284 D("copy_to_file() : EINTR, retrying\n");
285 continue;
286 }
Christopher Tate73779122011-04-21 12:53:28 -0700287 D("copy_to_file() : error %d\n", errno);
288 break;
289 }
290 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700291 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700292 }
Christopher Tatefba22972011-06-01 17:56:23 -0700293 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700294 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700295}
296
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800297static void *stdin_read_thread(void *x)
298{
299 int fd, fdi;
300 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800301 int r, n;
302 int state = 0;
303
304 int *fds = (int*) x;
305 fd = fds[0];
306 fdi = fds[1];
307 free(fds);
308
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800309 for(;;) {
310 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700311 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800312 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700313 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800314 if(r == 0) break;
315 if(r < 0) {
316 if(errno == EINTR) continue;
317 break;
318 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400319 for(n = 0; n < r; n++){
320 switch(buf[n]) {
321 case '\n':
322 state = 1;
323 break;
324 case '\r':
325 state = 1;
326 break;
327 case '~':
328 if(state == 1) state++;
329 break;
330 case '.':
331 if(state == 2) {
332 fprintf(stderr,"\n* disconnect *\n");
333#ifdef HAVE_TERMIO_H
334 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800335#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400336 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800337 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400338 default:
339 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800340 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800341 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800342 r = adb_write(fd, buf, r);
343 if(r <= 0) {
344 break;
345 }
346 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800347 return 0;
348}
349
350int interactive_shell(void)
351{
352 adb_thread_t thr;
353 int fdi, fd;
354 int *fds;
355
356 fd = adb_connect("shell:");
357 if(fd < 0) {
358 fprintf(stderr,"error: %s\n", adb_error());
359 return 1;
360 }
361 fdi = 0; //dup(0);
362
363 fds = malloc(sizeof(int) * 2);
364 fds[0] = fd;
365 fds[1] = fdi;
366
367#ifdef HAVE_TERMIO_H
368 stdin_raw_init(fdi);
369#endif
370 adb_thread_create(&thr, stdin_read_thread, fds);
371 read_and_dump(fd);
372#ifdef HAVE_TERMIO_H
373 stdin_raw_restore(fdi);
374#endif
375 return 0;
376}
377
378
379static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
380{
381 if (serial) {
382 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
383 } else {
384 const char* prefix = "host";
385 if (ttype == kTransportUsb)
386 prefix = "host-usb";
387 else if (ttype == kTransportLocal)
388 prefix = "host-local";
389
390 snprintf(buffer, buflen, "%s:%s", prefix, command);
391 }
392}
393
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100394int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800395 unsigned progress)
396{
397 char buf[4096];
398 unsigned total;
399 int fd;
400 const unsigned char *ptr;
401
402 sprintf(buf,"%s:%d", service, sz);
403 fd = adb_connect(buf);
404 if(fd < 0) {
405 fprintf(stderr,"error: %s\n", adb_error());
406 return -1;
407 }
408
409 int opt = CHUNK_SIZE;
410 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
411
412 total = sz;
413 ptr = data;
414
415 if(progress) {
416 char *x = strrchr(service, ':');
417 if(x) service = x + 1;
418 }
419
420 while(sz > 0) {
421 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
422 if(writex(fd, ptr, xfer)) {
423 adb_status(fd);
424 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
425 return -1;
426 }
427 sz -= xfer;
428 ptr += xfer;
429 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100430 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800431 fflush(stdout);
432 }
433 }
434 if(progress) {
435 printf("\n");
436 }
437
438 if(readx(fd, buf, 4)){
439 fprintf(stderr,"* error reading response *\n");
440 adb_close(fd);
441 return -1;
442 }
443 if(memcmp(buf, "OKAY", 4)) {
444 buf[4] = 0;
445 fprintf(stderr,"* error response '%s' *\n", buf);
446 adb_close(fd);
447 return -1;
448 }
449
450 adb_close(fd);
451 return 0;
452}
453
454
455int adb_download(const char *service, const char *fn, unsigned progress)
456{
457 void *data;
458 unsigned sz;
459
460 data = load_file(fn, &sz);
461 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100462 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800463 return -1;
464 }
465
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100466 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800467 free(data);
468 return status;
469}
470
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800471static void status_window(transport_type ttype, const char* serial)
472{
473 char command[4096];
474 char *state = 0;
475 char *laststate = 0;
476
477 /* silence stderr */
478#ifdef _WIN32
479 /* XXX: TODO */
480#else
481 int fd;
482 fd = unix_open("/dev/null", O_WRONLY);
483 dup2(fd, 2);
484 adb_close(fd);
485#endif
486
487 format_host_command(command, sizeof command, "get-state", ttype, serial);
488
489 for(;;) {
490 adb_sleep_ms(250);
491
492 if(state) {
493 free(state);
494 state = 0;
495 }
496
497 state = adb_query(command);
498
499 if(state) {
500 if(laststate && !strcmp(state,laststate)){
501 continue;
502 } else {
503 if(laststate) free(laststate);
504 laststate = strdup(state);
505 }
506 }
507
508 printf("%c[2J%c[2H", 27, 27);
509 printf("Android Debug Bridge\n");
510 printf("State: %s\n", state ? state : "offline");
511 fflush(stdout);
512 }
513}
514
515/** duplicate string and quote all \ " ( ) chars + space character. */
516static char *
517dupAndQuote(const char *s)
518{
519 const char *ts;
520 size_t alloc_len;
521 char *ret;
522 char *dest;
523
524 ts = s;
525
526 alloc_len = 0;
527
528 for( ;*ts != '\0'; ts++) {
529 alloc_len++;
530 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
531 alloc_len++;
532 }
533 }
534
535 ret = (char *)malloc(alloc_len + 1);
536
537 ts = s;
538 dest = ret;
539
540 for ( ;*ts != '\0'; ts++) {
541 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
542 *dest++ = '\\';
543 }
544
545 *dest++ = *ts;
546 }
547
548 *dest++ = '\0';
549
550 return ret;
551}
552
553/**
554 * Run ppp in "notty" mode against a resource listed as the first parameter
555 * eg:
556 *
557 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
558 *
559 */
560int ppp(int argc, char **argv)
561{
562#ifdef HAVE_WIN32_PROC
563 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
564 return -1;
565#else
566 char *adb_service_name;
567 pid_t pid;
568 int fd;
569
570 if (argc < 2) {
571 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
572 argv[0]);
573
574 return 1;
575 }
576
577 adb_service_name = argv[1];
578
579 fd = adb_connect(adb_service_name);
580
581 if(fd < 0) {
582 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
583 adb_service_name, adb_error());
584 return 1;
585 }
586
587 pid = fork();
588
589 if (pid < 0) {
590 perror("from fork()");
591 return 1;
592 } else if (pid == 0) {
593 int err;
594 int i;
595 const char **ppp_args;
596
597 // copy args
598 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
599 ppp_args[0] = "pppd";
600 for (i = 2 ; i < argc ; i++) {
601 //argv[2] and beyond become ppp_args[1] and beyond
602 ppp_args[i - 1] = argv[i];
603 }
604 ppp_args[i-1] = NULL;
605
606 // child side
607
608 dup2(fd, STDIN_FILENO);
609 dup2(fd, STDOUT_FILENO);
610 adb_close(STDERR_FILENO);
611 adb_close(fd);
612
613 err = execvp("pppd", (char * const *)ppp_args);
614
615 if (err < 0) {
616 perror("execing pppd");
617 }
618 exit(-1);
619 } else {
620 // parent side
621
622 adb_close(fd);
623 return 0;
624 }
625#endif /* !HAVE_WIN32_PROC */
626}
627
628static int send_shellcommand(transport_type transport, char* serial, char* buf)
629{
630 int fd, ret;
631
632 for(;;) {
633 fd = adb_connect(buf);
634 if(fd >= 0)
635 break;
636 fprintf(stderr,"- waiting for device -\n");
637 adb_sleep_ms(1000);
638 do_cmd(transport, serial, "wait-for-device", 0);
639 }
640
641 read_and_dump(fd);
642 ret = adb_close(fd);
643 if (ret)
644 perror("close");
645
646 return ret;
647}
648
649static int logcat(transport_type transport, char* serial, int argc, char **argv)
650{
651 char buf[4096];
652
653 char *log_tags;
654 char *quoted_log_tags;
655
656 log_tags = getenv("ANDROID_LOG_TAGS");
657 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
658
659 snprintf(buf, sizeof(buf),
660 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
661 quoted_log_tags);
662
663 free(quoted_log_tags);
664
Christopher Tate7b9b5162011-11-30 13:00:33 -0800665 if (!strcmp(argv[0],"longcat")) {
666 strncat(buf, " -v long", sizeof(buf)-1);
667 }
668
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800669 argc -= 1;
670 argv += 1;
671 while(argc-- > 0) {
672 char *quoted;
673
674 quoted = dupAndQuote (*argv++);
675
676 strncat(buf, " ", sizeof(buf)-1);
677 strncat(buf, quoted, sizeof(buf)-1);
678 free(quoted);
679 }
680
681 send_shellcommand(transport, serial, buf);
682 return 0;
683}
684
Christopher Tate1e9f2392011-12-08 19:04:34 -0800685static int mkdirs(char *path)
686{
687 int ret;
688 char *x = path + 1;
689
690 for(;;) {
691 x = adb_dirstart(x);
692 if(x == 0) return 0;
693 *x = 0;
694 ret = adb_mkdir(path, 0775);
695 *x = OS_PATH_SEPARATOR;
696 if((ret < 0) && (errno != EEXIST)) {
697 return ret;
698 }
699 x++;
700 }
701 return 0;
702}
703
Christopher Tate73779122011-04-21 12:53:28 -0700704static int backup(int argc, char** argv) {
705 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800706 char default_name[32];
707 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700708 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700709 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700710
Christopher Tatefba22972011-06-01 17:56:23 -0700711 /* find, extract, and use any -f argument */
712 for (i = 1; i < argc; i++) {
713 if (!strcmp("-f", argv[i])) {
714 if (i == argc-1) {
715 fprintf(stderr, "adb: -f passed with no filename\n");
716 return usage();
717 }
718 filename = argv[i+1];
719 for (j = i+2; j <= argc; ) {
720 argv[i++] = argv[j++];
721 }
722 argc -= 2;
723 argv[argc] = NULL;
724 }
Christopher Tate73779122011-04-21 12:53:28 -0700725 }
726
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700727 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
728 if (argc < 2) return usage();
729
Christopher Tate1e9f2392011-12-08 19:04:34 -0800730 adb_unlink(filename);
731 mkdirs((char *)filename);
732 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700733 if (outFd < 0) {
734 fprintf(stderr, "adb: unable to open file %s\n", filename);
735 return -1;
736 }
737
738 snprintf(buf, sizeof(buf), "backup");
739 for (argc--, argv++; argc; argc--, argv++) {
740 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
741 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
742 }
743
744 D("backup. filename=%s buf=%s\n", filename, buf);
745 fd = adb_connect(buf);
746 if (fd < 0) {
747 fprintf(stderr, "adb: unable to connect for backup\n");
748 adb_close(outFd);
749 return -1;
750 }
751
Christopher Tate9c829102012-01-06 15:43:03 -0800752 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700753 copy_to_file(fd, outFd);
754
755 adb_close(fd);
756 adb_close(outFd);
757 return 0;
758}
759
Christopher Tatecf5379b2011-05-17 15:52:54 -0700760static int restore(int argc, char** argv) {
761 const char* filename;
762 int fd, tarFd;
763
764 if (argc != 2) return usage();
765
766 filename = argv[1];
767 tarFd = adb_open(filename, O_RDONLY);
768 if (tarFd < 0) {
769 fprintf(stderr, "adb: unable to open file %s\n", filename);
770 return -1;
771 }
772
773 fd = adb_connect("restore:");
774 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700775 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700776 adb_close(tarFd);
777 return -1;
778 }
779
Christopher Tate9c829102012-01-06 15:43:03 -0800780 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700781 copy_to_file(tarFd, fd);
782
783 adb_close(fd);
784 adb_close(tarFd);
785 return 0;
786}
787
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800788#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
789static int top_works(const char *top)
790{
791 if (top != NULL && adb_is_absolute_host_path(top)) {
792 char path_buf[PATH_MAX];
793 snprintf(path_buf, sizeof(path_buf),
794 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
795 return access(path_buf, F_OK) == 0;
796 }
797 return 0;
798}
799
800static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
801{
802 strcpy(path_buf, indir);
803 while (1) {
804 if (top_works(path_buf)) {
805 return path_buf;
806 }
807 char *s = adb_dirstop(path_buf);
808 if (s != NULL) {
809 *s = '\0';
810 } else {
811 path_buf[0] = '\0';
812 return NULL;
813 }
814 }
815}
816
817static char *find_top(char path_buf[PATH_MAX])
818{
819 char *top = getenv("ANDROID_BUILD_TOP");
820 if (top != NULL && top[0] != '\0') {
821 if (!top_works(top)) {
822 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
823 return NULL;
824 }
825 } else {
826 top = getenv("TOP");
827 if (top != NULL && top[0] != '\0') {
828 if (!top_works(top)) {
829 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
830 return NULL;
831 }
832 } else {
833 top = NULL;
834 }
835 }
836
837 if (top != NULL) {
838 /* The environment pointed to a top directory that works.
839 */
840 strcpy(path_buf, top);
841 return path_buf;
842 }
843
844 /* The environment didn't help. Walk up the tree from the CWD
845 * to see if we can find the top.
846 */
847 char dir[PATH_MAX];
848 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
849 if (top == NULL) {
850 /* If the CWD isn't under a good-looking top, see if the
851 * executable is.
852 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100853 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800854 top = find_top_from(dir, path_buf);
855 }
856 return top;
857}
858
859/* <hint> may be:
860 * - A simple product name
861 * e.g., "sooner"
862TODO: debug? sooner-debug, sooner:debug?
863 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
864 * e.g., "out/target/product/sooner"
865 * - An absolute path to the PRODUCT_OUT dir
866 * e.g., "/src/device/out/target/product/sooner"
867 *
868 * Given <hint>, try to construct an absolute path to the
869 * ANDROID_PRODUCT_OUT dir.
870 */
871static const char *find_product_out_path(const char *hint)
872{
873 static char path_buf[PATH_MAX];
874
875 if (hint == NULL || hint[0] == '\0') {
876 return NULL;
877 }
878
879 /* If it's already absolute, don't bother doing any work.
880 */
881 if (adb_is_absolute_host_path(hint)) {
882 strcpy(path_buf, hint);
883 return path_buf;
884 }
885
886 /* If there are any slashes in it, assume it's a relative path;
887 * make it absolute.
888 */
889 if (adb_dirstart(hint) != NULL) {
890 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
891 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
892 return NULL;
893 }
894 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
895 fprintf(stderr, "adb: Couldn't assemble path\n");
896 return NULL;
897 }
898 strcat(path_buf, OS_PATH_SEPARATOR_STR);
899 strcat(path_buf, hint);
900 return path_buf;
901 }
902
903 /* It's a string without any slashes. Try to do something with it.
904 *
905 * Try to find the root of the build tree, and build a PRODUCT_OUT
906 * path from there.
907 */
908 char top_buf[PATH_MAX];
909 const char *top = find_top(top_buf);
910 if (top == NULL) {
911 fprintf(stderr, "adb: Couldn't find top of build tree\n");
912 return NULL;
913 }
914//TODO: if we have a way to indicate debug, look in out/debug/target/...
915 snprintf(path_buf, sizeof(path_buf),
916 "%s" OS_PATH_SEPARATOR_STR
917 "out" OS_PATH_SEPARATOR_STR
918 "target" OS_PATH_SEPARATOR_STR
919 "product" OS_PATH_SEPARATOR_STR
920 "%s", top_buf, hint);
921 if (access(path_buf, F_OK) < 0) {
922 fprintf(stderr, "adb: Couldn't find a product dir "
923 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
924 return NULL;
925 }
926 return path_buf;
927}
928
Mark Lindner9f9d1452014-03-11 17:55:59 -0700929
930static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2,
931 int* show_progress) {
932 *show_progress = 0;
933
934 if ((narg > 0) && !strcmp(*arg, "-p")) {
935 *show_progress = 1;
936 ++arg;
937 --narg;
938 }
939
940 if (narg > 0) {
941 *path1 = *arg;
942 ++arg;
943 --narg;
944 }
945
946 if (narg > 0) {
947 *path2 = *arg;
948 }
949}
950
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800951int adb_commandline(int argc, char **argv)
952{
953 char buf[4096];
954 int no_daemon = 0;
955 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100956 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800957 int persist = 0;
958 int r;
959 int quote;
960 transport_type ttype = kTransportAny;
961 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100962 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800963
964 /* If defined, this should be an absolute path to
965 * the directory containing all of the various system images
966 * for a particular product. If not defined, and the adb
967 * command requires this information, then the user must
968 * specify the path using "-p".
969 */
970 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
971 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
972 gProductOutPath = NULL;
973 }
974 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
975
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700976 serial = getenv("ANDROID_SERIAL");
977
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100978 /* Validate and assign the server port */
979 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
980 int server_port = DEFAULT_ADB_PORT;
981 if (server_port_str && strlen(server_port_str) > 0) {
982 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -0800983 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100984 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -0800985 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100986 server_port_str);
987 return usage();
988 }
989 }
990
991 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800992 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100993 if(!strcmp(argv[0],"server")) {
994 is_server = 1;
995 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800996 no_daemon = 1;
997 } else if (!strcmp(argv[0], "fork-server")) {
998 /* this is a special flag used only when the ADB client launches the ADB Server */
999 is_daemon = 1;
1000 } else if(!strcmp(argv[0],"persist")) {
1001 persist = 1;
1002 } else if(!strncmp(argv[0], "-p", 2)) {
1003 const char *product = NULL;
1004 if (argv[0][2] == '\0') {
1005 if (argc < 2) return usage();
1006 product = argv[1];
1007 argc--;
1008 argv++;
1009 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001010 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001011 }
1012 gProductOutPath = find_product_out_path(product);
1013 if (gProductOutPath == NULL) {
1014 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1015 product);
1016 return usage();
1017 }
1018 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1019 if (isdigit(argv[0][2])) {
1020 serial = argv[0] + 2;
1021 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001022 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001023 serial = argv[1];
1024 argc--;
1025 argv++;
1026 }
1027 } else if (!strcmp(argv[0],"-d")) {
1028 ttype = kTransportUsb;
1029 } else if (!strcmp(argv[0],"-e")) {
1030 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001031 } else if (!strcmp(argv[0],"-a")) {
1032 gListenAll = 1;
1033 } else if(!strncmp(argv[0], "-H", 2)) {
1034 const char *hostname = NULL;
1035 if (argv[0][2] == '\0') {
1036 if (argc < 2) return usage();
1037 hostname = argv[1];
1038 argc--;
1039 argv++;
1040 } else {
1041 hostname = argv[0] + 2;
1042 }
1043 adb_set_tcp_name(hostname);
1044
1045 } else if(!strncmp(argv[0], "-P", 2)) {
1046 if (argv[0][2] == '\0') {
1047 if (argc < 2) return usage();
1048 server_port_str = argv[1];
1049 argc--;
1050 argv++;
1051 } else {
1052 server_port_str = argv[0] + 2;
1053 }
1054 if (strlen(server_port_str) > 0) {
1055 server_port = (int) strtol(server_port_str, NULL, 0);
1056 if (server_port <= 0 || server_port > 65535) {
1057 fprintf(stderr,
1058 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1059 server_port_str);
1060 return usage();
1061 }
1062 } else {
1063 fprintf(stderr,
1064 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1065 return usage();
1066 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001067 } else {
1068 /* out of recognized modifiers and flags */
1069 break;
1070 }
1071 argc--;
1072 argv++;
1073 }
1074
1075 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001076 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001077
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001078 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001079 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001080 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001081 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001082 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001083 }
1084 if(r) {
1085 fprintf(stderr,"* could not start server *\n");
1086 }
1087 return r;
1088 }
1089
1090top:
1091 if(argc == 0) {
1092 return usage();
1093 }
1094
1095 /* adb_connect() commands */
1096
1097 if(!strcmp(argv[0], "devices")) {
1098 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001099 char *listopt;
1100 if (argc < 2)
1101 listopt = "";
1102 else if (argc == 2 && !strcmp(argv[1], "-l"))
1103 listopt = argv[1];
1104 else {
1105 fprintf(stderr, "Usage: adb devices [-l]\n");
1106 return 1;
1107 }
1108 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001109 tmp = adb_query(buf);
1110 if(tmp) {
1111 printf("List of devices attached \n");
1112 printf("%s\n", tmp);
1113 return 0;
1114 } else {
1115 return 1;
1116 }
1117 }
1118
Mike Lockwood01c2c302010-05-24 10:44:35 -04001119 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001120 char *tmp;
1121 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001122 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001123 return 1;
1124 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001125 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1126 tmp = adb_query(buf);
1127 if(tmp) {
1128 printf("%s\n", tmp);
1129 return 0;
1130 } else {
1131 return 1;
1132 }
1133 }
1134
1135 if(!strcmp(argv[0], "disconnect")) {
1136 char *tmp;
1137 if (argc > 2) {
1138 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1139 return 1;
1140 }
1141 if (argc == 2) {
1142 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1143 } else {
1144 snprintf(buf, sizeof buf, "host:disconnect:");
1145 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001146 tmp = adb_query(buf);
1147 if(tmp) {
1148 printf("%s\n", tmp);
1149 return 0;
1150 } else {
1151 return 1;
1152 }
1153 }
1154
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001155 if (!strcmp(argv[0], "emu")) {
1156 return adb_send_emulator_command(argc, argv);
1157 }
1158
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001159 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001160 int r;
1161 int fd;
1162
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001163 char h = (argv[0][0] == 'h');
1164
1165 if (h) {
1166 printf("\x1b[41;33m");
1167 fflush(stdout);
1168 }
1169
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001170 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001171 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001172 r = interactive_shell();
1173 if (h) {
1174 printf("\x1b[0m");
1175 fflush(stdout);
1176 }
1177 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001178 }
1179
1180 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1181 argc -= 2;
1182 argv += 2;
1183 while(argc-- > 0) {
1184 strcat(buf, " ");
1185
1186 /* quote empty strings and strings with spaces */
1187 quote = (**argv == 0 || strchr(*argv, ' '));
1188 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001189 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001190 strcat(buf, *argv++);
1191 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001192 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001193 }
1194
1195 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001196 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001197 fd = adb_connect(buf);
1198 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001199 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001200 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001201 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001202 adb_close(fd);
1203 r = 0;
1204 } else {
1205 fprintf(stderr,"error: %s\n", adb_error());
1206 r = -1;
1207 }
1208
1209 if(persist) {
1210 fprintf(stderr,"\n- waiting for device -\n");
1211 adb_sleep_ms(1000);
1212 do_cmd(ttype, serial, "wait-for-device", 0);
1213 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001214 if (h) {
1215 printf("\x1b[0m");
1216 fflush(stdout);
1217 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001218 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001219 return r;
1220 }
1221 }
1222 }
1223
1224 if(!strcmp(argv[0], "kill-server")) {
1225 int fd;
1226 fd = _adb_connect("host:kill");
1227 if(fd == -1) {
1228 fprintf(stderr,"* server not running *\n");
1229 return 1;
1230 }
1231 return 0;
1232 }
1233
Doug Zongker6b217ed2012-01-09 14:54:53 -08001234 if(!strcmp(argv[0], "sideload")) {
1235 if(argc != 2) return usage();
1236 if(adb_download("sideload", argv[1], 1)) {
1237 return 1;
1238 } else {
1239 return 0;
1240 }
1241 }
1242
Mike Lockwood26b88e32009-08-24 15:58:40 -07001243 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001244 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001245 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001246 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001247 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001248 if (!strcmp(argv[0], "reboot-bootloader"))
1249 snprintf(command, sizeof(command), "reboot:bootloader");
1250 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001251 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001252 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001253 snprintf(command, sizeof(command), "%s:", argv[0]);
1254 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001255 if(fd >= 0) {
1256 read_and_dump(fd);
1257 adb_close(fd);
1258 return 0;
1259 }
1260 fprintf(stderr,"error: %s\n", adb_error());
1261 return 1;
1262 }
1263
Mike Lockwood78589f32009-09-03 14:54:58 -04001264 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001265 if (argc != 1) return usage();
1266 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001267 return 0;
1268 }
1269
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001270 /* adb_command() wrapper commands */
1271
1272 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1273 char* service = argv[0];
1274 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1275 if (ttype == kTransportUsb) {
1276 service = "wait-for-usb";
1277 } else if (ttype == kTransportLocal) {
1278 service = "wait-for-local";
1279 } else {
1280 service = "wait-for-any";
1281 }
1282 }
1283
1284 format_host_command(buf, sizeof buf, service, ttype, serial);
1285
1286 if (adb_command(buf)) {
1287 D("failure: %s *\n",adb_error());
1288 fprintf(stderr,"error: %s\n", adb_error());
1289 return 1;
1290 }
1291
1292 /* Allow a command to be run after wait-for-device,
1293 * e.g. 'adb wait-for-device shell'.
1294 */
1295 if(argc > 1) {
1296 argc--;
1297 argv++;
1298 goto top;
1299 }
1300 return 0;
1301 }
1302
1303 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001304 char host_prefix[64];
1305 char remove = 0;
1306 char remove_all = 0;
1307 char list = 0;
1308 char no_rebind = 0;
1309
1310 // Parse options here.
1311 while (argc > 1 && argv[1][0] == '-') {
1312 if (!strcmp(argv[1], "--list"))
1313 list = 1;
1314 else if (!strcmp(argv[1], "--remove"))
1315 remove = 1;
1316 else if (!strcmp(argv[1], "--remove-all"))
1317 remove_all = 1;
1318 else if (!strcmp(argv[1], "--no-rebind"))
1319 no_rebind = 1;
1320 else {
1321 return usage();
1322 }
1323 argc--;
1324 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001325 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001326
1327 // Ensure we can only use one option at a time.
1328 if (list + remove + remove_all + no_rebind > 1) {
1329 return usage();
1330 }
1331
1332 // Determine the <host-prefix> for this command.
1333 if (serial) {
1334 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1335 serial);
1336 } else if (ttype == kTransportUsb) {
1337 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1338 } else if (ttype == kTransportLocal) {
1339 snprintf(host_prefix, sizeof host_prefix, "host-local");
1340 } else {
1341 snprintf(host_prefix, sizeof host_prefix, "host");
1342 }
1343
1344 // Implement forward --list
1345 if (list) {
1346 if (argc != 1)
1347 return usage();
1348 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1349 char* forwards = adb_query(buf);
1350 if (forwards == NULL) {
1351 fprintf(stderr, "error: %s\n", adb_error());
1352 return 1;
1353 }
1354 printf("%s", forwards);
1355 free(forwards);
1356 return 0;
1357 }
1358
1359 // Implement forward --remove-all
1360 else if (remove_all) {
1361 if (argc != 1)
1362 return usage();
1363 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1364 }
1365
1366 // Implement forward --remove <local>
1367 else if (remove) {
1368 if (argc != 2)
1369 return usage();
1370 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1371 }
1372 // Or implement one of:
1373 // forward <local> <remote>
1374 // forward --no-rebind <local> <remote>
1375 else
1376 {
1377 if (argc != 3)
1378 return usage();
1379 const char* command = no_rebind ? "forward:norebind:" : "forward";
1380 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1381 }
1382
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001383 if(adb_command(buf)) {
1384 fprintf(stderr,"error: %s\n", adb_error());
1385 return 1;
1386 }
1387 return 0;
1388 }
1389
1390 /* do_sync_*() commands */
1391
1392 if(!strcmp(argv[0], "ls")) {
1393 if(argc != 2) return usage();
1394 return do_sync_ls(argv[1]);
1395 }
1396
1397 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001398 int show_progress = 0;
1399 const char* lpath = NULL, *rpath = NULL;
1400
1401 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);
1402
1403 if ((lpath != NULL) && (rpath != NULL)) {
1404 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1405 }
1406
1407 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001408 }
1409
1410 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001411 int show_progress = 0;
1412 const char* rpath = NULL, *lpath = ".";
1413
1414 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);
1415
1416 if (rpath != NULL) {
1417 return do_sync_pull(rpath, lpath, show_progress);
Joe Onorato23595b02010-01-05 13:42:25 -08001418 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001419
1420 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001421 }
1422
1423 if(!strcmp(argv[0], "install")) {
1424 if (argc < 2) return usage();
1425 return install_app(ttype, serial, argc, argv);
1426 }
1427
1428 if(!strcmp(argv[0], "uninstall")) {
1429 if (argc < 2) return usage();
1430 return uninstall_app(ttype, serial, argc, argv);
1431 }
1432
1433 if(!strcmp(argv[0], "sync")) {
1434 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001435 int listonly = 0;
1436
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001437 int ret;
1438 if(argc < 2) {
1439 /* No local path was specified. */
1440 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001441 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1442 listonly = 1;
1443 if (argc == 3) {
1444 srcarg = argv[2];
1445 } else {
1446 srcarg = NULL;
1447 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001448 } else if(argc == 2) {
1449 /* A local path or "android"/"data" arg was specified. */
1450 srcarg = argv[1];
1451 } else {
1452 return usage();
1453 }
1454 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1455 if(ret != 0) return usage();
1456
1457 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001458 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001459 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001460 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001461
1462 free(android_srcpath);
1463 free(data_srcpath);
1464 return ret;
1465 }
1466
1467 /* passthrough commands */
1468
1469 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001470 !strcmp(argv[0],"get-serialno") ||
1471 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001472 {
1473 char *tmp;
1474
1475 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1476 tmp = adb_query(buf);
1477 if(tmp) {
1478 printf("%s\n", tmp);
1479 return 0;
1480 } else {
1481 return 1;
1482 }
1483 }
1484
1485 /* other commands */
1486
1487 if(!strcmp(argv[0],"status-window")) {
1488 status_window(ttype, serial);
1489 return 0;
1490 }
1491
Christopher Tate7b9b5162011-11-30 13:00:33 -08001492 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001493 return logcat(ttype, serial, argc, argv);
1494 }
1495
1496 if(!strcmp(argv[0],"ppp")) {
1497 return ppp(argc, argv);
1498 }
1499
1500 if (!strcmp(argv[0], "start-server")) {
1501 return adb_connect("host:start-server");
1502 }
1503
Christopher Tate73779122011-04-21 12:53:28 -07001504 if (!strcmp(argv[0], "backup")) {
1505 return backup(argc, argv);
1506 }
1507
Christopher Tatecf5379b2011-05-17 15:52:54 -07001508 if (!strcmp(argv[0], "restore")) {
1509 return restore(argc, argv);
1510 }
1511
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001512 if (!strcmp(argv[0], "jdwp")) {
1513 int fd = adb_connect("jdwp");
1514 if (fd >= 0) {
1515 read_and_dump(fd);
1516 adb_close(fd);
1517 return 0;
1518 } else {
1519 fprintf(stderr, "error: %s\n", adb_error());
1520 return -1;
1521 }
1522 }
1523
1524 /* "adb /?" is a common idiom under Windows */
1525 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1526 help();
1527 return 0;
1528 }
1529
1530 if(!strcmp(argv[0], "version")) {
1531 version(stdout);
1532 return 0;
1533 }
1534
1535 usage();
1536 return 1;
1537}
1538
1539static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1540{
1541 char *argv[16];
1542 int argc;
1543 va_list ap;
1544
1545 va_start(ap, cmd);
1546 argc = 0;
1547
1548 if (serial) {
1549 argv[argc++] = "-s";
1550 argv[argc++] = serial;
1551 } else if (ttype == kTransportUsb) {
1552 argv[argc++] = "-d";
1553 } else if (ttype == kTransportLocal) {
1554 argv[argc++] = "-e";
1555 }
1556
1557 argv[argc++] = cmd;
1558 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1559 va_end(ap);
1560
1561#if 0
1562 int n;
1563 fprintf(stderr,"argc = %d\n",argc);
1564 for(n = 0; n < argc; n++) {
1565 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1566 }
1567#endif
1568
1569 return adb_commandline(argc, argv);
1570}
1571
1572int find_sync_dirs(const char *srcarg,
1573 char **android_srcdir_out, char **data_srcdir_out)
1574{
1575 char *android_srcdir, *data_srcdir;
1576
1577 if(srcarg == NULL) {
1578 android_srcdir = product_file("system");
1579 data_srcdir = product_file("data");
1580 } else {
1581 /* srcarg may be "data", "system" or NULL.
1582 * if srcarg is NULL, then both data and system are synced
1583 */
1584 if(strcmp(srcarg, "system") == 0) {
1585 android_srcdir = product_file("system");
1586 data_srcdir = NULL;
1587 } else if(strcmp(srcarg, "data") == 0) {
1588 android_srcdir = NULL;
1589 data_srcdir = product_file("data");
1590 } else {
1591 /* It's not "system" or "data".
1592 */
1593 return 1;
1594 }
1595 }
1596
1597 if(android_srcdir_out != NULL)
1598 *android_srcdir_out = android_srcdir;
1599 else
1600 free(android_srcdir);
1601
1602 if(data_srcdir_out != NULL)
1603 *data_srcdir_out = data_srcdir;
1604 else
1605 free(data_srcdir);
1606
1607 return 0;
1608}
1609
1610static int pm_command(transport_type transport, char* serial,
1611 int argc, char** argv)
1612{
1613 char buf[4096];
1614
1615 snprintf(buf, sizeof(buf), "shell:pm");
1616
1617 while(argc-- > 0) {
1618 char *quoted;
1619
1620 quoted = dupAndQuote(*argv++);
1621
1622 strncat(buf, " ", sizeof(buf)-1);
1623 strncat(buf, quoted, sizeof(buf)-1);
1624 free(quoted);
1625 }
1626
1627 send_shellcommand(transport, serial, buf);
1628 return 0;
1629}
1630
1631int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1632{
1633 /* if the user choose the -k option, we refuse to do it until devices are
1634 out with the option to uninstall the remaining data somehow (adb/ui) */
1635 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1636 {
1637 printf(
1638 "The -k option uninstalls the application while retaining the data/cache.\n"
1639 "At the moment, there is no way to remove the remaining data.\n"
1640 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1641 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1642 return -1;
1643 }
1644
1645 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1646 return pm_command(transport, serial, argc, argv);
1647}
1648
1649static int delete_file(transport_type transport, char* serial, char* filename)
1650{
1651 char buf[4096];
1652 char* quoted;
1653
1654 snprintf(buf, sizeof(buf), "shell:rm ");
1655 quoted = dupAndQuote(filename);
1656 strncat(buf, quoted, sizeof(buf)-1);
1657 free(quoted);
1658
1659 send_shellcommand(transport, serial, buf);
1660 return 0;
1661}
1662
Kenny Root3802c992011-08-05 11:19:45 -07001663static const char* get_basename(const char* filename)
1664{
1665 const char* basename = adb_dirstop(filename);
1666 if (basename) {
1667 basename++;
1668 return basename;
1669 } else {
1670 return filename;
1671 }
1672}
1673
1674static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001675{
1676 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001677
Kenny Root3802c992011-08-05 11:19:45 -07001678 if (filename == NULL) {
1679 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001680 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001681
Kenny Root3802c992011-08-05 11:19:45 -07001682 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001683 fprintf(stderr, "can't find '%s' to install\n", filename);
1684 return 1;
1685 }
Kenny Root3802c992011-08-05 11:19:45 -07001686
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001687 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001688 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001689 return 1;
1690 }
1691
Kenny Root3802c992011-08-05 11:19:45 -07001692 return 0;
1693}
1694
1695int install_app(transport_type transport, char* serial, int argc, char** argv)
1696{
1697 static const char *const DATA_DEST = "/data/local/tmp/%s";
1698 static const char *const SD_DEST = "/sdcard/tmp/%s";
1699 const char* where = DATA_DEST;
1700 char apk_dest[PATH_MAX];
1701 char verification_dest[PATH_MAX];
1702 char* apk_file;
1703 char* verification_file = NULL;
1704 int file_arg = -1;
1705 int err;
1706 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001707 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001708
1709 for (i = 1; i < argc; i++) {
1710 if (*argv[i] != '-') {
1711 file_arg = i;
1712 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001713 } else if (!strcmp(argv[i], "-i")) {
1714 // Skip the installer package name.
1715 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001716 } else if (!strcmp(argv[i], "-s")) {
1717 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001718 } else if (!strcmp(argv[i], "--algo")) {
1719 verify_apk = 0;
1720 i++;
1721 } else if (!strcmp(argv[i], "--iv")) {
1722 verify_apk = 0;
1723 i++;
1724 } else if (!strcmp(argv[i], "--key")) {
1725 verify_apk = 0;
1726 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001727 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001728 }
1729
Kenny Root3802c992011-08-05 11:19:45 -07001730 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001731 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001732 return 1;
1733 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001734 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001735 return 1;
1736 }
1737
1738 apk_file = argv[file_arg];
1739
1740 if (file_arg != argc - 1) {
1741 verification_file = argv[file_arg + 1];
1742 }
1743
1744 if (check_file(apk_file) || check_file(verification_file)) {
1745 return 1;
1746 }
1747
1748 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1749 if (verification_file != NULL) {
1750 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1751
1752 if (!strcmp(apk_dest, verification_dest)) {
1753 fprintf(stderr, "APK and verification file can't have the same name\n");
1754 return 1;
1755 }
1756 }
1757
Mark Lindner9f9d1452014-03-11 17:55:59 -07001758 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001759 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001760 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001761 } else {
1762 argv[file_arg] = apk_dest; /* destination name, not source location */
1763 }
1764
1765 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001766 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1767 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001768 if (err) {
1769 goto cleanup_apk;
1770 } else {
1771 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1772 }
1773 }
1774
1775 pm_command(transport, serial, argc, argv);
1776
Kenny Root58d5f222012-03-26 16:14:02 -07001777cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001778 if (verification_file != NULL) {
1779 delete_file(transport, serial, verification_dest);
1780 }
1781
Kenny Root3802c992011-08-05 11:19:45 -07001782 delete_file(transport, serial, apk_dest);
1783
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001784 return err;
1785}