blob: 2e4cd373d24cfe940926fa42ca27aaba4f137cfd [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov31664102009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
44 char **android_srcdir_out, char **data_srcdir_out);
45int install_app(transport_type transport, char* serial, int argc, char** argv);
46int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47
48static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080049extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
51static char *product_file(const char *extra)
52{
53 int n;
54 char *x;
55
56 if (gProductOutPath == NULL) {
57 fprintf(stderr, "adb: Product directory not specified; "
58 "use -p or define ANDROID_PRODUCT_OUT\n");
59 exit(1);
60 }
61
62 n = strlen(gProductOutPath) + strlen(extra) + 2;
63 x = malloc(n);
64 if (x == 0) {
65 fprintf(stderr, "adb: Out of memory (product_file())\n");
66 exit(1);
67 }
68
69 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
70 return x;
71}
72
73void version(FILE * out) {
74 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
75 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
76}
77
78void help()
79{
80 version(stderr);
81
82 fprintf(stderr,
83 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080084 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085 " -d - directs command to the only connected USB device\n"
86 " returns an error if more than one USB device is present.\n"
87 " -e - directs command to the only running emulator.\n"
88 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070089 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070090 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070091 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080092 " -p <product name or path> - simple product name like 'sooner', or\n"
93 " a relative/absolute path to a product\n"
94 " out directory like 'out/target/product/sooner'.\n"
95 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
96 " environment variable is used, which must\n"
97 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080098 " -H - Name of adb server host (default: localhost)\n"
99 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700100 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700101 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400102 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
103 " Port 5555 is used by default if no port number is specified.\n"
104 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
105 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200106 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400107 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800108 "\n"
109 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700110 " adb push [-p] <local> <remote>\n"
111 " - copy file/dir to device\n"
112 " ('-p' to display the transfer progress)\n"
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 Projectdd7bc332009-03-03 19:32:55 -0800116 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600117 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-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' Turner0d82fbf2012-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 Projectdd7bc332009-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' Turner0d82fbf2012-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' Turner25258692013-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 Projectdd7bc332009-03-03 19:32:55 -0800152 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Browna77bef42014-04-15 13:34:04 -0700153 " adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700154 " - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800155 " ('-l' means forward-lock the app)\n"
156 " ('-r' means reinstall the app, keeping its data)\n"
Jeff Browna77bef42014-04-15 13:34:04 -0700157 " ('-d' means allow version code downgrade)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500158 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800160 " adb uninstall [-k] <package> - remove this app package from the device\n"
161 " ('-k' means keep the data and cache directories)\n"
162 " adb bugreport - return all information from the device\n"
163 " that should be included in a bug report.\n"
164 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800165 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700166 " - write an archive of the device's data to <file>.\n"
167 " If no -f option is supplied then the data is written\n"
168 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700169 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700170 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800171 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
172 " (aka .obb) files associated with each application; the default\n"
173 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700174 " (-shared|-noshared enable/disable backup of the device's\n"
175 " shared storage / SD card contents; the default is noshared.)\n"
176 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700177 " (-system|-nosystem toggles whether -all automatically includes\n"
178 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700179 " (<packages...> is the list of applications to be backed up. If\n"
180 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700181 " list is optional. Applications explicitly given on the\n"
182 " command line will be included even if -nosystem would\n"
183 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700184 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700185 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700186 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800187 " adb help - show this help message\n"
188 " adb version - show version num\n"
189 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 "scripting:\n"
191 " adb wait-for-device - block until device is online\n"
192 " adb start-server - ensure that there is a server running\n"
193 " adb kill-server - kill the server if it is running\n"
194 " adb get-state - prints: offline | bootloader | device\n"
195 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700196 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 " adb status-window - continuously print device status for a specified device\n"
198 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400199 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800200 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700201 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800202 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700203 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 "\n"
205 "networking:\n"
206 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500207 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
209 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
210 "\n"
211 "adb sync notes: adb sync [ <directory> ]\n"
212 " <localdir> can be interpreted in several ways:\n"
213 "\n"
214 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
215 "\n"
216 " - If it is \"system\" or \"data\", only the corresponding partition\n"
217 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000218 "\n"
219 "environmental variables:\n"
220 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
221 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
222 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
223 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800224 );
225}
226
227int usage()
228{
229 help();
230 return 1;
231}
232
233#ifdef HAVE_TERMIO_H
234static struct termios tio_save;
235
236static void stdin_raw_init(int fd)
237{
238 struct termios tio;
239
240 if(tcgetattr(fd, &tio)) return;
241 if(tcgetattr(fd, &tio_save)) return;
242
243 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
244
245 /* no timeout but request at least one character per read */
246 tio.c_cc[VTIME] = 0;
247 tio.c_cc[VMIN] = 1;
248
249 tcsetattr(fd, TCSANOW, &tio);
250 tcflush(fd, TCIFLUSH);
251}
252
253static void stdin_raw_restore(int fd)
254{
255 tcsetattr(fd, TCSANOW, &tio_save);
256 tcflush(fd, TCIFLUSH);
257}
258#endif
259
260static void read_and_dump(int fd)
261{
262 char buf[4096];
263 int len;
264
265 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700266 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700268 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269 if(len == 0) {
270 break;
271 }
272
273 if(len < 0) {
274 if(errno == EINTR) continue;
275 break;
276 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400277 fwrite(buf, 1, len, stdout);
278 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800279 }
280}
281
Christopher Tated2f54152011-04-21 12:53:28 -0700282static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700283 const size_t BUFSIZE = 32 * 1024;
284 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700285 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700286 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700287
288 D("copy_to_file(%d -> %d)\n", inFd, outFd);
289 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700290 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700291 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700292 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700293 break;
294 }
295 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700296 if (errno == EINTR) {
297 D("copy_to_file() : EINTR, retrying\n");
298 continue;
299 }
Christopher Tated2f54152011-04-21 12:53:28 -0700300 D("copy_to_file() : error %d\n", errno);
301 break;
302 }
303 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700304 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700305 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700306 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700307 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700308}
309
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800310static void *stdin_read_thread(void *x)
311{
312 int fd, fdi;
313 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800314 int r, n;
315 int state = 0;
316
317 int *fds = (int*) x;
318 fd = fds[0];
319 fdi = fds[1];
320 free(fds);
321
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800322 for(;;) {
323 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700324 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800325 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700326 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800327 if(r == 0) break;
328 if(r < 0) {
329 if(errno == EINTR) continue;
330 break;
331 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400332 for(n = 0; n < r; n++){
333 switch(buf[n]) {
334 case '\n':
335 state = 1;
336 break;
337 case '\r':
338 state = 1;
339 break;
340 case '~':
341 if(state == 1) state++;
342 break;
343 case '.':
344 if(state == 2) {
345 fprintf(stderr,"\n* disconnect *\n");
346#ifdef HAVE_TERMIO_H
347 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800348#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400349 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800350 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400351 default:
352 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800353 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800354 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800355 r = adb_write(fd, buf, r);
356 if(r <= 0) {
357 break;
358 }
359 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800360 return 0;
361}
362
363int interactive_shell(void)
364{
365 adb_thread_t thr;
366 int fdi, fd;
367 int *fds;
368
369 fd = adb_connect("shell:");
370 if(fd < 0) {
371 fprintf(stderr,"error: %s\n", adb_error());
372 return 1;
373 }
374 fdi = 0; //dup(0);
375
376 fds = malloc(sizeof(int) * 2);
377 fds[0] = fd;
378 fds[1] = fdi;
379
380#ifdef HAVE_TERMIO_H
381 stdin_raw_init(fdi);
382#endif
383 adb_thread_create(&thr, stdin_read_thread, fds);
384 read_and_dump(fd);
385#ifdef HAVE_TERMIO_H
386 stdin_raw_restore(fdi);
387#endif
388 return 0;
389}
390
391
392static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
393{
394 if (serial) {
395 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
396 } else {
397 const char* prefix = "host";
398 if (ttype == kTransportUsb)
399 prefix = "host-usb";
400 else if (ttype == kTransportLocal)
401 prefix = "host-local";
402
403 snprintf(buffer, buflen, "%s:%s", prefix, command);
404 }
405}
406
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100407int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800408 unsigned progress)
409{
410 char buf[4096];
411 unsigned total;
412 int fd;
413 const unsigned char *ptr;
414
415 sprintf(buf,"%s:%d", service, sz);
416 fd = adb_connect(buf);
417 if(fd < 0) {
418 fprintf(stderr,"error: %s\n", adb_error());
419 return -1;
420 }
421
422 int opt = CHUNK_SIZE;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700423 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800424
425 total = sz;
426 ptr = data;
427
428 if(progress) {
429 char *x = strrchr(service, ':');
430 if(x) service = x + 1;
431 }
432
433 while(sz > 0) {
434 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
435 if(writex(fd, ptr, xfer)) {
436 adb_status(fd);
437 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
438 return -1;
439 }
440 sz -= xfer;
441 ptr += xfer;
442 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100443 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800444 fflush(stdout);
445 }
446 }
447 if(progress) {
448 printf("\n");
449 }
450
451 if(readx(fd, buf, 4)){
452 fprintf(stderr,"* error reading response *\n");
453 adb_close(fd);
454 return -1;
455 }
456 if(memcmp(buf, "OKAY", 4)) {
457 buf[4] = 0;
458 fprintf(stderr,"* error response '%s' *\n", buf);
459 adb_close(fd);
460 return -1;
461 }
462
463 adb_close(fd);
464 return 0;
465}
466
467
468int adb_download(const char *service, const char *fn, unsigned progress)
469{
470 void *data;
471 unsigned sz;
472
473 data = load_file(fn, &sz);
474 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100475 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800476 return -1;
477 }
478
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100479 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800480 free(data);
481 return status;
482}
483
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800484static void status_window(transport_type ttype, const char* serial)
485{
486 char command[4096];
487 char *state = 0;
488 char *laststate = 0;
489
490 /* silence stderr */
491#ifdef _WIN32
492 /* XXX: TODO */
493#else
494 int fd;
495 fd = unix_open("/dev/null", O_WRONLY);
496 dup2(fd, 2);
497 adb_close(fd);
498#endif
499
500 format_host_command(command, sizeof command, "get-state", ttype, serial);
501
502 for(;;) {
503 adb_sleep_ms(250);
504
505 if(state) {
506 free(state);
507 state = 0;
508 }
509
510 state = adb_query(command);
511
512 if(state) {
513 if(laststate && !strcmp(state,laststate)){
514 continue;
515 } else {
516 if(laststate) free(laststate);
517 laststate = strdup(state);
518 }
519 }
520
521 printf("%c[2J%c[2H", 27, 27);
522 printf("Android Debug Bridge\n");
523 printf("State: %s\n", state ? state : "offline");
524 fflush(stdout);
525 }
526}
527
528/** duplicate string and quote all \ " ( ) chars + space character. */
529static char *
530dupAndQuote(const char *s)
531{
532 const char *ts;
533 size_t alloc_len;
534 char *ret;
535 char *dest;
536
537 ts = s;
538
539 alloc_len = 0;
540
541 for( ;*ts != '\0'; ts++) {
542 alloc_len++;
543 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
544 alloc_len++;
545 }
546 }
547
548 ret = (char *)malloc(alloc_len + 1);
549
550 ts = s;
551 dest = ret;
552
553 for ( ;*ts != '\0'; ts++) {
554 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
555 *dest++ = '\\';
556 }
557
558 *dest++ = *ts;
559 }
560
561 *dest++ = '\0';
562
563 return ret;
564}
565
566/**
567 * Run ppp in "notty" mode against a resource listed as the first parameter
568 * eg:
569 *
570 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
571 *
572 */
573int ppp(int argc, char **argv)
574{
575#ifdef HAVE_WIN32_PROC
576 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
577 return -1;
578#else
579 char *adb_service_name;
580 pid_t pid;
581 int fd;
582
583 if (argc < 2) {
584 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
585 argv[0]);
586
587 return 1;
588 }
589
590 adb_service_name = argv[1];
591
592 fd = adb_connect(adb_service_name);
593
594 if(fd < 0) {
595 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
596 adb_service_name, adb_error());
597 return 1;
598 }
599
600 pid = fork();
601
602 if (pid < 0) {
603 perror("from fork()");
604 return 1;
605 } else if (pid == 0) {
606 int err;
607 int i;
608 const char **ppp_args;
609
610 // copy args
611 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
612 ppp_args[0] = "pppd";
613 for (i = 2 ; i < argc ; i++) {
614 //argv[2] and beyond become ppp_args[1] and beyond
615 ppp_args[i - 1] = argv[i];
616 }
617 ppp_args[i-1] = NULL;
618
619 // child side
620
621 dup2(fd, STDIN_FILENO);
622 dup2(fd, STDOUT_FILENO);
623 adb_close(STDERR_FILENO);
624 adb_close(fd);
625
626 err = execvp("pppd", (char * const *)ppp_args);
627
628 if (err < 0) {
629 perror("execing pppd");
630 }
631 exit(-1);
632 } else {
633 // parent side
634
635 adb_close(fd);
636 return 0;
637 }
638#endif /* !HAVE_WIN32_PROC */
639}
640
641static int send_shellcommand(transport_type transport, char* serial, char* buf)
642{
643 int fd, ret;
644
645 for(;;) {
646 fd = adb_connect(buf);
647 if(fd >= 0)
648 break;
649 fprintf(stderr,"- waiting for device -\n");
650 adb_sleep_ms(1000);
651 do_cmd(transport, serial, "wait-for-device", 0);
652 }
653
654 read_and_dump(fd);
655 ret = adb_close(fd);
656 if (ret)
657 perror("close");
658
659 return ret;
660}
661
662static int logcat(transport_type transport, char* serial, int argc, char **argv)
663{
664 char buf[4096];
665
666 char *log_tags;
667 char *quoted_log_tags;
668
669 log_tags = getenv("ANDROID_LOG_TAGS");
670 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
671
672 snprintf(buf, sizeof(buf),
673 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
674 quoted_log_tags);
675
676 free(quoted_log_tags);
677
Christopher Tatedb0a8802011-11-30 13:00:33 -0800678 if (!strcmp(argv[0],"longcat")) {
679 strncat(buf, " -v long", sizeof(buf)-1);
680 }
681
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 argc -= 1;
683 argv += 1;
684 while(argc-- > 0) {
685 char *quoted;
686
687 quoted = dupAndQuote (*argv++);
688
689 strncat(buf, " ", sizeof(buf)-1);
690 strncat(buf, quoted, sizeof(buf)-1);
691 free(quoted);
692 }
693
694 send_shellcommand(transport, serial, buf);
695 return 0;
696}
697
Mark Salyzyn60299df2014-04-30 09:10:31 -0700698static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800699{
700 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700701 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800702
703 for(;;) {
704 x = adb_dirstart(x);
705 if(x == 0) return 0;
706 *x = 0;
707 ret = adb_mkdir(path, 0775);
708 *x = OS_PATH_SEPARATOR;
709 if((ret < 0) && (errno != EEXIST)) {
710 return ret;
711 }
712 x++;
713 }
714 return 0;
715}
716
Christopher Tated2f54152011-04-21 12:53:28 -0700717static int backup(int argc, char** argv) {
718 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800719 char default_name[32];
720 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700721 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700722 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700723
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700724 /* find, extract, and use any -f argument */
725 for (i = 1; i < argc; i++) {
726 if (!strcmp("-f", argv[i])) {
727 if (i == argc-1) {
728 fprintf(stderr, "adb: -f passed with no filename\n");
729 return usage();
730 }
731 filename = argv[i+1];
732 for (j = i+2; j <= argc; ) {
733 argv[i++] = argv[j++];
734 }
735 argc -= 2;
736 argv[argc] = NULL;
737 }
Christopher Tated2f54152011-04-21 12:53:28 -0700738 }
739
Christopher Tatebb86bc52011-08-22 17:12:08 -0700740 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
741 if (argc < 2) return usage();
742
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800743 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700744 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800745 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700746 if (outFd < 0) {
747 fprintf(stderr, "adb: unable to open file %s\n", filename);
748 return -1;
749 }
750
751 snprintf(buf, sizeof(buf), "backup");
752 for (argc--, argv++; argc; argc--, argv++) {
753 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
754 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
755 }
756
757 D("backup. filename=%s buf=%s\n", filename, buf);
758 fd = adb_connect(buf);
759 if (fd < 0) {
760 fprintf(stderr, "adb: unable to connect for backup\n");
761 adb_close(outFd);
762 return -1;
763 }
764
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800765 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700766 copy_to_file(fd, outFd);
767
768 adb_close(fd);
769 adb_close(outFd);
770 return 0;
771}
772
Christopher Tate702967a2011-05-17 15:52:54 -0700773static int restore(int argc, char** argv) {
774 const char* filename;
775 int fd, tarFd;
776
777 if (argc != 2) return usage();
778
779 filename = argv[1];
780 tarFd = adb_open(filename, O_RDONLY);
781 if (tarFd < 0) {
782 fprintf(stderr, "adb: unable to open file %s\n", filename);
783 return -1;
784 }
785
786 fd = adb_connect("restore:");
787 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700788 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700789 adb_close(tarFd);
790 return -1;
791 }
792
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800793 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700794 copy_to_file(tarFd, fd);
795
796 adb_close(fd);
797 adb_close(tarFd);
798 return 0;
799}
800
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800801#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
802static int top_works(const char *top)
803{
804 if (top != NULL && adb_is_absolute_host_path(top)) {
805 char path_buf[PATH_MAX];
806 snprintf(path_buf, sizeof(path_buf),
807 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
808 return access(path_buf, F_OK) == 0;
809 }
810 return 0;
811}
812
813static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
814{
815 strcpy(path_buf, indir);
816 while (1) {
817 if (top_works(path_buf)) {
818 return path_buf;
819 }
820 char *s = adb_dirstop(path_buf);
821 if (s != NULL) {
822 *s = '\0';
823 } else {
824 path_buf[0] = '\0';
825 return NULL;
826 }
827 }
828}
829
830static char *find_top(char path_buf[PATH_MAX])
831{
832 char *top = getenv("ANDROID_BUILD_TOP");
833 if (top != NULL && top[0] != '\0') {
834 if (!top_works(top)) {
835 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
836 return NULL;
837 }
838 } else {
839 top = getenv("TOP");
840 if (top != NULL && top[0] != '\0') {
841 if (!top_works(top)) {
842 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
843 return NULL;
844 }
845 } else {
846 top = NULL;
847 }
848 }
849
850 if (top != NULL) {
851 /* The environment pointed to a top directory that works.
852 */
853 strcpy(path_buf, top);
854 return path_buf;
855 }
856
857 /* The environment didn't help. Walk up the tree from the CWD
858 * to see if we can find the top.
859 */
860 char dir[PATH_MAX];
861 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
862 if (top == NULL) {
863 /* If the CWD isn't under a good-looking top, see if the
864 * executable is.
865 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100866 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800867 top = find_top_from(dir, path_buf);
868 }
869 return top;
870}
871
872/* <hint> may be:
873 * - A simple product name
874 * e.g., "sooner"
875TODO: debug? sooner-debug, sooner:debug?
876 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
877 * e.g., "out/target/product/sooner"
878 * - An absolute path to the PRODUCT_OUT dir
879 * e.g., "/src/device/out/target/product/sooner"
880 *
881 * Given <hint>, try to construct an absolute path to the
882 * ANDROID_PRODUCT_OUT dir.
883 */
884static const char *find_product_out_path(const char *hint)
885{
886 static char path_buf[PATH_MAX];
887
888 if (hint == NULL || hint[0] == '\0') {
889 return NULL;
890 }
891
892 /* If it's already absolute, don't bother doing any work.
893 */
894 if (adb_is_absolute_host_path(hint)) {
895 strcpy(path_buf, hint);
896 return path_buf;
897 }
898
899 /* If there are any slashes in it, assume it's a relative path;
900 * make it absolute.
901 */
902 if (adb_dirstart(hint) != NULL) {
903 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
904 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
905 return NULL;
906 }
907 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
908 fprintf(stderr, "adb: Couldn't assemble path\n");
909 return NULL;
910 }
911 strcat(path_buf, OS_PATH_SEPARATOR_STR);
912 strcat(path_buf, hint);
913 return path_buf;
914 }
915
916 /* It's a string without any slashes. Try to do something with it.
917 *
918 * Try to find the root of the build tree, and build a PRODUCT_OUT
919 * path from there.
920 */
921 char top_buf[PATH_MAX];
922 const char *top = find_top(top_buf);
923 if (top == NULL) {
924 fprintf(stderr, "adb: Couldn't find top of build tree\n");
925 return NULL;
926 }
927//TODO: if we have a way to indicate debug, look in out/debug/target/...
928 snprintf(path_buf, sizeof(path_buf),
929 "%s" OS_PATH_SEPARATOR_STR
930 "out" OS_PATH_SEPARATOR_STR
931 "target" OS_PATH_SEPARATOR_STR
932 "product" OS_PATH_SEPARATOR_STR
933 "%s", top_buf, hint);
934 if (access(path_buf, F_OK) < 0) {
935 fprintf(stderr, "adb: Couldn't find a product dir "
936 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
937 return NULL;
938 }
939 return path_buf;
940}
941
Mark Lindner76f2a932014-03-11 17:55:59 -0700942
943static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2,
944 int* show_progress) {
945 *show_progress = 0;
946
947 if ((narg > 0) && !strcmp(*arg, "-p")) {
948 *show_progress = 1;
949 ++arg;
950 --narg;
951 }
952
953 if (narg > 0) {
954 *path1 = *arg;
955 ++arg;
956 --narg;
957 }
958
959 if (narg > 0) {
960 *path2 = *arg;
961 }
962}
963
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964int adb_commandline(int argc, char **argv)
965{
966 char buf[4096];
967 int no_daemon = 0;
968 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100969 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800970 int persist = 0;
971 int r;
972 int quote;
973 transport_type ttype = kTransportAny;
974 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100975 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800976
977 /* If defined, this should be an absolute path to
978 * the directory containing all of the various system images
979 * for a particular product. If not defined, and the adb
980 * command requires this information, then the user must
981 * specify the path using "-p".
982 */
983 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
984 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
985 gProductOutPath = NULL;
986 }
987 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
988
Nick Pellydb449262009-05-07 12:48:03 -0700989 serial = getenv("ANDROID_SERIAL");
990
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100991 /* Validate and assign the server port */
992 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
993 int server_port = DEFAULT_ADB_PORT;
994 if (server_port_str && strlen(server_port_str) > 0) {
995 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800996 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100997 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800998 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100999 server_port_str);
1000 return usage();
1001 }
1002 }
1003
1004 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001005 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001006 if(!strcmp(argv[0],"server")) {
1007 is_server = 1;
1008 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001009 no_daemon = 1;
1010 } else if (!strcmp(argv[0], "fork-server")) {
1011 /* this is a special flag used only when the ADB client launches the ADB Server */
1012 is_daemon = 1;
1013 } else if(!strcmp(argv[0],"persist")) {
1014 persist = 1;
1015 } else if(!strncmp(argv[0], "-p", 2)) {
1016 const char *product = NULL;
1017 if (argv[0][2] == '\0') {
1018 if (argc < 2) return usage();
1019 product = argv[1];
1020 argc--;
1021 argv++;
1022 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001023 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001024 }
1025 gProductOutPath = find_product_out_path(product);
1026 if (gProductOutPath == NULL) {
1027 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1028 product);
1029 return usage();
1030 }
1031 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1032 if (isdigit(argv[0][2])) {
1033 serial = argv[0] + 2;
1034 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001035 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001036 serial = argv[1];
1037 argc--;
1038 argv++;
1039 }
1040 } else if (!strcmp(argv[0],"-d")) {
1041 ttype = kTransportUsb;
1042 } else if (!strcmp(argv[0],"-e")) {
1043 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001044 } else if (!strcmp(argv[0],"-a")) {
1045 gListenAll = 1;
1046 } else if(!strncmp(argv[0], "-H", 2)) {
1047 const char *hostname = NULL;
1048 if (argv[0][2] == '\0') {
1049 if (argc < 2) return usage();
1050 hostname = argv[1];
1051 argc--;
1052 argv++;
1053 } else {
1054 hostname = argv[0] + 2;
1055 }
1056 adb_set_tcp_name(hostname);
1057
1058 } else if(!strncmp(argv[0], "-P", 2)) {
1059 if (argv[0][2] == '\0') {
1060 if (argc < 2) return usage();
1061 server_port_str = argv[1];
1062 argc--;
1063 argv++;
1064 } else {
1065 server_port_str = argv[0] + 2;
1066 }
1067 if (strlen(server_port_str) > 0) {
1068 server_port = (int) strtol(server_port_str, NULL, 0);
1069 if (server_port <= 0 || server_port > 65535) {
1070 fprintf(stderr,
1071 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1072 server_port_str);
1073 return usage();
1074 }
1075 } else {
1076 fprintf(stderr,
1077 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1078 return usage();
1079 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001080 } else {
1081 /* out of recognized modifiers and flags */
1082 break;
1083 }
1084 argc--;
1085 argv++;
1086 }
1087
1088 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001089 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001090
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001091 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001092 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001093 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001094 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001095 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001096 }
1097 if(r) {
1098 fprintf(stderr,"* could not start server *\n");
1099 }
1100 return r;
1101 }
1102
1103top:
1104 if(argc == 0) {
1105 return usage();
1106 }
1107
1108 /* adb_connect() commands */
1109
1110 if(!strcmp(argv[0], "devices")) {
1111 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001112 char *listopt;
1113 if (argc < 2)
1114 listopt = "";
1115 else if (argc == 2 && !strcmp(argv[1], "-l"))
1116 listopt = argv[1];
1117 else {
1118 fprintf(stderr, "Usage: adb devices [-l]\n");
1119 return 1;
1120 }
1121 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001122 tmp = adb_query(buf);
1123 if(tmp) {
1124 printf("List of devices attached \n");
1125 printf("%s\n", tmp);
1126 return 0;
1127 } else {
1128 return 1;
1129 }
1130 }
1131
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001132 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001133 char *tmp;
1134 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001135 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001136 return 1;
1137 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001138 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1139 tmp = adb_query(buf);
1140 if(tmp) {
1141 printf("%s\n", tmp);
1142 return 0;
1143 } else {
1144 return 1;
1145 }
1146 }
1147
1148 if(!strcmp(argv[0], "disconnect")) {
1149 char *tmp;
1150 if (argc > 2) {
1151 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1152 return 1;
1153 }
1154 if (argc == 2) {
1155 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1156 } else {
1157 snprintf(buf, sizeof buf, "host:disconnect:");
1158 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001159 tmp = adb_query(buf);
1160 if(tmp) {
1161 printf("%s\n", tmp);
1162 return 0;
1163 } else {
1164 return 1;
1165 }
1166 }
1167
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001168 if (!strcmp(argv[0], "emu")) {
1169 return adb_send_emulator_command(argc, argv);
1170 }
1171
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001172 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001173 int r;
1174 int fd;
1175
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001176 char h = (argv[0][0] == 'h');
1177
1178 if (h) {
1179 printf("\x1b[41;33m");
1180 fflush(stdout);
1181 }
1182
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001183 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001184 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001185 r = interactive_shell();
1186 if (h) {
1187 printf("\x1b[0m");
1188 fflush(stdout);
1189 }
1190 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191 }
1192
1193 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1194 argc -= 2;
1195 argv += 2;
1196 while(argc-- > 0) {
1197 strcat(buf, " ");
1198
1199 /* quote empty strings and strings with spaces */
1200 quote = (**argv == 0 || strchr(*argv, ' '));
1201 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001202 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001203 strcat(buf, *argv++);
1204 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001205 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001206 }
1207
1208 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001209 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001210 fd = adb_connect(buf);
1211 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001212 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001213 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001214 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001215 adb_close(fd);
1216 r = 0;
1217 } else {
1218 fprintf(stderr,"error: %s\n", adb_error());
1219 r = -1;
1220 }
1221
1222 if(persist) {
1223 fprintf(stderr,"\n- waiting for device -\n");
1224 adb_sleep_ms(1000);
1225 do_cmd(ttype, serial, "wait-for-device", 0);
1226 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001227 if (h) {
1228 printf("\x1b[0m");
1229 fflush(stdout);
1230 }
JP Abgrall408fa572011-03-16 15:57:42 -07001231 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001232 return r;
1233 }
1234 }
1235 }
1236
1237 if(!strcmp(argv[0], "kill-server")) {
1238 int fd;
1239 fd = _adb_connect("host:kill");
1240 if(fd == -1) {
1241 fprintf(stderr,"* server not running *\n");
1242 return 1;
1243 }
1244 return 0;
1245 }
1246
Doug Zongker447f0612012-01-09 14:54:53 -08001247 if(!strcmp(argv[0], "sideload")) {
1248 if(argc != 2) return usage();
1249 if(adb_download("sideload", argv[1], 1)) {
1250 return 1;
1251 } else {
1252 return 0;
1253 }
1254 }
1255
Mike Lockwoodff196702009-08-24 15:58:40 -07001256 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001257 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001258 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001259 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001260 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001261 if (!strcmp(argv[0], "reboot-bootloader"))
1262 snprintf(command, sizeof(command), "reboot:bootloader");
1263 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001264 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001265 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001266 snprintf(command, sizeof(command), "%s:", argv[0]);
1267 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001268 if(fd >= 0) {
1269 read_and_dump(fd);
1270 adb_close(fd);
1271 return 0;
1272 }
1273 fprintf(stderr,"error: %s\n", adb_error());
1274 return 1;
1275 }
1276
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001277 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001278 if (argc != 1) return usage();
1279 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001280 return 0;
1281 }
1282
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001283 /* adb_command() wrapper commands */
1284
1285 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1286 char* service = argv[0];
1287 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1288 if (ttype == kTransportUsb) {
1289 service = "wait-for-usb";
1290 } else if (ttype == kTransportLocal) {
1291 service = "wait-for-local";
1292 } else {
1293 service = "wait-for-any";
1294 }
1295 }
1296
1297 format_host_command(buf, sizeof buf, service, ttype, serial);
1298
1299 if (adb_command(buf)) {
1300 D("failure: %s *\n",adb_error());
1301 fprintf(stderr,"error: %s\n", adb_error());
1302 return 1;
1303 }
1304
1305 /* Allow a command to be run after wait-for-device,
1306 * e.g. 'adb wait-for-device shell'.
1307 */
1308 if(argc > 1) {
1309 argc--;
1310 argv++;
1311 goto top;
1312 }
1313 return 0;
1314 }
1315
David 'Digit' Turner25258692013-03-21 21:07:42 +01001316 if(!strcmp(argv[0], "forward") ||
1317 !strcmp(argv[0], "reverse"))
1318 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001319 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001320 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001321 char remove = 0;
1322 char remove_all = 0;
1323 char list = 0;
1324 char no_rebind = 0;
1325
1326 // Parse options here.
1327 while (argc > 1 && argv[1][0] == '-') {
1328 if (!strcmp(argv[1], "--list"))
1329 list = 1;
1330 else if (!strcmp(argv[1], "--remove"))
1331 remove = 1;
1332 else if (!strcmp(argv[1], "--remove-all"))
1333 remove_all = 1;
1334 else if (!strcmp(argv[1], "--no-rebind"))
1335 no_rebind = 1;
1336 else {
1337 return usage();
1338 }
1339 argc--;
1340 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001341 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001342
1343 // Ensure we can only use one option at a time.
1344 if (list + remove + remove_all + no_rebind > 1) {
1345 return usage();
1346 }
1347
1348 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001349 if (reverse) {
1350 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001351 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001352 if (serial) {
1353 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1354 serial);
1355 } else if (ttype == kTransportUsb) {
1356 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1357 } else if (ttype == kTransportLocal) {
1358 snprintf(host_prefix, sizeof host_prefix, "host-local");
1359 } else {
1360 snprintf(host_prefix, sizeof host_prefix, "host");
1361 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001362 }
1363
1364 // Implement forward --list
1365 if (list) {
1366 if (argc != 1)
1367 return usage();
1368 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1369 char* forwards = adb_query(buf);
1370 if (forwards == NULL) {
1371 fprintf(stderr, "error: %s\n", adb_error());
1372 return 1;
1373 }
1374 printf("%s", forwards);
1375 free(forwards);
1376 return 0;
1377 }
1378
1379 // Implement forward --remove-all
1380 else if (remove_all) {
1381 if (argc != 1)
1382 return usage();
1383 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1384 }
1385
1386 // Implement forward --remove <local>
1387 else if (remove) {
1388 if (argc != 2)
1389 return usage();
1390 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1391 }
1392 // Or implement one of:
1393 // forward <local> <remote>
1394 // forward --no-rebind <local> <remote>
1395 else
1396 {
1397 if (argc != 3)
1398 return usage();
1399 const char* command = no_rebind ? "forward:norebind:" : "forward";
1400 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1401 }
1402
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 if(adb_command(buf)) {
1404 fprintf(stderr,"error: %s\n", adb_error());
1405 return 1;
1406 }
1407 return 0;
1408 }
1409
1410 /* do_sync_*() commands */
1411
1412 if(!strcmp(argv[0], "ls")) {
1413 if(argc != 2) return usage();
1414 return do_sync_ls(argv[1]);
1415 }
1416
1417 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001418 int show_progress = 0;
1419 const char* lpath = NULL, *rpath = NULL;
1420
1421 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);
1422
1423 if ((lpath != NULL) && (rpath != NULL)) {
1424 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1425 }
1426
1427 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001428 }
1429
1430 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001431 int show_progress = 0;
1432 const char* rpath = NULL, *lpath = ".";
1433
1434 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);
1435
1436 if (rpath != NULL) {
1437 return do_sync_pull(rpath, lpath, show_progress);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001438 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001439
1440 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001441 }
1442
1443 if(!strcmp(argv[0], "install")) {
1444 if (argc < 2) return usage();
1445 return install_app(ttype, serial, argc, argv);
1446 }
1447
1448 if(!strcmp(argv[0], "uninstall")) {
1449 if (argc < 2) return usage();
1450 return uninstall_app(ttype, serial, argc, argv);
1451 }
1452
1453 if(!strcmp(argv[0], "sync")) {
1454 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001455 int listonly = 0;
1456
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001457 int ret;
1458 if(argc < 2) {
1459 /* No local path was specified. */
1460 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001461 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1462 listonly = 1;
1463 if (argc == 3) {
1464 srcarg = argv[2];
1465 } else {
1466 srcarg = NULL;
1467 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001468 } else if(argc == 2) {
1469 /* A local path or "android"/"data" arg was specified. */
1470 srcarg = argv[1];
1471 } else {
1472 return usage();
1473 }
1474 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1475 if(ret != 0) return usage();
1476
1477 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001478 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001479 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001480 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001481
1482 free(android_srcpath);
1483 free(data_srcpath);
1484 return ret;
1485 }
1486
1487 /* passthrough commands */
1488
1489 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001490 !strcmp(argv[0],"get-serialno") ||
1491 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001492 {
1493 char *tmp;
1494
1495 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1496 tmp = adb_query(buf);
1497 if(tmp) {
1498 printf("%s\n", tmp);
1499 return 0;
1500 } else {
1501 return 1;
1502 }
1503 }
1504
1505 /* other commands */
1506
1507 if(!strcmp(argv[0],"status-window")) {
1508 status_window(ttype, serial);
1509 return 0;
1510 }
1511
Christopher Tatedb0a8802011-11-30 13:00:33 -08001512 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001513 return logcat(ttype, serial, argc, argv);
1514 }
1515
1516 if(!strcmp(argv[0],"ppp")) {
1517 return ppp(argc, argv);
1518 }
1519
1520 if (!strcmp(argv[0], "start-server")) {
1521 return adb_connect("host:start-server");
1522 }
1523
Christopher Tated2f54152011-04-21 12:53:28 -07001524 if (!strcmp(argv[0], "backup")) {
1525 return backup(argc, argv);
1526 }
1527
Christopher Tate702967a2011-05-17 15:52:54 -07001528 if (!strcmp(argv[0], "restore")) {
1529 return restore(argc, argv);
1530 }
1531
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001532 if (!strcmp(argv[0], "jdwp")) {
1533 int fd = adb_connect("jdwp");
1534 if (fd >= 0) {
1535 read_and_dump(fd);
1536 adb_close(fd);
1537 return 0;
1538 } else {
1539 fprintf(stderr, "error: %s\n", adb_error());
1540 return -1;
1541 }
1542 }
1543
1544 /* "adb /?" is a common idiom under Windows */
1545 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1546 help();
1547 return 0;
1548 }
1549
1550 if(!strcmp(argv[0], "version")) {
1551 version(stdout);
1552 return 0;
1553 }
1554
1555 usage();
1556 return 1;
1557}
1558
1559static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1560{
1561 char *argv[16];
1562 int argc;
1563 va_list ap;
1564
1565 va_start(ap, cmd);
1566 argc = 0;
1567
1568 if (serial) {
1569 argv[argc++] = "-s";
1570 argv[argc++] = serial;
1571 } else if (ttype == kTransportUsb) {
1572 argv[argc++] = "-d";
1573 } else if (ttype == kTransportLocal) {
1574 argv[argc++] = "-e";
1575 }
1576
1577 argv[argc++] = cmd;
1578 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1579 va_end(ap);
1580
1581#if 0
1582 int n;
1583 fprintf(stderr,"argc = %d\n",argc);
1584 for(n = 0; n < argc; n++) {
1585 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1586 }
1587#endif
1588
1589 return adb_commandline(argc, argv);
1590}
1591
1592int find_sync_dirs(const char *srcarg,
1593 char **android_srcdir_out, char **data_srcdir_out)
1594{
1595 char *android_srcdir, *data_srcdir;
1596
1597 if(srcarg == NULL) {
1598 android_srcdir = product_file("system");
1599 data_srcdir = product_file("data");
1600 } else {
1601 /* srcarg may be "data", "system" or NULL.
1602 * if srcarg is NULL, then both data and system are synced
1603 */
1604 if(strcmp(srcarg, "system") == 0) {
1605 android_srcdir = product_file("system");
1606 data_srcdir = NULL;
1607 } else if(strcmp(srcarg, "data") == 0) {
1608 android_srcdir = NULL;
1609 data_srcdir = product_file("data");
1610 } else {
1611 /* It's not "system" or "data".
1612 */
1613 return 1;
1614 }
1615 }
1616
1617 if(android_srcdir_out != NULL)
1618 *android_srcdir_out = android_srcdir;
1619 else
1620 free(android_srcdir);
1621
1622 if(data_srcdir_out != NULL)
1623 *data_srcdir_out = data_srcdir;
1624 else
1625 free(data_srcdir);
1626
1627 return 0;
1628}
1629
1630static int pm_command(transport_type transport, char* serial,
1631 int argc, char** argv)
1632{
1633 char buf[4096];
1634
1635 snprintf(buf, sizeof(buf), "shell:pm");
1636
1637 while(argc-- > 0) {
1638 char *quoted;
1639
1640 quoted = dupAndQuote(*argv++);
1641
1642 strncat(buf, " ", sizeof(buf)-1);
1643 strncat(buf, quoted, sizeof(buf)-1);
1644 free(quoted);
1645 }
1646
1647 send_shellcommand(transport, serial, buf);
1648 return 0;
1649}
1650
1651int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1652{
1653 /* if the user choose the -k option, we refuse to do it until devices are
1654 out with the option to uninstall the remaining data somehow (adb/ui) */
1655 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1656 {
1657 printf(
1658 "The -k option uninstalls the application while retaining the data/cache.\n"
1659 "At the moment, there is no way to remove the remaining data.\n"
1660 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1661 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1662 return -1;
1663 }
1664
1665 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1666 return pm_command(transport, serial, argc, argv);
1667}
1668
1669static int delete_file(transport_type transport, char* serial, char* filename)
1670{
1671 char buf[4096];
1672 char* quoted;
1673
1674 snprintf(buf, sizeof(buf), "shell:rm ");
1675 quoted = dupAndQuote(filename);
1676 strncat(buf, quoted, sizeof(buf)-1);
1677 free(quoted);
1678
1679 send_shellcommand(transport, serial, buf);
1680 return 0;
1681}
1682
Kenny Root597ea5b2011-08-05 11:19:45 -07001683static const char* get_basename(const char* filename)
1684{
1685 const char* basename = adb_dirstop(filename);
1686 if (basename) {
1687 basename++;
1688 return basename;
1689 } else {
1690 return filename;
1691 }
1692}
1693
1694static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001695{
1696 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001697
Kenny Root597ea5b2011-08-05 11:19:45 -07001698 if (filename == NULL) {
1699 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001700 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001701
Kenny Root597ea5b2011-08-05 11:19:45 -07001702 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001703 fprintf(stderr, "can't find '%s' to install\n", filename);
1704 return 1;
1705 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001706
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001707 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001708 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001709 return 1;
1710 }
1711
Kenny Root597ea5b2011-08-05 11:19:45 -07001712 return 0;
1713}
1714
1715int install_app(transport_type transport, char* serial, int argc, char** argv)
1716{
1717 static const char *const DATA_DEST = "/data/local/tmp/%s";
1718 static const char *const SD_DEST = "/sdcard/tmp/%s";
1719 const char* where = DATA_DEST;
1720 char apk_dest[PATH_MAX];
1721 char verification_dest[PATH_MAX];
1722 char* apk_file;
1723 char* verification_file = NULL;
1724 int file_arg = -1;
1725 int err;
1726 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001727 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001728
1729 for (i = 1; i < argc; i++) {
1730 if (*argv[i] != '-') {
1731 file_arg = i;
1732 break;
Kenny Roota031a912011-09-23 12:46:39 -07001733 } else if (!strcmp(argv[i], "-i")) {
1734 // Skip the installer package name.
1735 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001736 } else if (!strcmp(argv[i], "-s")) {
1737 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001738 } else if (!strcmp(argv[i], "--algo")) {
1739 verify_apk = 0;
1740 i++;
1741 } else if (!strcmp(argv[i], "--iv")) {
1742 verify_apk = 0;
1743 i++;
1744 } else if (!strcmp(argv[i], "--key")) {
1745 verify_apk = 0;
1746 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001747 } else if (!strcmp(argv[i], "--abi")) {
1748 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001749 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001750 }
1751
Kenny Root597ea5b2011-08-05 11:19:45 -07001752 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001753 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001754 return 1;
1755 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001756 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001757 return 1;
1758 }
1759
1760 apk_file = argv[file_arg];
1761
1762 if (file_arg != argc - 1) {
1763 verification_file = argv[file_arg + 1];
1764 }
1765
1766 if (check_file(apk_file) || check_file(verification_file)) {
1767 return 1;
1768 }
1769
1770 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1771 if (verification_file != NULL) {
1772 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1773
1774 if (!strcmp(apk_dest, verification_dest)) {
1775 fprintf(stderr, "APK and verification file can't have the same name\n");
1776 return 1;
1777 }
1778 }
1779
Mark Lindner76f2a932014-03-11 17:55:59 -07001780 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001781 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001782 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001783 } else {
1784 argv[file_arg] = apk_dest; /* destination name, not source location */
1785 }
1786
1787 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001788 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1789 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001790 if (err) {
1791 goto cleanup_apk;
1792 } else {
1793 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1794 }
1795 }
1796
1797 pm_command(transport, serial, argc, argv);
1798
Kenny Root60733e92012-03-26 16:14:02 -07001799cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001800 if (verification_file != NULL) {
1801 delete_file(transport, serial, verification_dest);
1802 }
1803
Kenny Root597ea5b2011-08-05 11:19:45 -07001804 delete_file(transport, serial, apk_dest);
1805
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001806 return err;
1807}