blob: 3970ab155bcd056c62ae830256bd03d060e4afcb [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"
David 'Digit' Turner963a4492013-03-21 21:07:42 +0100139 " adb reverse --list - list all reverse socket connections from device\n"
140 " adb reverse <remote> <local> - reverse socket connections\n"
141 " reverse specs are one of:\n"
142 " tcp:<port>\n"
143 " localabstract:<unix domain socket name>\n"
144 " localreserved:<unix domain socket name>\n"
145 " localfilesystem:<unix domain socket name>\n"
146 " adb reverse --norebind <remote> <local>\n"
147 " - same as 'adb reverse <remote> <local>' but fails\n"
148 " if <remote> is already reversed.\n"
149 " adb reverse --remove <remote>\n"
150 " - remove a specific reversed socket connection\n"
151 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800152 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700153 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
154 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800155 " ('-l' means forward-lock the app)\n"
156 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500157 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700158 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800159 " adb uninstall [-k] <package> - remove this app package from the device\n"
160 " ('-k' means keep the data and cache directories)\n"
161 " adb bugreport - return all information from the device\n"
162 " that should be included in a bug report.\n"
163 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800164 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700165 " - write an archive of the device's data to <file>.\n"
166 " If no -f option is supplied then the data is written\n"
167 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700168 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700169 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800170 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
171 " (aka .obb) files associated with each application; the default\n"
172 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700173 " (-shared|-noshared enable/disable backup of the device's\n"
174 " shared storage / SD card contents; the default is noshared.)\n"
175 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700176 " (-system|-nosystem toggles whether -all automatically includes\n"
177 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700178 " (<packages...> is the list of applications to be backed up. If\n"
179 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700180 " list is optional. Applications explicitly given on the\n"
181 " command line will be included even if -nosystem would\n"
182 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700183 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700184 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700185 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800186 " adb help - show this help message\n"
187 " adb version - show version num\n"
188 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800189 "scripting:\n"
190 " adb wait-for-device - block until device is online\n"
191 " adb start-server - ensure that there is a server running\n"
192 " adb kill-server - kill the server if it is running\n"
193 " adb get-state - prints: offline | bootloader | device\n"
194 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700195 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800196 " adb status-window - continuously print device status for a specified device\n"
197 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400198 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800199 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700200 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800201 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700202 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800203 "\n"
204 "networking:\n"
205 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500206 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800207 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
208 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
209 "\n"
210 "adb sync notes: adb sync [ <directory> ]\n"
211 " <localdir> can be interpreted in several ways:\n"
212 "\n"
213 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
214 "\n"
215 " - If it is \"system\" or \"data\", only the corresponding partition\n"
216 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000217 "\n"
218 "environmental variables:\n"
219 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
220 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
221 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
222 " 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 -0800223 );
224}
225
226int usage()
227{
228 help();
229 return 1;
230}
231
232#ifdef HAVE_TERMIO_H
233static struct termios tio_save;
234
235static void stdin_raw_init(int fd)
236{
237 struct termios tio;
238
239 if(tcgetattr(fd, &tio)) return;
240 if(tcgetattr(fd, &tio_save)) return;
241
242 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
243
244 /* no timeout but request at least one character per read */
245 tio.c_cc[VTIME] = 0;
246 tio.c_cc[VMIN] = 1;
247
248 tcsetattr(fd, TCSANOW, &tio);
249 tcflush(fd, TCIFLUSH);
250}
251
252static void stdin_raw_restore(int fd)
253{
254 tcsetattr(fd, TCSANOW, &tio_save);
255 tcflush(fd, TCIFLUSH);
256}
257#endif
258
259static void read_and_dump(int fd)
260{
261 char buf[4096];
262 int len;
263
264 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700265 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800266 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700267 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800268 if(len == 0) {
269 break;
270 }
271
272 if(len < 0) {
273 if(errno == EINTR) continue;
274 break;
275 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400276 fwrite(buf, 1, len, stdout);
277 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800278 }
279}
280
Christopher Tate73779122011-04-21 12:53:28 -0700281static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700282 const size_t BUFSIZE = 32 * 1024;
283 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700284 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700285 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700286
287 D("copy_to_file(%d -> %d)\n", inFd, outFd);
288 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700289 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700290 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700291 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700292 break;
293 }
294 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700295 if (errno == EINTR) {
296 D("copy_to_file() : EINTR, retrying\n");
297 continue;
298 }
Christopher Tate73779122011-04-21 12:53:28 -0700299 D("copy_to_file() : error %d\n", errno);
300 break;
301 }
302 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700303 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700304 }
Christopher Tatefba22972011-06-01 17:56:23 -0700305 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700306 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700307}
308
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800309static void *stdin_read_thread(void *x)
310{
311 int fd, fdi;
312 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313 int r, n;
314 int state = 0;
315
316 int *fds = (int*) x;
317 fd = fds[0];
318 fdi = fds[1];
319 free(fds);
320
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800321 for(;;) {
322 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700323 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800324 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700325 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800326 if(r == 0) break;
327 if(r < 0) {
328 if(errno == EINTR) continue;
329 break;
330 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400331 for(n = 0; n < r; n++){
332 switch(buf[n]) {
333 case '\n':
334 state = 1;
335 break;
336 case '\r':
337 state = 1;
338 break;
339 case '~':
340 if(state == 1) state++;
341 break;
342 case '.':
343 if(state == 2) {
344 fprintf(stderr,"\n* disconnect *\n");
345#ifdef HAVE_TERMIO_H
346 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800347#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400348 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800349 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400350 default:
351 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800352 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800353 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800354 r = adb_write(fd, buf, r);
355 if(r <= 0) {
356 break;
357 }
358 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800359 return 0;
360}
361
362int interactive_shell(void)
363{
364 adb_thread_t thr;
365 int fdi, fd;
366 int *fds;
367
368 fd = adb_connect("shell:");
369 if(fd < 0) {
370 fprintf(stderr,"error: %s\n", adb_error());
371 return 1;
372 }
373 fdi = 0; //dup(0);
374
375 fds = malloc(sizeof(int) * 2);
376 fds[0] = fd;
377 fds[1] = fdi;
378
379#ifdef HAVE_TERMIO_H
380 stdin_raw_init(fdi);
381#endif
382 adb_thread_create(&thr, stdin_read_thread, fds);
383 read_and_dump(fd);
384#ifdef HAVE_TERMIO_H
385 stdin_raw_restore(fdi);
386#endif
387 return 0;
388}
389
390
391static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
392{
393 if (serial) {
394 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
395 } else {
396 const char* prefix = "host";
397 if (ttype == kTransportUsb)
398 prefix = "host-usb";
399 else if (ttype == kTransportLocal)
400 prefix = "host-local";
401
402 snprintf(buffer, buflen, "%s:%s", prefix, command);
403 }
404}
405
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100406int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800407 unsigned progress)
408{
409 char buf[4096];
410 unsigned total;
411 int fd;
412 const unsigned char *ptr;
413
414 sprintf(buf,"%s:%d", service, sz);
415 fd = adb_connect(buf);
416 if(fd < 0) {
417 fprintf(stderr,"error: %s\n", adb_error());
418 return -1;
419 }
420
421 int opt = CHUNK_SIZE;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700422 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800423
424 total = sz;
425 ptr = data;
426
427 if(progress) {
428 char *x = strrchr(service, ':');
429 if(x) service = x + 1;
430 }
431
432 while(sz > 0) {
433 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
434 if(writex(fd, ptr, xfer)) {
435 adb_status(fd);
436 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
437 return -1;
438 }
439 sz -= xfer;
440 ptr += xfer;
441 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100442 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800443 fflush(stdout);
444 }
445 }
446 if(progress) {
447 printf("\n");
448 }
449
450 if(readx(fd, buf, 4)){
451 fprintf(stderr,"* error reading response *\n");
452 adb_close(fd);
453 return -1;
454 }
455 if(memcmp(buf, "OKAY", 4)) {
456 buf[4] = 0;
457 fprintf(stderr,"* error response '%s' *\n", buf);
458 adb_close(fd);
459 return -1;
460 }
461
462 adb_close(fd);
463 return 0;
464}
465
466
467int adb_download(const char *service, const char *fn, unsigned progress)
468{
469 void *data;
470 unsigned sz;
471
472 data = load_file(fn, &sz);
473 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100474 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800475 return -1;
476 }
477
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100478 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800479 free(data);
480 return status;
481}
482
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800483static void status_window(transport_type ttype, const char* serial)
484{
485 char command[4096];
486 char *state = 0;
487 char *laststate = 0;
488
489 /* silence stderr */
490#ifdef _WIN32
491 /* XXX: TODO */
492#else
493 int fd;
494 fd = unix_open("/dev/null", O_WRONLY);
495 dup2(fd, 2);
496 adb_close(fd);
497#endif
498
499 format_host_command(command, sizeof command, "get-state", ttype, serial);
500
501 for(;;) {
502 adb_sleep_ms(250);
503
504 if(state) {
505 free(state);
506 state = 0;
507 }
508
509 state = adb_query(command);
510
511 if(state) {
512 if(laststate && !strcmp(state,laststate)){
513 continue;
514 } else {
515 if(laststate) free(laststate);
516 laststate = strdup(state);
517 }
518 }
519
520 printf("%c[2J%c[2H", 27, 27);
521 printf("Android Debug Bridge\n");
522 printf("State: %s\n", state ? state : "offline");
523 fflush(stdout);
524 }
525}
526
527/** duplicate string and quote all \ " ( ) chars + space character. */
528static char *
529dupAndQuote(const char *s)
530{
531 const char *ts;
532 size_t alloc_len;
533 char *ret;
534 char *dest;
535
536 ts = s;
537
538 alloc_len = 0;
539
540 for( ;*ts != '\0'; ts++) {
541 alloc_len++;
542 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
543 alloc_len++;
544 }
545 }
546
547 ret = (char *)malloc(alloc_len + 1);
548
549 ts = s;
550 dest = ret;
551
552 for ( ;*ts != '\0'; ts++) {
553 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
554 *dest++ = '\\';
555 }
556
557 *dest++ = *ts;
558 }
559
560 *dest++ = '\0';
561
562 return ret;
563}
564
565/**
566 * Run ppp in "notty" mode against a resource listed as the first parameter
567 * eg:
568 *
569 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
570 *
571 */
572int ppp(int argc, char **argv)
573{
574#ifdef HAVE_WIN32_PROC
575 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
576 return -1;
577#else
578 char *adb_service_name;
579 pid_t pid;
580 int fd;
581
582 if (argc < 2) {
583 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
584 argv[0]);
585
586 return 1;
587 }
588
589 adb_service_name = argv[1];
590
591 fd = adb_connect(adb_service_name);
592
593 if(fd < 0) {
594 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
595 adb_service_name, adb_error());
596 return 1;
597 }
598
599 pid = fork();
600
601 if (pid < 0) {
602 perror("from fork()");
603 return 1;
604 } else if (pid == 0) {
605 int err;
606 int i;
607 const char **ppp_args;
608
609 // copy args
610 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
611 ppp_args[0] = "pppd";
612 for (i = 2 ; i < argc ; i++) {
613 //argv[2] and beyond become ppp_args[1] and beyond
614 ppp_args[i - 1] = argv[i];
615 }
616 ppp_args[i-1] = NULL;
617
618 // child side
619
620 dup2(fd, STDIN_FILENO);
621 dup2(fd, STDOUT_FILENO);
622 adb_close(STDERR_FILENO);
623 adb_close(fd);
624
625 err = execvp("pppd", (char * const *)ppp_args);
626
627 if (err < 0) {
628 perror("execing pppd");
629 }
630 exit(-1);
631 } else {
632 // parent side
633
634 adb_close(fd);
635 return 0;
636 }
637#endif /* !HAVE_WIN32_PROC */
638}
639
640static int send_shellcommand(transport_type transport, char* serial, char* buf)
641{
642 int fd, ret;
643
644 for(;;) {
645 fd = adb_connect(buf);
646 if(fd >= 0)
647 break;
648 fprintf(stderr,"- waiting for device -\n");
649 adb_sleep_ms(1000);
650 do_cmd(transport, serial, "wait-for-device", 0);
651 }
652
653 read_and_dump(fd);
654 ret = adb_close(fd);
655 if (ret)
656 perror("close");
657
658 return ret;
659}
660
661static int logcat(transport_type transport, char* serial, int argc, char **argv)
662{
663 char buf[4096];
664
665 char *log_tags;
666 char *quoted_log_tags;
667
668 log_tags = getenv("ANDROID_LOG_TAGS");
669 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
670
671 snprintf(buf, sizeof(buf),
672 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
673 quoted_log_tags);
674
675 free(quoted_log_tags);
676
Christopher Tate7b9b5162011-11-30 13:00:33 -0800677 if (!strcmp(argv[0],"longcat")) {
678 strncat(buf, " -v long", sizeof(buf)-1);
679 }
680
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800681 argc -= 1;
682 argv += 1;
683 while(argc-- > 0) {
684 char *quoted;
685
686 quoted = dupAndQuote (*argv++);
687
688 strncat(buf, " ", sizeof(buf)-1);
689 strncat(buf, quoted, sizeof(buf)-1);
690 free(quoted);
691 }
692
693 send_shellcommand(transport, serial, buf);
694 return 0;
695}
696
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700697static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800698{
699 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700700 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800701
702 for(;;) {
703 x = adb_dirstart(x);
704 if(x == 0) return 0;
705 *x = 0;
706 ret = adb_mkdir(path, 0775);
707 *x = OS_PATH_SEPARATOR;
708 if((ret < 0) && (errno != EEXIST)) {
709 return ret;
710 }
711 x++;
712 }
713 return 0;
714}
715
Christopher Tate73779122011-04-21 12:53:28 -0700716static int backup(int argc, char** argv) {
717 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800718 char default_name[32];
719 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700720 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700721 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700722
Christopher Tatefba22972011-06-01 17:56:23 -0700723 /* find, extract, and use any -f argument */
724 for (i = 1; i < argc; i++) {
725 if (!strcmp("-f", argv[i])) {
726 if (i == argc-1) {
727 fprintf(stderr, "adb: -f passed with no filename\n");
728 return usage();
729 }
730 filename = argv[i+1];
731 for (j = i+2; j <= argc; ) {
732 argv[i++] = argv[j++];
733 }
734 argc -= 2;
735 argv[argc] = NULL;
736 }
Christopher Tate73779122011-04-21 12:53:28 -0700737 }
738
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700739 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
740 if (argc < 2) return usage();
741
Christopher Tate1e9f2392011-12-08 19:04:34 -0800742 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700743 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800744 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700745 if (outFd < 0) {
746 fprintf(stderr, "adb: unable to open file %s\n", filename);
747 return -1;
748 }
749
750 snprintf(buf, sizeof(buf), "backup");
751 for (argc--, argv++; argc; argc--, argv++) {
752 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
753 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
754 }
755
756 D("backup. filename=%s buf=%s\n", filename, buf);
757 fd = adb_connect(buf);
758 if (fd < 0) {
759 fprintf(stderr, "adb: unable to connect for backup\n");
760 adb_close(outFd);
761 return -1;
762 }
763
Christopher Tate9c829102012-01-06 15:43:03 -0800764 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700765 copy_to_file(fd, outFd);
766
767 adb_close(fd);
768 adb_close(outFd);
769 return 0;
770}
771
Christopher Tatecf5379b2011-05-17 15:52:54 -0700772static int restore(int argc, char** argv) {
773 const char* filename;
774 int fd, tarFd;
775
776 if (argc != 2) return usage();
777
778 filename = argv[1];
779 tarFd = adb_open(filename, O_RDONLY);
780 if (tarFd < 0) {
781 fprintf(stderr, "adb: unable to open file %s\n", filename);
782 return -1;
783 }
784
785 fd = adb_connect("restore:");
786 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700787 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700788 adb_close(tarFd);
789 return -1;
790 }
791
Christopher Tate9c829102012-01-06 15:43:03 -0800792 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700793 copy_to_file(tarFd, fd);
794
795 adb_close(fd);
796 adb_close(tarFd);
797 return 0;
798}
799
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800800#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
801static int top_works(const char *top)
802{
803 if (top != NULL && adb_is_absolute_host_path(top)) {
804 char path_buf[PATH_MAX];
805 snprintf(path_buf, sizeof(path_buf),
806 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
807 return access(path_buf, F_OK) == 0;
808 }
809 return 0;
810}
811
812static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
813{
814 strcpy(path_buf, indir);
815 while (1) {
816 if (top_works(path_buf)) {
817 return path_buf;
818 }
819 char *s = adb_dirstop(path_buf);
820 if (s != NULL) {
821 *s = '\0';
822 } else {
823 path_buf[0] = '\0';
824 return NULL;
825 }
826 }
827}
828
829static char *find_top(char path_buf[PATH_MAX])
830{
831 char *top = getenv("ANDROID_BUILD_TOP");
832 if (top != NULL && top[0] != '\0') {
833 if (!top_works(top)) {
834 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
835 return NULL;
836 }
837 } else {
838 top = getenv("TOP");
839 if (top != NULL && top[0] != '\0') {
840 if (!top_works(top)) {
841 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
842 return NULL;
843 }
844 } else {
845 top = NULL;
846 }
847 }
848
849 if (top != NULL) {
850 /* The environment pointed to a top directory that works.
851 */
852 strcpy(path_buf, top);
853 return path_buf;
854 }
855
856 /* The environment didn't help. Walk up the tree from the CWD
857 * to see if we can find the top.
858 */
859 char dir[PATH_MAX];
860 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
861 if (top == NULL) {
862 /* If the CWD isn't under a good-looking top, see if the
863 * executable is.
864 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100865 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800866 top = find_top_from(dir, path_buf);
867 }
868 return top;
869}
870
871/* <hint> may be:
872 * - A simple product name
873 * e.g., "sooner"
874TODO: debug? sooner-debug, sooner:debug?
875 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
876 * e.g., "out/target/product/sooner"
877 * - An absolute path to the PRODUCT_OUT dir
878 * e.g., "/src/device/out/target/product/sooner"
879 *
880 * Given <hint>, try to construct an absolute path to the
881 * ANDROID_PRODUCT_OUT dir.
882 */
883static const char *find_product_out_path(const char *hint)
884{
885 static char path_buf[PATH_MAX];
886
887 if (hint == NULL || hint[0] == '\0') {
888 return NULL;
889 }
890
891 /* If it's already absolute, don't bother doing any work.
892 */
893 if (adb_is_absolute_host_path(hint)) {
894 strcpy(path_buf, hint);
895 return path_buf;
896 }
897
898 /* If there are any slashes in it, assume it's a relative path;
899 * make it absolute.
900 */
901 if (adb_dirstart(hint) != NULL) {
902 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
903 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
904 return NULL;
905 }
906 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
907 fprintf(stderr, "adb: Couldn't assemble path\n");
908 return NULL;
909 }
910 strcat(path_buf, OS_PATH_SEPARATOR_STR);
911 strcat(path_buf, hint);
912 return path_buf;
913 }
914
915 /* It's a string without any slashes. Try to do something with it.
916 *
917 * Try to find the root of the build tree, and build a PRODUCT_OUT
918 * path from there.
919 */
920 char top_buf[PATH_MAX];
921 const char *top = find_top(top_buf);
922 if (top == NULL) {
923 fprintf(stderr, "adb: Couldn't find top of build tree\n");
924 return NULL;
925 }
926//TODO: if we have a way to indicate debug, look in out/debug/target/...
927 snprintf(path_buf, sizeof(path_buf),
928 "%s" OS_PATH_SEPARATOR_STR
929 "out" OS_PATH_SEPARATOR_STR
930 "target" OS_PATH_SEPARATOR_STR
931 "product" OS_PATH_SEPARATOR_STR
932 "%s", top_buf, hint);
933 if (access(path_buf, F_OK) < 0) {
934 fprintf(stderr, "adb: Couldn't find a product dir "
935 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
936 return NULL;
937 }
938 return path_buf;
939}
940
Mark Lindner9f9d1452014-03-11 17:55:59 -0700941
942static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2,
943 int* show_progress) {
944 *show_progress = 0;
945
946 if ((narg > 0) && !strcmp(*arg, "-p")) {
947 *show_progress = 1;
948 ++arg;
949 --narg;
950 }
951
952 if (narg > 0) {
953 *path1 = *arg;
954 ++arg;
955 --narg;
956 }
957
958 if (narg > 0) {
959 *path2 = *arg;
960 }
961}
962
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800963int adb_commandline(int argc, char **argv)
964{
965 char buf[4096];
966 int no_daemon = 0;
967 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100968 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800969 int persist = 0;
970 int r;
971 int quote;
972 transport_type ttype = kTransportAny;
973 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100974 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800975
976 /* If defined, this should be an absolute path to
977 * the directory containing all of the various system images
978 * for a particular product. If not defined, and the adb
979 * command requires this information, then the user must
980 * specify the path using "-p".
981 */
982 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
983 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
984 gProductOutPath = NULL;
985 }
986 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
987
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700988 serial = getenv("ANDROID_SERIAL");
989
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100990 /* Validate and assign the server port */
991 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
992 int server_port = DEFAULT_ADB_PORT;
993 if (server_port_str && strlen(server_port_str) > 0) {
994 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -0800995 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100996 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -0800997 "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 +0100998 server_port_str);
999 return usage();
1000 }
1001 }
1002
1003 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001004 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001005 if(!strcmp(argv[0],"server")) {
1006 is_server = 1;
1007 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001008 no_daemon = 1;
1009 } else if (!strcmp(argv[0], "fork-server")) {
1010 /* this is a special flag used only when the ADB client launches the ADB Server */
1011 is_daemon = 1;
1012 } else if(!strcmp(argv[0],"persist")) {
1013 persist = 1;
1014 } else if(!strncmp(argv[0], "-p", 2)) {
1015 const char *product = NULL;
1016 if (argv[0][2] == '\0') {
1017 if (argc < 2) return usage();
1018 product = argv[1];
1019 argc--;
1020 argv++;
1021 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001022 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001023 }
1024 gProductOutPath = find_product_out_path(product);
1025 if (gProductOutPath == NULL) {
1026 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1027 product);
1028 return usage();
1029 }
1030 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1031 if (isdigit(argv[0][2])) {
1032 serial = argv[0] + 2;
1033 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001034 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001035 serial = argv[1];
1036 argc--;
1037 argv++;
1038 }
1039 } else if (!strcmp(argv[0],"-d")) {
1040 ttype = kTransportUsb;
1041 } else if (!strcmp(argv[0],"-e")) {
1042 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001043 } else if (!strcmp(argv[0],"-a")) {
1044 gListenAll = 1;
1045 } else if(!strncmp(argv[0], "-H", 2)) {
1046 const char *hostname = NULL;
1047 if (argv[0][2] == '\0') {
1048 if (argc < 2) return usage();
1049 hostname = argv[1];
1050 argc--;
1051 argv++;
1052 } else {
1053 hostname = argv[0] + 2;
1054 }
1055 adb_set_tcp_name(hostname);
1056
1057 } else if(!strncmp(argv[0], "-P", 2)) {
1058 if (argv[0][2] == '\0') {
1059 if (argc < 2) return usage();
1060 server_port_str = argv[1];
1061 argc--;
1062 argv++;
1063 } else {
1064 server_port_str = argv[0] + 2;
1065 }
1066 if (strlen(server_port_str) > 0) {
1067 server_port = (int) strtol(server_port_str, NULL, 0);
1068 if (server_port <= 0 || server_port > 65535) {
1069 fprintf(stderr,
1070 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1071 server_port_str);
1072 return usage();
1073 }
1074 } else {
1075 fprintf(stderr,
1076 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1077 return usage();
1078 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001079 } else {
1080 /* out of recognized modifiers and flags */
1081 break;
1082 }
1083 argc--;
1084 argv++;
1085 }
1086
1087 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001088 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001089
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001090 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001091 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001092 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001093 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001094 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001095 }
1096 if(r) {
1097 fprintf(stderr,"* could not start server *\n");
1098 }
1099 return r;
1100 }
1101
1102top:
1103 if(argc == 0) {
1104 return usage();
1105 }
1106
1107 /* adb_connect() commands */
1108
1109 if(!strcmp(argv[0], "devices")) {
1110 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001111 char *listopt;
1112 if (argc < 2)
1113 listopt = "";
1114 else if (argc == 2 && !strcmp(argv[1], "-l"))
1115 listopt = argv[1];
1116 else {
1117 fprintf(stderr, "Usage: adb devices [-l]\n");
1118 return 1;
1119 }
1120 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001121 tmp = adb_query(buf);
1122 if(tmp) {
1123 printf("List of devices attached \n");
1124 printf("%s\n", tmp);
1125 return 0;
1126 } else {
1127 return 1;
1128 }
1129 }
1130
Mike Lockwood01c2c302010-05-24 10:44:35 -04001131 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001132 char *tmp;
1133 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001134 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001135 return 1;
1136 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001137 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1138 tmp = adb_query(buf);
1139 if(tmp) {
1140 printf("%s\n", tmp);
1141 return 0;
1142 } else {
1143 return 1;
1144 }
1145 }
1146
1147 if(!strcmp(argv[0], "disconnect")) {
1148 char *tmp;
1149 if (argc > 2) {
1150 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1151 return 1;
1152 }
1153 if (argc == 2) {
1154 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1155 } else {
1156 snprintf(buf, sizeof buf, "host:disconnect:");
1157 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001158 tmp = adb_query(buf);
1159 if(tmp) {
1160 printf("%s\n", tmp);
1161 return 0;
1162 } else {
1163 return 1;
1164 }
1165 }
1166
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001167 if (!strcmp(argv[0], "emu")) {
1168 return adb_send_emulator_command(argc, argv);
1169 }
1170
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001171 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001172 int r;
1173 int fd;
1174
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001175 char h = (argv[0][0] == 'h');
1176
1177 if (h) {
1178 printf("\x1b[41;33m");
1179 fflush(stdout);
1180 }
1181
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001182 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001183 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001184 r = interactive_shell();
1185 if (h) {
1186 printf("\x1b[0m");
1187 fflush(stdout);
1188 }
1189 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001190 }
1191
1192 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1193 argc -= 2;
1194 argv += 2;
1195 while(argc-- > 0) {
1196 strcat(buf, " ");
1197
1198 /* quote empty strings and strings with spaces */
1199 quote = (**argv == 0 || strchr(*argv, ' '));
1200 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001201 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001202 strcat(buf, *argv++);
1203 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001204 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001205 }
1206
1207 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001208 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001209 fd = adb_connect(buf);
1210 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001211 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001212 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001213 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001214 adb_close(fd);
1215 r = 0;
1216 } else {
1217 fprintf(stderr,"error: %s\n", adb_error());
1218 r = -1;
1219 }
1220
1221 if(persist) {
1222 fprintf(stderr,"\n- waiting for device -\n");
1223 adb_sleep_ms(1000);
1224 do_cmd(ttype, serial, "wait-for-device", 0);
1225 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001226 if (h) {
1227 printf("\x1b[0m");
1228 fflush(stdout);
1229 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001230 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001231 return r;
1232 }
1233 }
1234 }
1235
1236 if(!strcmp(argv[0], "kill-server")) {
1237 int fd;
1238 fd = _adb_connect("host:kill");
1239 if(fd == -1) {
1240 fprintf(stderr,"* server not running *\n");
1241 return 1;
1242 }
1243 return 0;
1244 }
1245
Doug Zongker6b217ed2012-01-09 14:54:53 -08001246 if(!strcmp(argv[0], "sideload")) {
1247 if(argc != 2) return usage();
1248 if(adb_download("sideload", argv[1], 1)) {
1249 return 1;
1250 } else {
1251 return 0;
1252 }
1253 }
1254
Mike Lockwood26b88e32009-08-24 15:58:40 -07001255 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001256 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001257 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001258 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001259 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001260 if (!strcmp(argv[0], "reboot-bootloader"))
1261 snprintf(command, sizeof(command), "reboot:bootloader");
1262 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001263 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001264 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001265 snprintf(command, sizeof(command), "%s:", argv[0]);
1266 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001267 if(fd >= 0) {
1268 read_and_dump(fd);
1269 adb_close(fd);
1270 return 0;
1271 }
1272 fprintf(stderr,"error: %s\n", adb_error());
1273 return 1;
1274 }
1275
Mike Lockwood78589f32009-09-03 14:54:58 -04001276 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001277 if (argc != 1) return usage();
1278 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001279 return 0;
1280 }
1281
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001282 /* adb_command() wrapper commands */
1283
1284 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1285 char* service = argv[0];
1286 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1287 if (ttype == kTransportUsb) {
1288 service = "wait-for-usb";
1289 } else if (ttype == kTransportLocal) {
1290 service = "wait-for-local";
1291 } else {
1292 service = "wait-for-any";
1293 }
1294 }
1295
1296 format_host_command(buf, sizeof buf, service, ttype, serial);
1297
1298 if (adb_command(buf)) {
1299 D("failure: %s *\n",adb_error());
1300 fprintf(stderr,"error: %s\n", adb_error());
1301 return 1;
1302 }
1303
1304 /* Allow a command to be run after wait-for-device,
1305 * e.g. 'adb wait-for-device shell'.
1306 */
1307 if(argc > 1) {
1308 argc--;
1309 argv++;
1310 goto top;
1311 }
1312 return 0;
1313 }
1314
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001315 if(!strcmp(argv[0], "forward") ||
1316 !strcmp(argv[0], "reverse"))
1317 {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001318 char host_prefix[64];
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001319 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001320 char remove = 0;
1321 char remove_all = 0;
1322 char list = 0;
1323 char no_rebind = 0;
1324
1325 // Parse options here.
1326 while (argc > 1 && argv[1][0] == '-') {
1327 if (!strcmp(argv[1], "--list"))
1328 list = 1;
1329 else if (!strcmp(argv[1], "--remove"))
1330 remove = 1;
1331 else if (!strcmp(argv[1], "--remove-all"))
1332 remove_all = 1;
1333 else if (!strcmp(argv[1], "--no-rebind"))
1334 no_rebind = 1;
1335 else {
1336 return usage();
1337 }
1338 argc--;
1339 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001340 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001341
1342 // Ensure we can only use one option at a time.
1343 if (list + remove + remove_all + no_rebind > 1) {
1344 return usage();
1345 }
1346
1347 // Determine the <host-prefix> for this command.
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001348 if (reverse) {
1349 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001350 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001351 if (serial) {
1352 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1353 serial);
1354 } else if (ttype == kTransportUsb) {
1355 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1356 } else if (ttype == kTransportLocal) {
1357 snprintf(host_prefix, sizeof host_prefix, "host-local");
1358 } else {
1359 snprintf(host_prefix, sizeof host_prefix, "host");
1360 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001361 }
1362
1363 // Implement forward --list
1364 if (list) {
1365 if (argc != 1)
1366 return usage();
1367 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1368 char* forwards = adb_query(buf);
1369 if (forwards == NULL) {
1370 fprintf(stderr, "error: %s\n", adb_error());
1371 return 1;
1372 }
1373 printf("%s", forwards);
1374 free(forwards);
1375 return 0;
1376 }
1377
1378 // Implement forward --remove-all
1379 else if (remove_all) {
1380 if (argc != 1)
1381 return usage();
1382 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1383 }
1384
1385 // Implement forward --remove <local>
1386 else if (remove) {
1387 if (argc != 2)
1388 return usage();
1389 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1390 }
1391 // Or implement one of:
1392 // forward <local> <remote>
1393 // forward --no-rebind <local> <remote>
1394 else
1395 {
1396 if (argc != 3)
1397 return usage();
1398 const char* command = no_rebind ? "forward:norebind:" : "forward";
1399 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1400 }
1401
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001402 if(adb_command(buf)) {
1403 fprintf(stderr,"error: %s\n", adb_error());
1404 return 1;
1405 }
1406 return 0;
1407 }
1408
1409 /* do_sync_*() commands */
1410
1411 if(!strcmp(argv[0], "ls")) {
1412 if(argc != 2) return usage();
1413 return do_sync_ls(argv[1]);
1414 }
1415
1416 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001417 int show_progress = 0;
1418 const char* lpath = NULL, *rpath = NULL;
1419
1420 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);
1421
1422 if ((lpath != NULL) && (rpath != NULL)) {
1423 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1424 }
1425
1426 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001427 }
1428
1429 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001430 int show_progress = 0;
1431 const char* rpath = NULL, *lpath = ".";
1432
1433 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);
1434
1435 if (rpath != NULL) {
1436 return do_sync_pull(rpath, lpath, show_progress);
Joe Onorato23595b02010-01-05 13:42:25 -08001437 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001438
1439 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001440 }
1441
1442 if(!strcmp(argv[0], "install")) {
1443 if (argc < 2) return usage();
1444 return install_app(ttype, serial, argc, argv);
1445 }
1446
1447 if(!strcmp(argv[0], "uninstall")) {
1448 if (argc < 2) return usage();
1449 return uninstall_app(ttype, serial, argc, argv);
1450 }
1451
1452 if(!strcmp(argv[0], "sync")) {
1453 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001454 int listonly = 0;
1455
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001456 int ret;
1457 if(argc < 2) {
1458 /* No local path was specified. */
1459 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001460 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1461 listonly = 1;
1462 if (argc == 3) {
1463 srcarg = argv[2];
1464 } else {
1465 srcarg = NULL;
1466 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001467 } else if(argc == 2) {
1468 /* A local path or "android"/"data" arg was specified. */
1469 srcarg = argv[1];
1470 } else {
1471 return usage();
1472 }
1473 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1474 if(ret != 0) return usage();
1475
1476 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001477 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001478 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001479 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001480
1481 free(android_srcpath);
1482 free(data_srcpath);
1483 return ret;
1484 }
1485
1486 /* passthrough commands */
1487
1488 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001489 !strcmp(argv[0],"get-serialno") ||
1490 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001491 {
1492 char *tmp;
1493
1494 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1495 tmp = adb_query(buf);
1496 if(tmp) {
1497 printf("%s\n", tmp);
1498 return 0;
1499 } else {
1500 return 1;
1501 }
1502 }
1503
1504 /* other commands */
1505
1506 if(!strcmp(argv[0],"status-window")) {
1507 status_window(ttype, serial);
1508 return 0;
1509 }
1510
Christopher Tate7b9b5162011-11-30 13:00:33 -08001511 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001512 return logcat(ttype, serial, argc, argv);
1513 }
1514
1515 if(!strcmp(argv[0],"ppp")) {
1516 return ppp(argc, argv);
1517 }
1518
1519 if (!strcmp(argv[0], "start-server")) {
1520 return adb_connect("host:start-server");
1521 }
1522
Christopher Tate73779122011-04-21 12:53:28 -07001523 if (!strcmp(argv[0], "backup")) {
1524 return backup(argc, argv);
1525 }
1526
Christopher Tatecf5379b2011-05-17 15:52:54 -07001527 if (!strcmp(argv[0], "restore")) {
1528 return restore(argc, argv);
1529 }
1530
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001531 if (!strcmp(argv[0], "jdwp")) {
1532 int fd = adb_connect("jdwp");
1533 if (fd >= 0) {
1534 read_and_dump(fd);
1535 adb_close(fd);
1536 return 0;
1537 } else {
1538 fprintf(stderr, "error: %s\n", adb_error());
1539 return -1;
1540 }
1541 }
1542
1543 /* "adb /?" is a common idiom under Windows */
1544 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1545 help();
1546 return 0;
1547 }
1548
1549 if(!strcmp(argv[0], "version")) {
1550 version(stdout);
1551 return 0;
1552 }
1553
1554 usage();
1555 return 1;
1556}
1557
1558static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1559{
1560 char *argv[16];
1561 int argc;
1562 va_list ap;
1563
1564 va_start(ap, cmd);
1565 argc = 0;
1566
1567 if (serial) {
1568 argv[argc++] = "-s";
1569 argv[argc++] = serial;
1570 } else if (ttype == kTransportUsb) {
1571 argv[argc++] = "-d";
1572 } else if (ttype == kTransportLocal) {
1573 argv[argc++] = "-e";
1574 }
1575
1576 argv[argc++] = cmd;
1577 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1578 va_end(ap);
1579
1580#if 0
1581 int n;
1582 fprintf(stderr,"argc = %d\n",argc);
1583 for(n = 0; n < argc; n++) {
1584 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1585 }
1586#endif
1587
1588 return adb_commandline(argc, argv);
1589}
1590
1591int find_sync_dirs(const char *srcarg,
1592 char **android_srcdir_out, char **data_srcdir_out)
1593{
1594 char *android_srcdir, *data_srcdir;
1595
1596 if(srcarg == NULL) {
1597 android_srcdir = product_file("system");
1598 data_srcdir = product_file("data");
1599 } else {
1600 /* srcarg may be "data", "system" or NULL.
1601 * if srcarg is NULL, then both data and system are synced
1602 */
1603 if(strcmp(srcarg, "system") == 0) {
1604 android_srcdir = product_file("system");
1605 data_srcdir = NULL;
1606 } else if(strcmp(srcarg, "data") == 0) {
1607 android_srcdir = NULL;
1608 data_srcdir = product_file("data");
1609 } else {
1610 /* It's not "system" or "data".
1611 */
1612 return 1;
1613 }
1614 }
1615
1616 if(android_srcdir_out != NULL)
1617 *android_srcdir_out = android_srcdir;
1618 else
1619 free(android_srcdir);
1620
1621 if(data_srcdir_out != NULL)
1622 *data_srcdir_out = data_srcdir;
1623 else
1624 free(data_srcdir);
1625
1626 return 0;
1627}
1628
1629static int pm_command(transport_type transport, char* serial,
1630 int argc, char** argv)
1631{
1632 char buf[4096];
1633
1634 snprintf(buf, sizeof(buf), "shell:pm");
1635
1636 while(argc-- > 0) {
1637 char *quoted;
1638
1639 quoted = dupAndQuote(*argv++);
1640
1641 strncat(buf, " ", sizeof(buf)-1);
1642 strncat(buf, quoted, sizeof(buf)-1);
1643 free(quoted);
1644 }
1645
1646 send_shellcommand(transport, serial, buf);
1647 return 0;
1648}
1649
1650int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1651{
1652 /* if the user choose the -k option, we refuse to do it until devices are
1653 out with the option to uninstall the remaining data somehow (adb/ui) */
1654 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1655 {
1656 printf(
1657 "The -k option uninstalls the application while retaining the data/cache.\n"
1658 "At the moment, there is no way to remove the remaining data.\n"
1659 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1660 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1661 return -1;
1662 }
1663
1664 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1665 return pm_command(transport, serial, argc, argv);
1666}
1667
1668static int delete_file(transport_type transport, char* serial, char* filename)
1669{
1670 char buf[4096];
1671 char* quoted;
1672
1673 snprintf(buf, sizeof(buf), "shell:rm ");
1674 quoted = dupAndQuote(filename);
1675 strncat(buf, quoted, sizeof(buf)-1);
1676 free(quoted);
1677
1678 send_shellcommand(transport, serial, buf);
1679 return 0;
1680}
1681
Kenny Root3802c992011-08-05 11:19:45 -07001682static const char* get_basename(const char* filename)
1683{
1684 const char* basename = adb_dirstop(filename);
1685 if (basename) {
1686 basename++;
1687 return basename;
1688 } else {
1689 return filename;
1690 }
1691}
1692
1693static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001694{
1695 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001696
Kenny Root3802c992011-08-05 11:19:45 -07001697 if (filename == NULL) {
1698 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001699 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001700
Kenny Root3802c992011-08-05 11:19:45 -07001701 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001702 fprintf(stderr, "can't find '%s' to install\n", filename);
1703 return 1;
1704 }
Kenny Root3802c992011-08-05 11:19:45 -07001705
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001706 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001707 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001708 return 1;
1709 }
1710
Kenny Root3802c992011-08-05 11:19:45 -07001711 return 0;
1712}
1713
1714int install_app(transport_type transport, char* serial, int argc, char** argv)
1715{
1716 static const char *const DATA_DEST = "/data/local/tmp/%s";
1717 static const char *const SD_DEST = "/sdcard/tmp/%s";
1718 const char* where = DATA_DEST;
1719 char apk_dest[PATH_MAX];
1720 char verification_dest[PATH_MAX];
1721 char* apk_file;
1722 char* verification_file = NULL;
1723 int file_arg = -1;
1724 int err;
1725 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001726 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001727
1728 for (i = 1; i < argc; i++) {
1729 if (*argv[i] != '-') {
1730 file_arg = i;
1731 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001732 } else if (!strcmp(argv[i], "-i")) {
1733 // Skip the installer package name.
1734 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001735 } else if (!strcmp(argv[i], "-s")) {
1736 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001737 } else if (!strcmp(argv[i], "--algo")) {
1738 verify_apk = 0;
1739 i++;
1740 } else if (!strcmp(argv[i], "--iv")) {
1741 verify_apk = 0;
1742 i++;
1743 } else if (!strcmp(argv[i], "--key")) {
1744 verify_apk = 0;
1745 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001746 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001747 }
1748
Kenny Root3802c992011-08-05 11:19:45 -07001749 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001750 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001751 return 1;
1752 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001753 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001754 return 1;
1755 }
1756
1757 apk_file = argv[file_arg];
1758
1759 if (file_arg != argc - 1) {
1760 verification_file = argv[file_arg + 1];
1761 }
1762
1763 if (check_file(apk_file) || check_file(verification_file)) {
1764 return 1;
1765 }
1766
1767 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1768 if (verification_file != NULL) {
1769 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1770
1771 if (!strcmp(apk_dest, verification_dest)) {
1772 fprintf(stderr, "APK and verification file can't have the same name\n");
1773 return 1;
1774 }
1775 }
1776
Mark Lindner9f9d1452014-03-11 17:55:59 -07001777 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001778 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001779 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001780 } else {
1781 argv[file_arg] = apk_dest; /* destination name, not source location */
1782 }
1783
1784 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001785 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1786 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001787 if (err) {
1788 goto cleanup_apk;
1789 } else {
1790 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1791 }
1792 }
1793
1794 pm_command(transport, serial, argc, argv);
1795
Kenny Root58d5f222012-03-26 16:14:02 -07001796cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001797 if (verification_file != NULL) {
1798 delete_file(transport, serial, verification_dest);
1799 }
1800
Kenny Root3802c992011-08-05 11:19:45 -07001801 delete_file(transport, serial, apk_dest);
1802
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001803 return err;
1804}