blob: 83b568d962af8dc8b785f0c7bef82ba8974ede9c [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"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700140 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
141 " - 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"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500144 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700145 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800146 " adb uninstall [-k] <package> - remove this app package from the device\n"
147 " ('-k' means keep the data and cache directories)\n"
148 " adb bugreport - return all information from the device\n"
149 " that should be included in a bug report.\n"
150 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800151 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700152 " - write an archive of the device's data to <file>.\n"
153 " If no -f option is supplied then the data is written\n"
154 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700155 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700156 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800157 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
158 " (aka .obb) files associated with each application; the default\n"
159 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700160 " (-shared|-noshared enable/disable backup of the device's\n"
161 " shared storage / SD card contents; the default is noshared.)\n"
162 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700163 " (-system|-nosystem toggles whether -all automatically includes\n"
164 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700165 " (<packages...> is the list of applications to be backed up. If\n"
166 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700167 " list is optional. Applications explicitly given on the\n"
168 " command line will be included even if -nosystem would\n"
169 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700170 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700171 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700172 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800173 " adb help - show this help message\n"
174 " adb version - show version num\n"
175 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800176 "scripting:\n"
177 " adb wait-for-device - block until device is online\n"
178 " adb start-server - ensure that there is a server running\n"
179 " adb kill-server - kill the server if it is running\n"
180 " adb get-state - prints: offline | bootloader | device\n"
181 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700182 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800183 " adb status-window - continuously print device status for a specified device\n"
184 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400185 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800186 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700187 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800188 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700189 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800190 "\n"
191 "networking:\n"
192 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500193 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800194 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
195 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
196 "\n"
197 "adb sync notes: adb sync [ <directory> ]\n"
198 " <localdir> can be interpreted in several ways:\n"
199 "\n"
200 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
201 "\n"
202 " - If it is \"system\" or \"data\", only the corresponding partition\n"
203 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000204 "\n"
205 "environmental variables:\n"
206 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
207 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
208 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
209 " 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 -0800210 );
211}
212
213int usage()
214{
215 help();
216 return 1;
217}
218
219#ifdef HAVE_TERMIO_H
220static struct termios tio_save;
221
222static void stdin_raw_init(int fd)
223{
224 struct termios tio;
225
226 if(tcgetattr(fd, &tio)) return;
227 if(tcgetattr(fd, &tio_save)) return;
228
229 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
230
231 /* no timeout but request at least one character per read */
232 tio.c_cc[VTIME] = 0;
233 tio.c_cc[VMIN] = 1;
234
235 tcsetattr(fd, TCSANOW, &tio);
236 tcflush(fd, TCIFLUSH);
237}
238
239static void stdin_raw_restore(int fd)
240{
241 tcsetattr(fd, TCSANOW, &tio_save);
242 tcflush(fd, TCIFLUSH);
243}
244#endif
245
246static void read_and_dump(int fd)
247{
248 char buf[4096];
249 int len;
250
251 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700252 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800253 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700254 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800255 if(len == 0) {
256 break;
257 }
258
259 if(len < 0) {
260 if(errno == EINTR) continue;
261 break;
262 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400263 fwrite(buf, 1, len, stdout);
264 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800265 }
266}
267
Christopher Tate73779122011-04-21 12:53:28 -0700268static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700269 const size_t BUFSIZE = 32 * 1024;
270 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700271 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700272 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700273
274 D("copy_to_file(%d -> %d)\n", inFd, outFd);
275 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700276 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700277 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700278 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700279 break;
280 }
281 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700282 if (errno == EINTR) {
283 D("copy_to_file() : EINTR, retrying\n");
284 continue;
285 }
Christopher Tate73779122011-04-21 12:53:28 -0700286 D("copy_to_file() : error %d\n", errno);
287 break;
288 }
289 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700290 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700291 }
Christopher Tatefba22972011-06-01 17:56:23 -0700292 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700293 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700294}
295
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800296static void *stdin_read_thread(void *x)
297{
298 int fd, fdi;
299 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800300 int r, n;
301 int state = 0;
302
303 int *fds = (int*) x;
304 fd = fds[0];
305 fdi = fds[1];
306 free(fds);
307
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800308 for(;;) {
309 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700310 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800311 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700312 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313 if(r == 0) break;
314 if(r < 0) {
315 if(errno == EINTR) continue;
316 break;
317 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400318 for(n = 0; n < r; n++){
319 switch(buf[n]) {
320 case '\n':
321 state = 1;
322 break;
323 case '\r':
324 state = 1;
325 break;
326 case '~':
327 if(state == 1) state++;
328 break;
329 case '.':
330 if(state == 2) {
331 fprintf(stderr,"\n* disconnect *\n");
332#ifdef HAVE_TERMIO_H
333 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800334#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400335 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800336 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400337 default:
338 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800339 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800340 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800341 r = adb_write(fd, buf, r);
342 if(r <= 0) {
343 break;
344 }
345 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800346 return 0;
347}
348
349int interactive_shell(void)
350{
351 adb_thread_t thr;
352 int fdi, fd;
353 int *fds;
354
355 fd = adb_connect("shell:");
356 if(fd < 0) {
357 fprintf(stderr,"error: %s\n", adb_error());
358 return 1;
359 }
360 fdi = 0; //dup(0);
361
362 fds = malloc(sizeof(int) * 2);
363 fds[0] = fd;
364 fds[1] = fdi;
365
366#ifdef HAVE_TERMIO_H
367 stdin_raw_init(fdi);
368#endif
369 adb_thread_create(&thr, stdin_read_thread, fds);
370 read_and_dump(fd);
371#ifdef HAVE_TERMIO_H
372 stdin_raw_restore(fdi);
373#endif
374 return 0;
375}
376
377
378static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
379{
380 if (serial) {
381 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
382 } else {
383 const char* prefix = "host";
384 if (ttype == kTransportUsb)
385 prefix = "host-usb";
386 else if (ttype == kTransportLocal)
387 prefix = "host-local";
388
389 snprintf(buffer, buflen, "%s:%s", prefix, command);
390 }
391}
392
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100393int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800394 unsigned progress)
395{
396 char buf[4096];
397 unsigned total;
398 int fd;
399 const unsigned char *ptr;
400
401 sprintf(buf,"%s:%d", service, sz);
402 fd = adb_connect(buf);
403 if(fd < 0) {
404 fprintf(stderr,"error: %s\n", adb_error());
405 return -1;
406 }
407
408 int opt = CHUNK_SIZE;
409 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
410
411 total = sz;
412 ptr = data;
413
414 if(progress) {
415 char *x = strrchr(service, ':');
416 if(x) service = x + 1;
417 }
418
419 while(sz > 0) {
420 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
421 if(writex(fd, ptr, xfer)) {
422 adb_status(fd);
423 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
424 return -1;
425 }
426 sz -= xfer;
427 ptr += xfer;
428 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100429 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800430 fflush(stdout);
431 }
432 }
433 if(progress) {
434 printf("\n");
435 }
436
437 if(readx(fd, buf, 4)){
438 fprintf(stderr,"* error reading response *\n");
439 adb_close(fd);
440 return -1;
441 }
442 if(memcmp(buf, "OKAY", 4)) {
443 buf[4] = 0;
444 fprintf(stderr,"* error response '%s' *\n", buf);
445 adb_close(fd);
446 return -1;
447 }
448
449 adb_close(fd);
450 return 0;
451}
452
453
454int adb_download(const char *service, const char *fn, unsigned progress)
455{
456 void *data;
457 unsigned sz;
458
459 data = load_file(fn, &sz);
460 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100461 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800462 return -1;
463 }
464
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100465 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800466 free(data);
467 return status;
468}
469
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800470static void status_window(transport_type ttype, const char* serial)
471{
472 char command[4096];
473 char *state = 0;
474 char *laststate = 0;
475
476 /* silence stderr */
477#ifdef _WIN32
478 /* XXX: TODO */
479#else
480 int fd;
481 fd = unix_open("/dev/null", O_WRONLY);
482 dup2(fd, 2);
483 adb_close(fd);
484#endif
485
486 format_host_command(command, sizeof command, "get-state", ttype, serial);
487
488 for(;;) {
489 adb_sleep_ms(250);
490
491 if(state) {
492 free(state);
493 state = 0;
494 }
495
496 state = adb_query(command);
497
498 if(state) {
499 if(laststate && !strcmp(state,laststate)){
500 continue;
501 } else {
502 if(laststate) free(laststate);
503 laststate = strdup(state);
504 }
505 }
506
507 printf("%c[2J%c[2H", 27, 27);
508 printf("Android Debug Bridge\n");
509 printf("State: %s\n", state ? state : "offline");
510 fflush(stdout);
511 }
512}
513
514/** duplicate string and quote all \ " ( ) chars + space character. */
515static char *
516dupAndQuote(const char *s)
517{
518 const char *ts;
519 size_t alloc_len;
520 char *ret;
521 char *dest;
522
523 ts = s;
524
525 alloc_len = 0;
526
527 for( ;*ts != '\0'; ts++) {
528 alloc_len++;
529 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
530 alloc_len++;
531 }
532 }
533
534 ret = (char *)malloc(alloc_len + 1);
535
536 ts = s;
537 dest = ret;
538
539 for ( ;*ts != '\0'; ts++) {
540 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
541 *dest++ = '\\';
542 }
543
544 *dest++ = *ts;
545 }
546
547 *dest++ = '\0';
548
549 return ret;
550}
551
552/**
553 * Run ppp in "notty" mode against a resource listed as the first parameter
554 * eg:
555 *
556 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
557 *
558 */
559int ppp(int argc, char **argv)
560{
561#ifdef HAVE_WIN32_PROC
562 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
563 return -1;
564#else
565 char *adb_service_name;
566 pid_t pid;
567 int fd;
568
569 if (argc < 2) {
570 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
571 argv[0]);
572
573 return 1;
574 }
575
576 adb_service_name = argv[1];
577
578 fd = adb_connect(adb_service_name);
579
580 if(fd < 0) {
581 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
582 adb_service_name, adb_error());
583 return 1;
584 }
585
586 pid = fork();
587
588 if (pid < 0) {
589 perror("from fork()");
590 return 1;
591 } else if (pid == 0) {
592 int err;
593 int i;
594 const char **ppp_args;
595
596 // copy args
597 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
598 ppp_args[0] = "pppd";
599 for (i = 2 ; i < argc ; i++) {
600 //argv[2] and beyond become ppp_args[1] and beyond
601 ppp_args[i - 1] = argv[i];
602 }
603 ppp_args[i-1] = NULL;
604
605 // child side
606
607 dup2(fd, STDIN_FILENO);
608 dup2(fd, STDOUT_FILENO);
609 adb_close(STDERR_FILENO);
610 adb_close(fd);
611
612 err = execvp("pppd", (char * const *)ppp_args);
613
614 if (err < 0) {
615 perror("execing pppd");
616 }
617 exit(-1);
618 } else {
619 // parent side
620
621 adb_close(fd);
622 return 0;
623 }
624#endif /* !HAVE_WIN32_PROC */
625}
626
627static int send_shellcommand(transport_type transport, char* serial, char* buf)
628{
629 int fd, ret;
630
631 for(;;) {
632 fd = adb_connect(buf);
633 if(fd >= 0)
634 break;
635 fprintf(stderr,"- waiting for device -\n");
636 adb_sleep_ms(1000);
637 do_cmd(transport, serial, "wait-for-device", 0);
638 }
639
640 read_and_dump(fd);
641 ret = adb_close(fd);
642 if (ret)
643 perror("close");
644
645 return ret;
646}
647
648static int logcat(transport_type transport, char* serial, int argc, char **argv)
649{
650 char buf[4096];
651
652 char *log_tags;
653 char *quoted_log_tags;
654
655 log_tags = getenv("ANDROID_LOG_TAGS");
656 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
657
658 snprintf(buf, sizeof(buf),
659 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
660 quoted_log_tags);
661
662 free(quoted_log_tags);
663
Christopher Tate7b9b5162011-11-30 13:00:33 -0800664 if (!strcmp(argv[0],"longcat")) {
665 strncat(buf, " -v long", sizeof(buf)-1);
666 }
667
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800668 argc -= 1;
669 argv += 1;
670 while(argc-- > 0) {
671 char *quoted;
672
673 quoted = dupAndQuote (*argv++);
674
675 strncat(buf, " ", sizeof(buf)-1);
676 strncat(buf, quoted, sizeof(buf)-1);
677 free(quoted);
678 }
679
680 send_shellcommand(transport, serial, buf);
681 return 0;
682}
683
Christopher Tate1e9f2392011-12-08 19:04:34 -0800684static int mkdirs(char *path)
685{
686 int ret;
687 char *x = path + 1;
688
689 for(;;) {
690 x = adb_dirstart(x);
691 if(x == 0) return 0;
692 *x = 0;
693 ret = adb_mkdir(path, 0775);
694 *x = OS_PATH_SEPARATOR;
695 if((ret < 0) && (errno != EEXIST)) {
696 return ret;
697 }
698 x++;
699 }
700 return 0;
701}
702
Christopher Tate73779122011-04-21 12:53:28 -0700703static int backup(int argc, char** argv) {
704 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800705 char default_name[32];
706 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700707 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700708 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700709
Christopher Tatefba22972011-06-01 17:56:23 -0700710 /* find, extract, and use any -f argument */
711 for (i = 1; i < argc; i++) {
712 if (!strcmp("-f", argv[i])) {
713 if (i == argc-1) {
714 fprintf(stderr, "adb: -f passed with no filename\n");
715 return usage();
716 }
717 filename = argv[i+1];
718 for (j = i+2; j <= argc; ) {
719 argv[i++] = argv[j++];
720 }
721 argc -= 2;
722 argv[argc] = NULL;
723 }
Christopher Tate73779122011-04-21 12:53:28 -0700724 }
725
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700726 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
727 if (argc < 2) return usage();
728
Christopher Tate1e9f2392011-12-08 19:04:34 -0800729 adb_unlink(filename);
730 mkdirs((char *)filename);
731 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700732 if (outFd < 0) {
733 fprintf(stderr, "adb: unable to open file %s\n", filename);
734 return -1;
735 }
736
737 snprintf(buf, sizeof(buf), "backup");
738 for (argc--, argv++; argc; argc--, argv++) {
739 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
740 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
741 }
742
743 D("backup. filename=%s buf=%s\n", filename, buf);
744 fd = adb_connect(buf);
745 if (fd < 0) {
746 fprintf(stderr, "adb: unable to connect for backup\n");
747 adb_close(outFd);
748 return -1;
749 }
750
Christopher Tate9c829102012-01-06 15:43:03 -0800751 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700752 copy_to_file(fd, outFd);
753
754 adb_close(fd);
755 adb_close(outFd);
756 return 0;
757}
758
Christopher Tatecf5379b2011-05-17 15:52:54 -0700759static int restore(int argc, char** argv) {
760 const char* filename;
761 int fd, tarFd;
762
763 if (argc != 2) return usage();
764
765 filename = argv[1];
766 tarFd = adb_open(filename, O_RDONLY);
767 if (tarFd < 0) {
768 fprintf(stderr, "adb: unable to open file %s\n", filename);
769 return -1;
770 }
771
772 fd = adb_connect("restore:");
773 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700774 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700775 adb_close(tarFd);
776 return -1;
777 }
778
Christopher Tate9c829102012-01-06 15:43:03 -0800779 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700780 copy_to_file(tarFd, fd);
781
782 adb_close(fd);
783 adb_close(tarFd);
784 return 0;
785}
786
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800787#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
788static int top_works(const char *top)
789{
790 if (top != NULL && adb_is_absolute_host_path(top)) {
791 char path_buf[PATH_MAX];
792 snprintf(path_buf, sizeof(path_buf),
793 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
794 return access(path_buf, F_OK) == 0;
795 }
796 return 0;
797}
798
799static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
800{
801 strcpy(path_buf, indir);
802 while (1) {
803 if (top_works(path_buf)) {
804 return path_buf;
805 }
806 char *s = adb_dirstop(path_buf);
807 if (s != NULL) {
808 *s = '\0';
809 } else {
810 path_buf[0] = '\0';
811 return NULL;
812 }
813 }
814}
815
816static char *find_top(char path_buf[PATH_MAX])
817{
818 char *top = getenv("ANDROID_BUILD_TOP");
819 if (top != NULL && top[0] != '\0') {
820 if (!top_works(top)) {
821 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
822 return NULL;
823 }
824 } else {
825 top = getenv("TOP");
826 if (top != NULL && top[0] != '\0') {
827 if (!top_works(top)) {
828 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
829 return NULL;
830 }
831 } else {
832 top = NULL;
833 }
834 }
835
836 if (top != NULL) {
837 /* The environment pointed to a top directory that works.
838 */
839 strcpy(path_buf, top);
840 return path_buf;
841 }
842
843 /* The environment didn't help. Walk up the tree from the CWD
844 * to see if we can find the top.
845 */
846 char dir[PATH_MAX];
847 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
848 if (top == NULL) {
849 /* If the CWD isn't under a good-looking top, see if the
850 * executable is.
851 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100852 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800853 top = find_top_from(dir, path_buf);
854 }
855 return top;
856}
857
858/* <hint> may be:
859 * - A simple product name
860 * e.g., "sooner"
861TODO: debug? sooner-debug, sooner:debug?
862 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
863 * e.g., "out/target/product/sooner"
864 * - An absolute path to the PRODUCT_OUT dir
865 * e.g., "/src/device/out/target/product/sooner"
866 *
867 * Given <hint>, try to construct an absolute path to the
868 * ANDROID_PRODUCT_OUT dir.
869 */
870static const char *find_product_out_path(const char *hint)
871{
872 static char path_buf[PATH_MAX];
873
874 if (hint == NULL || hint[0] == '\0') {
875 return NULL;
876 }
877
878 /* If it's already absolute, don't bother doing any work.
879 */
880 if (adb_is_absolute_host_path(hint)) {
881 strcpy(path_buf, hint);
882 return path_buf;
883 }
884
885 /* If there are any slashes in it, assume it's a relative path;
886 * make it absolute.
887 */
888 if (adb_dirstart(hint) != NULL) {
889 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
890 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
891 return NULL;
892 }
893 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
894 fprintf(stderr, "adb: Couldn't assemble path\n");
895 return NULL;
896 }
897 strcat(path_buf, OS_PATH_SEPARATOR_STR);
898 strcat(path_buf, hint);
899 return path_buf;
900 }
901
902 /* It's a string without any slashes. Try to do something with it.
903 *
904 * Try to find the root of the build tree, and build a PRODUCT_OUT
905 * path from there.
906 */
907 char top_buf[PATH_MAX];
908 const char *top = find_top(top_buf);
909 if (top == NULL) {
910 fprintf(stderr, "adb: Couldn't find top of build tree\n");
911 return NULL;
912 }
913//TODO: if we have a way to indicate debug, look in out/debug/target/...
914 snprintf(path_buf, sizeof(path_buf),
915 "%s" OS_PATH_SEPARATOR_STR
916 "out" OS_PATH_SEPARATOR_STR
917 "target" OS_PATH_SEPARATOR_STR
918 "product" OS_PATH_SEPARATOR_STR
919 "%s", top_buf, hint);
920 if (access(path_buf, F_OK) < 0) {
921 fprintf(stderr, "adb: Couldn't find a product dir "
922 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
923 return NULL;
924 }
925 return path_buf;
926}
927
Mark Lindner9f9d1452014-03-11 17:55:59 -0700928
929static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2,
930 int* show_progress) {
931 *show_progress = 0;
932
933 if ((narg > 0) && !strcmp(*arg, "-p")) {
934 *show_progress = 1;
935 ++arg;
936 --narg;
937 }
938
939 if (narg > 0) {
940 *path1 = *arg;
941 ++arg;
942 --narg;
943 }
944
945 if (narg > 0) {
946 *path2 = *arg;
947 }
948}
949
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800950int adb_commandline(int argc, char **argv)
951{
952 char buf[4096];
953 int no_daemon = 0;
954 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100955 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800956 int persist = 0;
957 int r;
958 int quote;
959 transport_type ttype = kTransportAny;
960 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100961 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800962
963 /* If defined, this should be an absolute path to
964 * the directory containing all of the various system images
965 * for a particular product. If not defined, and the adb
966 * command requires this information, then the user must
967 * specify the path using "-p".
968 */
969 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
970 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
971 gProductOutPath = NULL;
972 }
973 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
974
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700975 serial = getenv("ANDROID_SERIAL");
976
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100977 /* Validate and assign the server port */
978 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
979 int server_port = DEFAULT_ADB_PORT;
980 if (server_port_str && strlen(server_port_str) > 0) {
981 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -0800982 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100983 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -0800984 "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 +0100985 server_port_str);
986 return usage();
987 }
988 }
989
990 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800991 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100992 if(!strcmp(argv[0],"server")) {
993 is_server = 1;
994 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800995 no_daemon = 1;
996 } else if (!strcmp(argv[0], "fork-server")) {
997 /* this is a special flag used only when the ADB client launches the ADB Server */
998 is_daemon = 1;
999 } else if(!strcmp(argv[0],"persist")) {
1000 persist = 1;
1001 } else if(!strncmp(argv[0], "-p", 2)) {
1002 const char *product = NULL;
1003 if (argv[0][2] == '\0') {
1004 if (argc < 2) return usage();
1005 product = argv[1];
1006 argc--;
1007 argv++;
1008 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001009 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001010 }
1011 gProductOutPath = find_product_out_path(product);
1012 if (gProductOutPath == NULL) {
1013 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1014 product);
1015 return usage();
1016 }
1017 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1018 if (isdigit(argv[0][2])) {
1019 serial = argv[0] + 2;
1020 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001021 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001022 serial = argv[1];
1023 argc--;
1024 argv++;
1025 }
1026 } else if (!strcmp(argv[0],"-d")) {
1027 ttype = kTransportUsb;
1028 } else if (!strcmp(argv[0],"-e")) {
1029 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001030 } else if (!strcmp(argv[0],"-a")) {
1031 gListenAll = 1;
1032 } else if(!strncmp(argv[0], "-H", 2)) {
1033 const char *hostname = NULL;
1034 if (argv[0][2] == '\0') {
1035 if (argc < 2) return usage();
1036 hostname = argv[1];
1037 argc--;
1038 argv++;
1039 } else {
1040 hostname = argv[0] + 2;
1041 }
1042 adb_set_tcp_name(hostname);
1043
1044 } else if(!strncmp(argv[0], "-P", 2)) {
1045 if (argv[0][2] == '\0') {
1046 if (argc < 2) return usage();
1047 server_port_str = argv[1];
1048 argc--;
1049 argv++;
1050 } else {
1051 server_port_str = argv[0] + 2;
1052 }
1053 if (strlen(server_port_str) > 0) {
1054 server_port = (int) strtol(server_port_str, NULL, 0);
1055 if (server_port <= 0 || server_port > 65535) {
1056 fprintf(stderr,
1057 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1058 server_port_str);
1059 return usage();
1060 }
1061 } else {
1062 fprintf(stderr,
1063 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1064 return usage();
1065 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001066 } else {
1067 /* out of recognized modifiers and flags */
1068 break;
1069 }
1070 argc--;
1071 argv++;
1072 }
1073
1074 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001075 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001076
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001077 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001078 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001079 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001080 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001081 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001082 }
1083 if(r) {
1084 fprintf(stderr,"* could not start server *\n");
1085 }
1086 return r;
1087 }
1088
1089top:
1090 if(argc == 0) {
1091 return usage();
1092 }
1093
1094 /* adb_connect() commands */
1095
1096 if(!strcmp(argv[0], "devices")) {
1097 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001098 char *listopt;
1099 if (argc < 2)
1100 listopt = "";
1101 else if (argc == 2 && !strcmp(argv[1], "-l"))
1102 listopt = argv[1];
1103 else {
1104 fprintf(stderr, "Usage: adb devices [-l]\n");
1105 return 1;
1106 }
1107 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001108 tmp = adb_query(buf);
1109 if(tmp) {
1110 printf("List of devices attached \n");
1111 printf("%s\n", tmp);
1112 return 0;
1113 } else {
1114 return 1;
1115 }
1116 }
1117
Mike Lockwood01c2c302010-05-24 10:44:35 -04001118 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001119 char *tmp;
1120 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001121 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001122 return 1;
1123 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001124 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1125 tmp = adb_query(buf);
1126 if(tmp) {
1127 printf("%s\n", tmp);
1128 return 0;
1129 } else {
1130 return 1;
1131 }
1132 }
1133
1134 if(!strcmp(argv[0], "disconnect")) {
1135 char *tmp;
1136 if (argc > 2) {
1137 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1138 return 1;
1139 }
1140 if (argc == 2) {
1141 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1142 } else {
1143 snprintf(buf, sizeof buf, "host:disconnect:");
1144 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001145 tmp = adb_query(buf);
1146 if(tmp) {
1147 printf("%s\n", tmp);
1148 return 0;
1149 } else {
1150 return 1;
1151 }
1152 }
1153
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001154 if (!strcmp(argv[0], "emu")) {
1155 return adb_send_emulator_command(argc, argv);
1156 }
1157
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001158 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001159 int r;
1160 int fd;
1161
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001162 char h = (argv[0][0] == 'h');
1163
1164 if (h) {
1165 printf("\x1b[41;33m");
1166 fflush(stdout);
1167 }
1168
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001169 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001170 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001171 r = interactive_shell();
1172 if (h) {
1173 printf("\x1b[0m");
1174 fflush(stdout);
1175 }
1176 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001177 }
1178
1179 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1180 argc -= 2;
1181 argv += 2;
1182 while(argc-- > 0) {
1183 strcat(buf, " ");
1184
1185 /* quote empty strings and strings with spaces */
1186 quote = (**argv == 0 || strchr(*argv, ' '));
1187 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001188 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001189 strcat(buf, *argv++);
1190 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001191 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001192 }
1193
1194 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001195 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001196 fd = adb_connect(buf);
1197 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001198 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001199 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001200 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001201 adb_close(fd);
1202 r = 0;
1203 } else {
1204 fprintf(stderr,"error: %s\n", adb_error());
1205 r = -1;
1206 }
1207
1208 if(persist) {
1209 fprintf(stderr,"\n- waiting for device -\n");
1210 adb_sleep_ms(1000);
1211 do_cmd(ttype, serial, "wait-for-device", 0);
1212 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001213 if (h) {
1214 printf("\x1b[0m");
1215 fflush(stdout);
1216 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001217 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001218 return r;
1219 }
1220 }
1221 }
1222
1223 if(!strcmp(argv[0], "kill-server")) {
1224 int fd;
1225 fd = _adb_connect("host:kill");
1226 if(fd == -1) {
1227 fprintf(stderr,"* server not running *\n");
1228 return 1;
1229 }
1230 return 0;
1231 }
1232
Doug Zongker6b217ed2012-01-09 14:54:53 -08001233 if(!strcmp(argv[0], "sideload")) {
1234 if(argc != 2) return usage();
1235 if(adb_download("sideload", argv[1], 1)) {
1236 return 1;
1237 } else {
1238 return 0;
1239 }
1240 }
1241
Mike Lockwood26b88e32009-08-24 15:58:40 -07001242 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001243 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001244 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001245 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001246 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001247 if (!strcmp(argv[0], "reboot-bootloader"))
1248 snprintf(command, sizeof(command), "reboot:bootloader");
1249 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001250 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001251 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001252 snprintf(command, sizeof(command), "%s:", argv[0]);
1253 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001254 if(fd >= 0) {
1255 read_and_dump(fd);
1256 adb_close(fd);
1257 return 0;
1258 }
1259 fprintf(stderr,"error: %s\n", adb_error());
1260 return 1;
1261 }
1262
Mike Lockwood78589f32009-09-03 14:54:58 -04001263 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001264 if (argc != 1) return usage();
1265 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001266 return 0;
1267 }
1268
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001269 /* adb_command() wrapper commands */
1270
1271 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1272 char* service = argv[0];
1273 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1274 if (ttype == kTransportUsb) {
1275 service = "wait-for-usb";
1276 } else if (ttype == kTransportLocal) {
1277 service = "wait-for-local";
1278 } else {
1279 service = "wait-for-any";
1280 }
1281 }
1282
1283 format_host_command(buf, sizeof buf, service, ttype, serial);
1284
1285 if (adb_command(buf)) {
1286 D("failure: %s *\n",adb_error());
1287 fprintf(stderr,"error: %s\n", adb_error());
1288 return 1;
1289 }
1290
1291 /* Allow a command to be run after wait-for-device,
1292 * e.g. 'adb wait-for-device shell'.
1293 */
1294 if(argc > 1) {
1295 argc--;
1296 argv++;
1297 goto top;
1298 }
1299 return 0;
1300 }
1301
1302 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001303 char host_prefix[64];
1304 char remove = 0;
1305 char remove_all = 0;
1306 char list = 0;
1307 char no_rebind = 0;
1308
1309 // Parse options here.
1310 while (argc > 1 && argv[1][0] == '-') {
1311 if (!strcmp(argv[1], "--list"))
1312 list = 1;
1313 else if (!strcmp(argv[1], "--remove"))
1314 remove = 1;
1315 else if (!strcmp(argv[1], "--remove-all"))
1316 remove_all = 1;
1317 else if (!strcmp(argv[1], "--no-rebind"))
1318 no_rebind = 1;
1319 else {
1320 return usage();
1321 }
1322 argc--;
1323 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001324 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001325
1326 // Ensure we can only use one option at a time.
1327 if (list + remove + remove_all + no_rebind > 1) {
1328 return usage();
1329 }
1330
1331 // Determine the <host-prefix> for this command.
1332 if (serial) {
1333 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1334 serial);
1335 } else if (ttype == kTransportUsb) {
1336 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1337 } else if (ttype == kTransportLocal) {
1338 snprintf(host_prefix, sizeof host_prefix, "host-local");
1339 } else {
1340 snprintf(host_prefix, sizeof host_prefix, "host");
1341 }
1342
1343 // Implement forward --list
1344 if (list) {
1345 if (argc != 1)
1346 return usage();
1347 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1348 char* forwards = adb_query(buf);
1349 if (forwards == NULL) {
1350 fprintf(stderr, "error: %s\n", adb_error());
1351 return 1;
1352 }
1353 printf("%s", forwards);
1354 free(forwards);
1355 return 0;
1356 }
1357
1358 // Implement forward --remove-all
1359 else if (remove_all) {
1360 if (argc != 1)
1361 return usage();
1362 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1363 }
1364
1365 // Implement forward --remove <local>
1366 else if (remove) {
1367 if (argc != 2)
1368 return usage();
1369 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1370 }
1371 // Or implement one of:
1372 // forward <local> <remote>
1373 // forward --no-rebind <local> <remote>
1374 else
1375 {
1376 if (argc != 3)
1377 return usage();
1378 const char* command = no_rebind ? "forward:norebind:" : "forward";
1379 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1380 }
1381
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001382 if(adb_command(buf)) {
1383 fprintf(stderr,"error: %s\n", adb_error());
1384 return 1;
1385 }
1386 return 0;
1387 }
1388
1389 /* do_sync_*() commands */
1390
1391 if(!strcmp(argv[0], "ls")) {
1392 if(argc != 2) return usage();
1393 return do_sync_ls(argv[1]);
1394 }
1395
1396 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001397 int show_progress = 0;
1398 const char* lpath = NULL, *rpath = NULL;
1399
1400 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);
1401
1402 if ((lpath != NULL) && (rpath != NULL)) {
1403 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1404 }
1405
1406 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001407 }
1408
1409 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001410 int show_progress = 0;
1411 const char* rpath = NULL, *lpath = ".";
1412
1413 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);
1414
1415 if (rpath != NULL) {
1416 return do_sync_pull(rpath, lpath, show_progress);
Joe Onorato23595b02010-01-05 13:42:25 -08001417 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001418
1419 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001420 }
1421
1422 if(!strcmp(argv[0], "install")) {
1423 if (argc < 2) return usage();
1424 return install_app(ttype, serial, argc, argv);
1425 }
1426
1427 if(!strcmp(argv[0], "uninstall")) {
1428 if (argc < 2) return usage();
1429 return uninstall_app(ttype, serial, argc, argv);
1430 }
1431
1432 if(!strcmp(argv[0], "sync")) {
1433 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001434 int listonly = 0;
1435
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001436 int ret;
1437 if(argc < 2) {
1438 /* No local path was specified. */
1439 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001440 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1441 listonly = 1;
1442 if (argc == 3) {
1443 srcarg = argv[2];
1444 } else {
1445 srcarg = NULL;
1446 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001447 } else if(argc == 2) {
1448 /* A local path or "android"/"data" arg was specified. */
1449 srcarg = argv[1];
1450 } else {
1451 return usage();
1452 }
1453 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1454 if(ret != 0) return usage();
1455
1456 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001457 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001458 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001459 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001460
1461 free(android_srcpath);
1462 free(data_srcpath);
1463 return ret;
1464 }
1465
1466 /* passthrough commands */
1467
1468 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001469 !strcmp(argv[0],"get-serialno") ||
1470 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001471 {
1472 char *tmp;
1473
1474 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1475 tmp = adb_query(buf);
1476 if(tmp) {
1477 printf("%s\n", tmp);
1478 return 0;
1479 } else {
1480 return 1;
1481 }
1482 }
1483
1484 /* other commands */
1485
1486 if(!strcmp(argv[0],"status-window")) {
1487 status_window(ttype, serial);
1488 return 0;
1489 }
1490
Christopher Tate7b9b5162011-11-30 13:00:33 -08001491 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001492 return logcat(ttype, serial, argc, argv);
1493 }
1494
1495 if(!strcmp(argv[0],"ppp")) {
1496 return ppp(argc, argv);
1497 }
1498
1499 if (!strcmp(argv[0], "start-server")) {
1500 return adb_connect("host:start-server");
1501 }
1502
Christopher Tate73779122011-04-21 12:53:28 -07001503 if (!strcmp(argv[0], "backup")) {
1504 return backup(argc, argv);
1505 }
1506
Christopher Tatecf5379b2011-05-17 15:52:54 -07001507 if (!strcmp(argv[0], "restore")) {
1508 return restore(argc, argv);
1509 }
1510
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001511 if (!strcmp(argv[0], "jdwp")) {
1512 int fd = adb_connect("jdwp");
1513 if (fd >= 0) {
1514 read_and_dump(fd);
1515 adb_close(fd);
1516 return 0;
1517 } else {
1518 fprintf(stderr, "error: %s\n", adb_error());
1519 return -1;
1520 }
1521 }
1522
1523 /* "adb /?" is a common idiom under Windows */
1524 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1525 help();
1526 return 0;
1527 }
1528
1529 if(!strcmp(argv[0], "version")) {
1530 version(stdout);
1531 return 0;
1532 }
1533
1534 usage();
1535 return 1;
1536}
1537
1538static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1539{
1540 char *argv[16];
1541 int argc;
1542 va_list ap;
1543
1544 va_start(ap, cmd);
1545 argc = 0;
1546
1547 if (serial) {
1548 argv[argc++] = "-s";
1549 argv[argc++] = serial;
1550 } else if (ttype == kTransportUsb) {
1551 argv[argc++] = "-d";
1552 } else if (ttype == kTransportLocal) {
1553 argv[argc++] = "-e";
1554 }
1555
1556 argv[argc++] = cmd;
1557 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1558 va_end(ap);
1559
1560#if 0
1561 int n;
1562 fprintf(stderr,"argc = %d\n",argc);
1563 for(n = 0; n < argc; n++) {
1564 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1565 }
1566#endif
1567
1568 return adb_commandline(argc, argv);
1569}
1570
1571int find_sync_dirs(const char *srcarg,
1572 char **android_srcdir_out, char **data_srcdir_out)
1573{
1574 char *android_srcdir, *data_srcdir;
1575
1576 if(srcarg == NULL) {
1577 android_srcdir = product_file("system");
1578 data_srcdir = product_file("data");
1579 } else {
1580 /* srcarg may be "data", "system" or NULL.
1581 * if srcarg is NULL, then both data and system are synced
1582 */
1583 if(strcmp(srcarg, "system") == 0) {
1584 android_srcdir = product_file("system");
1585 data_srcdir = NULL;
1586 } else if(strcmp(srcarg, "data") == 0) {
1587 android_srcdir = NULL;
1588 data_srcdir = product_file("data");
1589 } else {
1590 /* It's not "system" or "data".
1591 */
1592 return 1;
1593 }
1594 }
1595
1596 if(android_srcdir_out != NULL)
1597 *android_srcdir_out = android_srcdir;
1598 else
1599 free(android_srcdir);
1600
1601 if(data_srcdir_out != NULL)
1602 *data_srcdir_out = data_srcdir;
1603 else
1604 free(data_srcdir);
1605
1606 return 0;
1607}
1608
1609static int pm_command(transport_type transport, char* serial,
1610 int argc, char** argv)
1611{
1612 char buf[4096];
1613
1614 snprintf(buf, sizeof(buf), "shell:pm");
1615
1616 while(argc-- > 0) {
1617 char *quoted;
1618
1619 quoted = dupAndQuote(*argv++);
1620
1621 strncat(buf, " ", sizeof(buf)-1);
1622 strncat(buf, quoted, sizeof(buf)-1);
1623 free(quoted);
1624 }
1625
1626 send_shellcommand(transport, serial, buf);
1627 return 0;
1628}
1629
1630int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1631{
1632 /* if the user choose the -k option, we refuse to do it until devices are
1633 out with the option to uninstall the remaining data somehow (adb/ui) */
1634 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1635 {
1636 printf(
1637 "The -k option uninstalls the application while retaining the data/cache.\n"
1638 "At the moment, there is no way to remove the remaining data.\n"
1639 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1640 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1641 return -1;
1642 }
1643
1644 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1645 return pm_command(transport, serial, argc, argv);
1646}
1647
1648static int delete_file(transport_type transport, char* serial, char* filename)
1649{
1650 char buf[4096];
1651 char* quoted;
1652
1653 snprintf(buf, sizeof(buf), "shell:rm ");
1654 quoted = dupAndQuote(filename);
1655 strncat(buf, quoted, sizeof(buf)-1);
1656 free(quoted);
1657
1658 send_shellcommand(transport, serial, buf);
1659 return 0;
1660}
1661
Kenny Root3802c992011-08-05 11:19:45 -07001662static const char* get_basename(const char* filename)
1663{
1664 const char* basename = adb_dirstop(filename);
1665 if (basename) {
1666 basename++;
1667 return basename;
1668 } else {
1669 return filename;
1670 }
1671}
1672
1673static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001674{
1675 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001676
Kenny Root3802c992011-08-05 11:19:45 -07001677 if (filename == NULL) {
1678 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001679 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001680
Kenny Root3802c992011-08-05 11:19:45 -07001681 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001682 fprintf(stderr, "can't find '%s' to install\n", filename);
1683 return 1;
1684 }
Kenny Root3802c992011-08-05 11:19:45 -07001685
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001686 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001687 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001688 return 1;
1689 }
1690
Kenny Root3802c992011-08-05 11:19:45 -07001691 return 0;
1692}
1693
1694int install_app(transport_type transport, char* serial, int argc, char** argv)
1695{
1696 static const char *const DATA_DEST = "/data/local/tmp/%s";
1697 static const char *const SD_DEST = "/sdcard/tmp/%s";
1698 const char* where = DATA_DEST;
1699 char apk_dest[PATH_MAX];
1700 char verification_dest[PATH_MAX];
1701 char* apk_file;
1702 char* verification_file = NULL;
1703 int file_arg = -1;
1704 int err;
1705 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001706 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001707
1708 for (i = 1; i < argc; i++) {
1709 if (*argv[i] != '-') {
1710 file_arg = i;
1711 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001712 } else if (!strcmp(argv[i], "-i")) {
1713 // Skip the installer package name.
1714 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001715 } else if (!strcmp(argv[i], "-s")) {
1716 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001717 } else if (!strcmp(argv[i], "--algo")) {
1718 verify_apk = 0;
1719 i++;
1720 } else if (!strcmp(argv[i], "--iv")) {
1721 verify_apk = 0;
1722 i++;
1723 } else if (!strcmp(argv[i], "--key")) {
1724 verify_apk = 0;
1725 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001726 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001727 }
1728
Kenny Root3802c992011-08-05 11:19:45 -07001729 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001730 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001731 return 1;
1732 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001733 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001734 return 1;
1735 }
1736
1737 apk_file = argv[file_arg];
1738
1739 if (file_arg != argc - 1) {
1740 verification_file = argv[file_arg + 1];
1741 }
1742
1743 if (check_file(apk_file) || check_file(verification_file)) {
1744 return 1;
1745 }
1746
1747 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1748 if (verification_file != NULL) {
1749 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1750
1751 if (!strcmp(apk_dest, verification_dest)) {
1752 fprintf(stderr, "APK and verification file can't have the same name\n");
1753 return 1;
1754 }
1755 }
1756
Mark Lindner9f9d1452014-03-11 17:55:59 -07001757 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001758 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001759 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001760 } else {
1761 argv[file_arg] = apk_dest; /* destination name, not source location */
1762 }
1763
1764 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001765 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1766 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001767 if (err) {
1768 goto cleanup_apk;
1769 } else {
1770 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1771 }
1772 }
1773
1774 pm_command(transport, serial, argc, argv);
1775
Kenny Root58d5f222012-03-26 16:14:02 -07001776cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001777 if (verification_file != NULL) {
1778 delete_file(transport, serial, verification_dest);
1779 }
1780
Kenny Root3802c992011-08-05 11:19:45 -07001781 delete_file(transport, serial, apk_dest);
1782
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001783 return err;
1784}