blob: 5df5796cd267748032bc699112fb66b10bdb9181 [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"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700113 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner9f9d1452014-03-11 17:55:59 -0700114 " - copy file/dir from device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700116 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800117 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600118 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800119 " (see 'adb help all')\n"
120 " adb shell - run remote shell interactively\n"
121 " adb shell <command> - run remote shell command\n"
122 " adb emu <command> - run emulator console command\n"
123 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100124 " adb forward --list - list all forward socket connections.\n"
125 " the format is a list of lines with the following format:\n"
126 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800127 " adb forward <local> <remote> - forward socket connections\n"
128 " forward specs are one of: \n"
129 " tcp:<port>\n"
130 " localabstract:<unix domain socket name>\n"
131 " localreserved:<unix domain socket name>\n"
132 " localfilesystem:<unix domain socket name>\n"
133 " dev:<character device name>\n"
134 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner6c489802012-11-14 15:01:55 +0100135 " adb forward --no-rebind <local> <remote>\n"
136 " - same as 'adb forward <local> <remote>' but fails\n"
137 " if <local> is already forwarded\n"
138 " adb forward --remove <local> - remove a specific forward socket connection\n"
139 " adb forward --remove-all - remove all forward socket connections\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800140 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700141 " adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700142 " - push this package file to the device and install it\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800143 " ('-l' means forward-lock the app)\n"
144 " ('-r' means reinstall the app, keeping its data)\n"
Jeff Brown8ad905b2014-04-15 13:34:04 -0700145 " ('-d' means allow version code downgrade)\n"
Mike Lockwood4cc5c012010-02-19 17:53:27 -0500146 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward5fe7ec22012-04-24 10:43:41 -0700147 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800148 " adb uninstall [-k] <package> - remove this app package from the device\n"
149 " ('-k' means keep the data and cache directories)\n"
150 " adb bugreport - return all information from the device\n"
151 " that should be included in a bug report.\n"
152 "\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800153 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700154 " - write an archive of the device's data to <file>.\n"
155 " If no -f option is supplied then the data is written\n"
156 " to \"backup.ab\" in the current directory.\n"
Christopher Tate73779122011-04-21 12:53:28 -0700157 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700158 " in the archive; the default is noapk.)\n"
Christopher Tate6f2937c2013-03-06 16:40:52 -0800159 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
160 " (aka .obb) files associated with each application; the default\n"
161 " is noobb.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700162 " (-shared|-noshared enable/disable backup of the device's\n"
163 " shared storage / SD card contents; the default is noshared.)\n"
164 " (-all means to back up all installed applications)\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700165 " (-system|-nosystem toggles whether -all automatically includes\n"
166 " system applications; the default is to include system apps)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700167 " (<packages...> is the list of applications to be backed up. If\n"
168 " the -all or -shared flags are passed, then the package\n"
Christopher Tate1cbb6df2011-10-03 18:27:01 -0700169 " list is optional. Applications explicitly given on the\n"
170 " command line will be included even if -nosystem would\n"
171 " ordinarily cause them to be omitted.)\n"
Christopher Tate73779122011-04-21 12:53:28 -0700172 "\n"
Christopher Tate24b56162011-08-09 17:05:29 -0700173 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tatecf5379b2011-05-17 15:52:54 -0700174 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800175 " adb help - show this help message\n"
176 " adb version - show version num\n"
177 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800178 "scripting:\n"
179 " adb wait-for-device - block until device is online\n"
180 " adb start-server - ensure that there is a server running\n"
181 " adb kill-server - kill the server if it is running\n"
182 " adb get-state - prints: offline | bootloader | device\n"
183 " adb get-serialno - prints: <serial-number>\n"
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700184 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800185 " adb status-window - continuously print device status for a specified device\n"
186 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood12a35ea2009-08-04 20:37:51 -0400187 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guyf925d912009-12-14 14:42:17 -0800188 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700189 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guyf925d912009-12-14 14:42:17 -0800190 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood26b88e32009-08-24 15:58:40 -0700191 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800192 "\n"
193 "networking:\n"
194 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootf8eb5782009-06-08 14:40:30 -0500195 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800196 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
197 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
198 "\n"
199 "adb sync notes: adb sync [ <directory> ]\n"
200 " <localdir> can be interpreted in several ways:\n"
201 "\n"
202 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
203 "\n"
204 " - If it is \"system\" or \"data\", only the corresponding partition\n"
205 " is updated.\n"
Tim1b29ed32010-02-16 20:18:29 +0000206 "\n"
207 "environmental variables:\n"
208 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
209 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
210 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
211 " 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 -0800212 );
213}
214
215int usage()
216{
217 help();
218 return 1;
219}
220
221#ifdef HAVE_TERMIO_H
222static struct termios tio_save;
223
224static void stdin_raw_init(int fd)
225{
226 struct termios tio;
227
228 if(tcgetattr(fd, &tio)) return;
229 if(tcgetattr(fd, &tio_save)) return;
230
231 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
232
233 /* no timeout but request at least one character per read */
234 tio.c_cc[VTIME] = 0;
235 tio.c_cc[VMIN] = 1;
236
237 tcsetattr(fd, TCSANOW, &tio);
238 tcflush(fd, TCIFLUSH);
239}
240
241static void stdin_raw_restore(int fd)
242{
243 tcsetattr(fd, TCSANOW, &tio_save);
244 tcflush(fd, TCIFLUSH);
245}
246#endif
247
248static void read_and_dump(int fd)
249{
250 char buf[4096];
251 int len;
252
253 while(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700254 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800255 len = adb_read(fd, buf, 4096);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700256 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800257 if(len == 0) {
258 break;
259 }
260
261 if(len < 0) {
262 if(errno == EINTR) continue;
263 break;
264 }
Mike Lockwood597ea9a2009-09-22 01:18:40 -0400265 fwrite(buf, 1, len, stdout);
266 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800267 }
268}
269
Christopher Tate73779122011-04-21 12:53:28 -0700270static void copy_to_file(int inFd, int outFd) {
Christopher Tatea162e242011-06-10 11:38:37 -0700271 const size_t BUFSIZE = 32 * 1024;
272 char* buf = (char*) malloc(BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700273 int len;
Christopher Tatefba22972011-06-01 17:56:23 -0700274 long total = 0;
Christopher Tate73779122011-04-21 12:53:28 -0700275
276 D("copy_to_file(%d -> %d)\n", inFd, outFd);
277 for (;;) {
Christopher Tatea162e242011-06-10 11:38:37 -0700278 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tate73779122011-04-21 12:53:28 -0700279 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700280 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700281 break;
282 }
283 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700284 if (errno == EINTR) {
285 D("copy_to_file() : EINTR, retrying\n");
286 continue;
287 }
Christopher Tate73779122011-04-21 12:53:28 -0700288 D("copy_to_file() : error %d\n", errno);
289 break;
290 }
291 adb_write(outFd, buf, len);
Christopher Tatefba22972011-06-01 17:56:23 -0700292 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700293 }
Christopher Tatefba22972011-06-01 17:56:23 -0700294 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700295 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700296}
297
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800298static void *stdin_read_thread(void *x)
299{
300 int fd, fdi;
301 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800302 int r, n;
303 int state = 0;
304
305 int *fds = (int*) x;
306 fd = fds[0];
307 fdi = fds[1];
308 free(fds);
309
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800310 for(;;) {
311 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700312 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700314 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800315 if(r == 0) break;
316 if(r < 0) {
317 if(errno == EINTR) continue;
318 break;
319 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400320 for(n = 0; n < r; n++){
321 switch(buf[n]) {
322 case '\n':
323 state = 1;
324 break;
325 case '\r':
326 state = 1;
327 break;
328 case '~':
329 if(state == 1) state++;
330 break;
331 case '.':
332 if(state == 2) {
333 fprintf(stderr,"\n* disconnect *\n");
334#ifdef HAVE_TERMIO_H
335 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800336#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400337 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800338 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400339 default:
340 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800341 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800342 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800343 r = adb_write(fd, buf, r);
344 if(r <= 0) {
345 break;
346 }
347 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800348 return 0;
349}
350
351int interactive_shell(void)
352{
353 adb_thread_t thr;
354 int fdi, fd;
355 int *fds;
356
357 fd = adb_connect("shell:");
358 if(fd < 0) {
359 fprintf(stderr,"error: %s\n", adb_error());
360 return 1;
361 }
362 fdi = 0; //dup(0);
363
364 fds = malloc(sizeof(int) * 2);
365 fds[0] = fd;
366 fds[1] = fdi;
367
368#ifdef HAVE_TERMIO_H
369 stdin_raw_init(fdi);
370#endif
371 adb_thread_create(&thr, stdin_read_thread, fds);
372 read_and_dump(fd);
373#ifdef HAVE_TERMIO_H
374 stdin_raw_restore(fdi);
375#endif
376 return 0;
377}
378
379
380static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
381{
382 if (serial) {
383 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
384 } else {
385 const char* prefix = "host";
386 if (ttype == kTransportUsb)
387 prefix = "host-usb";
388 else if (ttype == kTransportLocal)
389 prefix = "host-local";
390
391 snprintf(buffer, buflen, "%s:%s", prefix, command);
392 }
393}
394
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100395int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800396 unsigned progress)
397{
398 char buf[4096];
399 unsigned total;
400 int fd;
401 const unsigned char *ptr;
402
403 sprintf(buf,"%s:%d", service, sz);
404 fd = adb_connect(buf);
405 if(fd < 0) {
406 fprintf(stderr,"error: %s\n", adb_error());
407 return -1;
408 }
409
410 int opt = CHUNK_SIZE;
411 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
412
413 total = sz;
414 ptr = data;
415
416 if(progress) {
417 char *x = strrchr(service, ':');
418 if(x) service = x + 1;
419 }
420
421 while(sz > 0) {
422 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
423 if(writex(fd, ptr, xfer)) {
424 adb_status(fd);
425 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
426 return -1;
427 }
428 sz -= xfer;
429 ptr += xfer;
430 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100431 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800432 fflush(stdout);
433 }
434 }
435 if(progress) {
436 printf("\n");
437 }
438
439 if(readx(fd, buf, 4)){
440 fprintf(stderr,"* error reading response *\n");
441 adb_close(fd);
442 return -1;
443 }
444 if(memcmp(buf, "OKAY", 4)) {
445 buf[4] = 0;
446 fprintf(stderr,"* error response '%s' *\n", buf);
447 adb_close(fd);
448 return -1;
449 }
450
451 adb_close(fd);
452 return 0;
453}
454
455
456int adb_download(const char *service, const char *fn, unsigned progress)
457{
458 void *data;
459 unsigned sz;
460
461 data = load_file(fn, &sz);
462 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100463 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800464 return -1;
465 }
466
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100467 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800468 free(data);
469 return status;
470}
471
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800472static void status_window(transport_type ttype, const char* serial)
473{
474 char command[4096];
475 char *state = 0;
476 char *laststate = 0;
477
478 /* silence stderr */
479#ifdef _WIN32
480 /* XXX: TODO */
481#else
482 int fd;
483 fd = unix_open("/dev/null", O_WRONLY);
484 dup2(fd, 2);
485 adb_close(fd);
486#endif
487
488 format_host_command(command, sizeof command, "get-state", ttype, serial);
489
490 for(;;) {
491 adb_sleep_ms(250);
492
493 if(state) {
494 free(state);
495 state = 0;
496 }
497
498 state = adb_query(command);
499
500 if(state) {
501 if(laststate && !strcmp(state,laststate)){
502 continue;
503 } else {
504 if(laststate) free(laststate);
505 laststate = strdup(state);
506 }
507 }
508
509 printf("%c[2J%c[2H", 27, 27);
510 printf("Android Debug Bridge\n");
511 printf("State: %s\n", state ? state : "offline");
512 fflush(stdout);
513 }
514}
515
516/** duplicate string and quote all \ " ( ) chars + space character. */
517static char *
518dupAndQuote(const char *s)
519{
520 const char *ts;
521 size_t alloc_len;
522 char *ret;
523 char *dest;
524
525 ts = s;
526
527 alloc_len = 0;
528
529 for( ;*ts != '\0'; ts++) {
530 alloc_len++;
531 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
532 alloc_len++;
533 }
534 }
535
536 ret = (char *)malloc(alloc_len + 1);
537
538 ts = s;
539 dest = ret;
540
541 for ( ;*ts != '\0'; ts++) {
542 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
543 *dest++ = '\\';
544 }
545
546 *dest++ = *ts;
547 }
548
549 *dest++ = '\0';
550
551 return ret;
552}
553
554/**
555 * Run ppp in "notty" mode against a resource listed as the first parameter
556 * eg:
557 *
558 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
559 *
560 */
561int ppp(int argc, char **argv)
562{
563#ifdef HAVE_WIN32_PROC
564 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
565 return -1;
566#else
567 char *adb_service_name;
568 pid_t pid;
569 int fd;
570
571 if (argc < 2) {
572 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
573 argv[0]);
574
575 return 1;
576 }
577
578 adb_service_name = argv[1];
579
580 fd = adb_connect(adb_service_name);
581
582 if(fd < 0) {
583 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
584 adb_service_name, adb_error());
585 return 1;
586 }
587
588 pid = fork();
589
590 if (pid < 0) {
591 perror("from fork()");
592 return 1;
593 } else if (pid == 0) {
594 int err;
595 int i;
596 const char **ppp_args;
597
598 // copy args
599 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
600 ppp_args[0] = "pppd";
601 for (i = 2 ; i < argc ; i++) {
602 //argv[2] and beyond become ppp_args[1] and beyond
603 ppp_args[i - 1] = argv[i];
604 }
605 ppp_args[i-1] = NULL;
606
607 // child side
608
609 dup2(fd, STDIN_FILENO);
610 dup2(fd, STDOUT_FILENO);
611 adb_close(STDERR_FILENO);
612 adb_close(fd);
613
614 err = execvp("pppd", (char * const *)ppp_args);
615
616 if (err < 0) {
617 perror("execing pppd");
618 }
619 exit(-1);
620 } else {
621 // parent side
622
623 adb_close(fd);
624 return 0;
625 }
626#endif /* !HAVE_WIN32_PROC */
627}
628
629static int send_shellcommand(transport_type transport, char* serial, char* buf)
630{
631 int fd, ret;
632
633 for(;;) {
634 fd = adb_connect(buf);
635 if(fd >= 0)
636 break;
637 fprintf(stderr,"- waiting for device -\n");
638 adb_sleep_ms(1000);
639 do_cmd(transport, serial, "wait-for-device", 0);
640 }
641
642 read_and_dump(fd);
643 ret = adb_close(fd);
644 if (ret)
645 perror("close");
646
647 return ret;
648}
649
650static int logcat(transport_type transport, char* serial, int argc, char **argv)
651{
652 char buf[4096];
653
654 char *log_tags;
655 char *quoted_log_tags;
656
657 log_tags = getenv("ANDROID_LOG_TAGS");
658 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
659
660 snprintf(buf, sizeof(buf),
661 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
662 quoted_log_tags);
663
664 free(quoted_log_tags);
665
Christopher Tate7b9b5162011-11-30 13:00:33 -0800666 if (!strcmp(argv[0],"longcat")) {
667 strncat(buf, " -v long", sizeof(buf)-1);
668 }
669
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800670 argc -= 1;
671 argv += 1;
672 while(argc-- > 0) {
673 char *quoted;
674
675 quoted = dupAndQuote (*argv++);
676
677 strncat(buf, " ", sizeof(buf)-1);
678 strncat(buf, quoted, sizeof(buf)-1);
679 free(quoted);
680 }
681
682 send_shellcommand(transport, serial, buf);
683 return 0;
684}
685
Christopher Tate1e9f2392011-12-08 19:04:34 -0800686static int mkdirs(char *path)
687{
688 int ret;
689 char *x = path + 1;
690
691 for(;;) {
692 x = adb_dirstart(x);
693 if(x == 0) return 0;
694 *x = 0;
695 ret = adb_mkdir(path, 0775);
696 *x = OS_PATH_SEPARATOR;
697 if((ret < 0) && (errno != EEXIST)) {
698 return ret;
699 }
700 x++;
701 }
702 return 0;
703}
704
Christopher Tate73779122011-04-21 12:53:28 -0700705static int backup(int argc, char** argv) {
706 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800707 char default_name[32];
708 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700709 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700710 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700711
Christopher Tatefba22972011-06-01 17:56:23 -0700712 /* find, extract, and use any -f argument */
713 for (i = 1; i < argc; i++) {
714 if (!strcmp("-f", argv[i])) {
715 if (i == argc-1) {
716 fprintf(stderr, "adb: -f passed with no filename\n");
717 return usage();
718 }
719 filename = argv[i+1];
720 for (j = i+2; j <= argc; ) {
721 argv[i++] = argv[j++];
722 }
723 argc -= 2;
724 argv[argc] = NULL;
725 }
Christopher Tate73779122011-04-21 12:53:28 -0700726 }
727
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700728 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
729 if (argc < 2) return usage();
730
Christopher Tate1e9f2392011-12-08 19:04:34 -0800731 adb_unlink(filename);
732 mkdirs((char *)filename);
733 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700734 if (outFd < 0) {
735 fprintf(stderr, "adb: unable to open file %s\n", filename);
736 return -1;
737 }
738
739 snprintf(buf, sizeof(buf), "backup");
740 for (argc--, argv++; argc; argc--, argv++) {
741 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
742 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
743 }
744
745 D("backup. filename=%s buf=%s\n", filename, buf);
746 fd = adb_connect(buf);
747 if (fd < 0) {
748 fprintf(stderr, "adb: unable to connect for backup\n");
749 adb_close(outFd);
750 return -1;
751 }
752
Christopher Tate9c829102012-01-06 15:43:03 -0800753 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700754 copy_to_file(fd, outFd);
755
756 adb_close(fd);
757 adb_close(outFd);
758 return 0;
759}
760
Christopher Tatecf5379b2011-05-17 15:52:54 -0700761static int restore(int argc, char** argv) {
762 const char* filename;
763 int fd, tarFd;
764
765 if (argc != 2) return usage();
766
767 filename = argv[1];
768 tarFd = adb_open(filename, O_RDONLY);
769 if (tarFd < 0) {
770 fprintf(stderr, "adb: unable to open file %s\n", filename);
771 return -1;
772 }
773
774 fd = adb_connect("restore:");
775 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700776 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700777 adb_close(tarFd);
778 return -1;
779 }
780
Christopher Tate9c829102012-01-06 15:43:03 -0800781 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700782 copy_to_file(tarFd, fd);
783
784 adb_close(fd);
785 adb_close(tarFd);
786 return 0;
787}
788
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800789#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
790static int top_works(const char *top)
791{
792 if (top != NULL && adb_is_absolute_host_path(top)) {
793 char path_buf[PATH_MAX];
794 snprintf(path_buf, sizeof(path_buf),
795 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
796 return access(path_buf, F_OK) == 0;
797 }
798 return 0;
799}
800
801static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
802{
803 strcpy(path_buf, indir);
804 while (1) {
805 if (top_works(path_buf)) {
806 return path_buf;
807 }
808 char *s = adb_dirstop(path_buf);
809 if (s != NULL) {
810 *s = '\0';
811 } else {
812 path_buf[0] = '\0';
813 return NULL;
814 }
815 }
816}
817
818static char *find_top(char path_buf[PATH_MAX])
819{
820 char *top = getenv("ANDROID_BUILD_TOP");
821 if (top != NULL && top[0] != '\0') {
822 if (!top_works(top)) {
823 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
824 return NULL;
825 }
826 } else {
827 top = getenv("TOP");
828 if (top != NULL && top[0] != '\0') {
829 if (!top_works(top)) {
830 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
831 return NULL;
832 }
833 } else {
834 top = NULL;
835 }
836 }
837
838 if (top != NULL) {
839 /* The environment pointed to a top directory that works.
840 */
841 strcpy(path_buf, top);
842 return path_buf;
843 }
844
845 /* The environment didn't help. Walk up the tree from the CWD
846 * to see if we can find the top.
847 */
848 char dir[PATH_MAX];
849 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
850 if (top == NULL) {
851 /* If the CWD isn't under a good-looking top, see if the
852 * executable is.
853 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100854 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800855 top = find_top_from(dir, path_buf);
856 }
857 return top;
858}
859
860/* <hint> may be:
861 * - A simple product name
862 * e.g., "sooner"
863TODO: debug? sooner-debug, sooner:debug?
864 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
865 * e.g., "out/target/product/sooner"
866 * - An absolute path to the PRODUCT_OUT dir
867 * e.g., "/src/device/out/target/product/sooner"
868 *
869 * Given <hint>, try to construct an absolute path to the
870 * ANDROID_PRODUCT_OUT dir.
871 */
872static const char *find_product_out_path(const char *hint)
873{
874 static char path_buf[PATH_MAX];
875
876 if (hint == NULL || hint[0] == '\0') {
877 return NULL;
878 }
879
880 /* If it's already absolute, don't bother doing any work.
881 */
882 if (adb_is_absolute_host_path(hint)) {
883 strcpy(path_buf, hint);
884 return path_buf;
885 }
886
887 /* If there are any slashes in it, assume it's a relative path;
888 * make it absolute.
889 */
890 if (adb_dirstart(hint) != NULL) {
891 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
892 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
893 return NULL;
894 }
895 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
896 fprintf(stderr, "adb: Couldn't assemble path\n");
897 return NULL;
898 }
899 strcat(path_buf, OS_PATH_SEPARATOR_STR);
900 strcat(path_buf, hint);
901 return path_buf;
902 }
903
904 /* It's a string without any slashes. Try to do something with it.
905 *
906 * Try to find the root of the build tree, and build a PRODUCT_OUT
907 * path from there.
908 */
909 char top_buf[PATH_MAX];
910 const char *top = find_top(top_buf);
911 if (top == NULL) {
912 fprintf(stderr, "adb: Couldn't find top of build tree\n");
913 return NULL;
914 }
915//TODO: if we have a way to indicate debug, look in out/debug/target/...
916 snprintf(path_buf, sizeof(path_buf),
917 "%s" OS_PATH_SEPARATOR_STR
918 "out" OS_PATH_SEPARATOR_STR
919 "target" OS_PATH_SEPARATOR_STR
920 "product" OS_PATH_SEPARATOR_STR
921 "%s", top_buf, hint);
922 if (access(path_buf, F_OK) < 0) {
923 fprintf(stderr, "adb: Couldn't find a product dir "
924 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
925 return NULL;
926 }
927 return path_buf;
928}
929
Mark Lindner9f9d1452014-03-11 17:55:59 -0700930
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700931static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
932 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -0700933 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700934 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700935
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700936 while (narg > 0) {
937 if (!strcmp(*arg, "-p")) {
938 *show_progress = 1;
939 } else if (!strcmp(*arg, "-a")) {
940 *copy_attrs = 1;
941 } else {
942 break;
943 }
Mark Lindner9f9d1452014-03-11 17:55:59 -0700944 ++arg;
945 --narg;
946 }
947
948 if (narg > 0) {
949 *path1 = *arg;
950 ++arg;
951 --narg;
952 }
953
954 if (narg > 0) {
955 *path2 = *arg;
956 }
957}
958
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800959int adb_commandline(int argc, char **argv)
960{
961 char buf[4096];
962 int no_daemon = 0;
963 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100964 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800965 int persist = 0;
966 int r;
967 int quote;
968 transport_type ttype = kTransportAny;
969 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100970 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800971
972 /* If defined, this should be an absolute path to
973 * the directory containing all of the various system images
974 * for a particular product. If not defined, and the adb
975 * command requires this information, then the user must
976 * specify the path using "-p".
977 */
978 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
979 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
980 gProductOutPath = NULL;
981 }
982 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
983
Nick Pellyaf2fe9b2009-05-07 12:48:03 -0700984 serial = getenv("ANDROID_SERIAL");
985
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100986 /* Validate and assign the server port */
987 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
988 int server_port = DEFAULT_ADB_PORT;
989 if (server_port_str && strlen(server_port_str) > 0) {
990 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -0800991 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100992 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -0800993 "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 +0100994 server_port_str);
995 return usage();
996 }
997 }
998
999 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001000 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001001 if(!strcmp(argv[0],"server")) {
1002 is_server = 1;
1003 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001004 no_daemon = 1;
1005 } else if (!strcmp(argv[0], "fork-server")) {
1006 /* this is a special flag used only when the ADB client launches the ADB Server */
1007 is_daemon = 1;
1008 } else if(!strcmp(argv[0],"persist")) {
1009 persist = 1;
1010 } else if(!strncmp(argv[0], "-p", 2)) {
1011 const char *product = NULL;
1012 if (argv[0][2] == '\0') {
1013 if (argc < 2) return usage();
1014 product = argv[1];
1015 argc--;
1016 argv++;
1017 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001018 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001019 }
1020 gProductOutPath = find_product_out_path(product);
1021 if (gProductOutPath == NULL) {
1022 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1023 product);
1024 return usage();
1025 }
1026 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1027 if (isdigit(argv[0][2])) {
1028 serial = argv[0] + 2;
1029 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001030 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001031 serial = argv[1];
1032 argc--;
1033 argv++;
1034 }
1035 } else if (!strcmp(argv[0],"-d")) {
1036 ttype = kTransportUsb;
1037 } else if (!strcmp(argv[0],"-e")) {
1038 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001039 } else if (!strcmp(argv[0],"-a")) {
1040 gListenAll = 1;
1041 } else if(!strncmp(argv[0], "-H", 2)) {
1042 const char *hostname = NULL;
1043 if (argv[0][2] == '\0') {
1044 if (argc < 2) return usage();
1045 hostname = argv[1];
1046 argc--;
1047 argv++;
1048 } else {
1049 hostname = argv[0] + 2;
1050 }
1051 adb_set_tcp_name(hostname);
1052
1053 } else if(!strncmp(argv[0], "-P", 2)) {
1054 if (argv[0][2] == '\0') {
1055 if (argc < 2) return usage();
1056 server_port_str = argv[1];
1057 argc--;
1058 argv++;
1059 } else {
1060 server_port_str = argv[0] + 2;
1061 }
1062 if (strlen(server_port_str) > 0) {
1063 server_port = (int) strtol(server_port_str, NULL, 0);
1064 if (server_port <= 0 || server_port > 65535) {
1065 fprintf(stderr,
1066 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1067 server_port_str);
1068 return usage();
1069 }
1070 } else {
1071 fprintf(stderr,
1072 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1073 return usage();
1074 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001075 } else {
1076 /* out of recognized modifiers and flags */
1077 break;
1078 }
1079 argc--;
1080 argv++;
1081 }
1082
1083 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001084 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001085
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001086 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001087 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001088 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001089 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001090 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001091 }
1092 if(r) {
1093 fprintf(stderr,"* could not start server *\n");
1094 }
1095 return r;
1096 }
1097
1098top:
1099 if(argc == 0) {
1100 return usage();
1101 }
1102
1103 /* adb_connect() commands */
1104
1105 if(!strcmp(argv[0], "devices")) {
1106 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001107 char *listopt;
1108 if (argc < 2)
1109 listopt = "";
1110 else if (argc == 2 && !strcmp(argv[1], "-l"))
1111 listopt = argv[1];
1112 else {
1113 fprintf(stderr, "Usage: adb devices [-l]\n");
1114 return 1;
1115 }
1116 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001117 tmp = adb_query(buf);
1118 if(tmp) {
1119 printf("List of devices attached \n");
1120 printf("%s\n", tmp);
1121 return 0;
1122 } else {
1123 return 1;
1124 }
1125 }
1126
Mike Lockwood01c2c302010-05-24 10:44:35 -04001127 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001128 char *tmp;
1129 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001130 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001131 return 1;
1132 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001133 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1134 tmp = adb_query(buf);
1135 if(tmp) {
1136 printf("%s\n", tmp);
1137 return 0;
1138 } else {
1139 return 1;
1140 }
1141 }
1142
1143 if(!strcmp(argv[0], "disconnect")) {
1144 char *tmp;
1145 if (argc > 2) {
1146 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1147 return 1;
1148 }
1149 if (argc == 2) {
1150 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1151 } else {
1152 snprintf(buf, sizeof buf, "host:disconnect:");
1153 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001154 tmp = adb_query(buf);
1155 if(tmp) {
1156 printf("%s\n", tmp);
1157 return 0;
1158 } else {
1159 return 1;
1160 }
1161 }
1162
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001163 if (!strcmp(argv[0], "emu")) {
1164 return adb_send_emulator_command(argc, argv);
1165 }
1166
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001167 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001168 int r;
1169 int fd;
1170
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001171 char h = (argv[0][0] == 'h');
1172
1173 if (h) {
1174 printf("\x1b[41;33m");
1175 fflush(stdout);
1176 }
1177
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001178 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001179 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001180 r = interactive_shell();
1181 if (h) {
1182 printf("\x1b[0m");
1183 fflush(stdout);
1184 }
1185 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001186 }
1187
1188 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1189 argc -= 2;
1190 argv += 2;
1191 while(argc-- > 0) {
1192 strcat(buf, " ");
1193
1194 /* quote empty strings and strings with spaces */
1195 quote = (**argv == 0 || strchr(*argv, ' '));
1196 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001197 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001198 strcat(buf, *argv++);
1199 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001200 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001201 }
1202
1203 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001204 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001205 fd = adb_connect(buf);
1206 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001207 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001208 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001209 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001210 adb_close(fd);
1211 r = 0;
1212 } else {
1213 fprintf(stderr,"error: %s\n", adb_error());
1214 r = -1;
1215 }
1216
1217 if(persist) {
1218 fprintf(stderr,"\n- waiting for device -\n");
1219 adb_sleep_ms(1000);
1220 do_cmd(ttype, serial, "wait-for-device", 0);
1221 } else {
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001222 if (h) {
1223 printf("\x1b[0m");
1224 fflush(stdout);
1225 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001226 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001227 return r;
1228 }
1229 }
1230 }
1231
1232 if(!strcmp(argv[0], "kill-server")) {
1233 int fd;
1234 fd = _adb_connect("host:kill");
1235 if(fd == -1) {
1236 fprintf(stderr,"* server not running *\n");
1237 return 1;
1238 }
1239 return 0;
1240 }
1241
Doug Zongker6b217ed2012-01-09 14:54:53 -08001242 if(!strcmp(argv[0], "sideload")) {
1243 if(argc != 2) return usage();
1244 if(adb_download("sideload", argv[1], 1)) {
1245 return 1;
1246 } else {
1247 return 0;
1248 }
1249 }
1250
Mike Lockwood26b88e32009-08-24 15:58:40 -07001251 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001252 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001253 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001254 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001255 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001256 if (!strcmp(argv[0], "reboot-bootloader"))
1257 snprintf(command, sizeof(command), "reboot:bootloader");
1258 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001259 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001260 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001261 snprintf(command, sizeof(command), "%s:", argv[0]);
1262 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001263 if(fd >= 0) {
1264 read_and_dump(fd);
1265 adb_close(fd);
1266 return 0;
1267 }
1268 fprintf(stderr,"error: %s\n", adb_error());
1269 return 1;
1270 }
1271
Mike Lockwood78589f32009-09-03 14:54:58 -04001272 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001273 if (argc != 1) return usage();
1274 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001275 return 0;
1276 }
1277
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001278 /* adb_command() wrapper commands */
1279
1280 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1281 char* service = argv[0];
1282 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1283 if (ttype == kTransportUsb) {
1284 service = "wait-for-usb";
1285 } else if (ttype == kTransportLocal) {
1286 service = "wait-for-local";
1287 } else {
1288 service = "wait-for-any";
1289 }
1290 }
1291
1292 format_host_command(buf, sizeof buf, service, ttype, serial);
1293
1294 if (adb_command(buf)) {
1295 D("failure: %s *\n",adb_error());
1296 fprintf(stderr,"error: %s\n", adb_error());
1297 return 1;
1298 }
1299
1300 /* Allow a command to be run after wait-for-device,
1301 * e.g. 'adb wait-for-device shell'.
1302 */
1303 if(argc > 1) {
1304 argc--;
1305 argv++;
1306 goto top;
1307 }
1308 return 0;
1309 }
1310
1311 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001312 char host_prefix[64];
1313 char remove = 0;
1314 char remove_all = 0;
1315 char list = 0;
1316 char no_rebind = 0;
1317
1318 // Parse options here.
1319 while (argc > 1 && argv[1][0] == '-') {
1320 if (!strcmp(argv[1], "--list"))
1321 list = 1;
1322 else if (!strcmp(argv[1], "--remove"))
1323 remove = 1;
1324 else if (!strcmp(argv[1], "--remove-all"))
1325 remove_all = 1;
1326 else if (!strcmp(argv[1], "--no-rebind"))
1327 no_rebind = 1;
1328 else {
1329 return usage();
1330 }
1331 argc--;
1332 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001333 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001334
1335 // Ensure we can only use one option at a time.
1336 if (list + remove + remove_all + no_rebind > 1) {
1337 return usage();
1338 }
1339
1340 // Determine the <host-prefix> for this command.
1341 if (serial) {
1342 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1343 serial);
1344 } else if (ttype == kTransportUsb) {
1345 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1346 } else if (ttype == kTransportLocal) {
1347 snprintf(host_prefix, sizeof host_prefix, "host-local");
1348 } else {
1349 snprintf(host_prefix, sizeof host_prefix, "host");
1350 }
1351
1352 // Implement forward --list
1353 if (list) {
1354 if (argc != 1)
1355 return usage();
1356 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1357 char* forwards = adb_query(buf);
1358 if (forwards == NULL) {
1359 fprintf(stderr, "error: %s\n", adb_error());
1360 return 1;
1361 }
1362 printf("%s", forwards);
1363 free(forwards);
1364 return 0;
1365 }
1366
1367 // Implement forward --remove-all
1368 else if (remove_all) {
1369 if (argc != 1)
1370 return usage();
1371 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1372 }
1373
1374 // Implement forward --remove <local>
1375 else if (remove) {
1376 if (argc != 2)
1377 return usage();
1378 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1379 }
1380 // Or implement one of:
1381 // forward <local> <remote>
1382 // forward --no-rebind <local> <remote>
1383 else
1384 {
1385 if (argc != 3)
1386 return usage();
1387 const char* command = no_rebind ? "forward:norebind:" : "forward";
1388 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1389 }
1390
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001391 if(adb_command(buf)) {
1392 fprintf(stderr,"error: %s\n", adb_error());
1393 return 1;
1394 }
1395 return 0;
1396 }
1397
1398 /* do_sync_*() commands */
1399
1400 if(!strcmp(argv[0], "ls")) {
1401 if(argc != 2) return usage();
1402 return do_sync_ls(argv[1]);
1403 }
1404
1405 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001406 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001407 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001408 const char* lpath = NULL, *rpath = NULL;
1409
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001410 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001411
1412 if ((lpath != NULL) && (rpath != NULL)) {
1413 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1414 }
1415
1416 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001417 }
1418
1419 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001420 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001421 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001422 const char* rpath = NULL, *lpath = ".";
1423
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001424 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001425
1426 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001427 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001428 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001429
1430 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001431 }
1432
1433 if(!strcmp(argv[0], "install")) {
1434 if (argc < 2) return usage();
1435 return install_app(ttype, serial, argc, argv);
1436 }
1437
1438 if(!strcmp(argv[0], "uninstall")) {
1439 if (argc < 2) return usage();
1440 return uninstall_app(ttype, serial, argc, argv);
1441 }
1442
1443 if(!strcmp(argv[0], "sync")) {
1444 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001445 int listonly = 0;
1446
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001447 int ret;
1448 if(argc < 2) {
1449 /* No local path was specified. */
1450 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001451 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1452 listonly = 1;
1453 if (argc == 3) {
1454 srcarg = argv[2];
1455 } else {
1456 srcarg = NULL;
1457 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001458 } else if(argc == 2) {
1459 /* A local path or "android"/"data" arg was specified. */
1460 srcarg = argv[1];
1461 } else {
1462 return usage();
1463 }
1464 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1465 if(ret != 0) return usage();
1466
1467 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001468 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001469 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001470 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001471
1472 free(android_srcpath);
1473 free(data_srcpath);
1474 return ret;
1475 }
1476
1477 /* passthrough commands */
1478
1479 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001480 !strcmp(argv[0],"get-serialno") ||
1481 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001482 {
1483 char *tmp;
1484
1485 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1486 tmp = adb_query(buf);
1487 if(tmp) {
1488 printf("%s\n", tmp);
1489 return 0;
1490 } else {
1491 return 1;
1492 }
1493 }
1494
1495 /* other commands */
1496
1497 if(!strcmp(argv[0],"status-window")) {
1498 status_window(ttype, serial);
1499 return 0;
1500 }
1501
Christopher Tate7b9b5162011-11-30 13:00:33 -08001502 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001503 return logcat(ttype, serial, argc, argv);
1504 }
1505
1506 if(!strcmp(argv[0],"ppp")) {
1507 return ppp(argc, argv);
1508 }
1509
1510 if (!strcmp(argv[0], "start-server")) {
1511 return adb_connect("host:start-server");
1512 }
1513
Christopher Tate73779122011-04-21 12:53:28 -07001514 if (!strcmp(argv[0], "backup")) {
1515 return backup(argc, argv);
1516 }
1517
Christopher Tatecf5379b2011-05-17 15:52:54 -07001518 if (!strcmp(argv[0], "restore")) {
1519 return restore(argc, argv);
1520 }
1521
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001522 if (!strcmp(argv[0], "jdwp")) {
1523 int fd = adb_connect("jdwp");
1524 if (fd >= 0) {
1525 read_and_dump(fd);
1526 adb_close(fd);
1527 return 0;
1528 } else {
1529 fprintf(stderr, "error: %s\n", adb_error());
1530 return -1;
1531 }
1532 }
1533
1534 /* "adb /?" is a common idiom under Windows */
1535 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1536 help();
1537 return 0;
1538 }
1539
1540 if(!strcmp(argv[0], "version")) {
1541 version(stdout);
1542 return 0;
1543 }
1544
1545 usage();
1546 return 1;
1547}
1548
1549static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1550{
1551 char *argv[16];
1552 int argc;
1553 va_list ap;
1554
1555 va_start(ap, cmd);
1556 argc = 0;
1557
1558 if (serial) {
1559 argv[argc++] = "-s";
1560 argv[argc++] = serial;
1561 } else if (ttype == kTransportUsb) {
1562 argv[argc++] = "-d";
1563 } else if (ttype == kTransportLocal) {
1564 argv[argc++] = "-e";
1565 }
1566
1567 argv[argc++] = cmd;
1568 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1569 va_end(ap);
1570
1571#if 0
1572 int n;
1573 fprintf(stderr,"argc = %d\n",argc);
1574 for(n = 0; n < argc; n++) {
1575 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1576 }
1577#endif
1578
1579 return adb_commandline(argc, argv);
1580}
1581
1582int find_sync_dirs(const char *srcarg,
1583 char **android_srcdir_out, char **data_srcdir_out)
1584{
1585 char *android_srcdir, *data_srcdir;
1586
1587 if(srcarg == NULL) {
1588 android_srcdir = product_file("system");
1589 data_srcdir = product_file("data");
1590 } else {
1591 /* srcarg may be "data", "system" or NULL.
1592 * if srcarg is NULL, then both data and system are synced
1593 */
1594 if(strcmp(srcarg, "system") == 0) {
1595 android_srcdir = product_file("system");
1596 data_srcdir = NULL;
1597 } else if(strcmp(srcarg, "data") == 0) {
1598 android_srcdir = NULL;
1599 data_srcdir = product_file("data");
1600 } else {
1601 /* It's not "system" or "data".
1602 */
1603 return 1;
1604 }
1605 }
1606
1607 if(android_srcdir_out != NULL)
1608 *android_srcdir_out = android_srcdir;
1609 else
1610 free(android_srcdir);
1611
1612 if(data_srcdir_out != NULL)
1613 *data_srcdir_out = data_srcdir;
1614 else
1615 free(data_srcdir);
1616
1617 return 0;
1618}
1619
1620static int pm_command(transport_type transport, char* serial,
1621 int argc, char** argv)
1622{
1623 char buf[4096];
1624
1625 snprintf(buf, sizeof(buf), "shell:pm");
1626
1627 while(argc-- > 0) {
1628 char *quoted;
1629
1630 quoted = dupAndQuote(*argv++);
1631
1632 strncat(buf, " ", sizeof(buf)-1);
1633 strncat(buf, quoted, sizeof(buf)-1);
1634 free(quoted);
1635 }
1636
1637 send_shellcommand(transport, serial, buf);
1638 return 0;
1639}
1640
1641int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1642{
1643 /* if the user choose the -k option, we refuse to do it until devices are
1644 out with the option to uninstall the remaining data somehow (adb/ui) */
1645 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1646 {
1647 printf(
1648 "The -k option uninstalls the application while retaining the data/cache.\n"
1649 "At the moment, there is no way to remove the remaining data.\n"
1650 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1651 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1652 return -1;
1653 }
1654
1655 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1656 return pm_command(transport, serial, argc, argv);
1657}
1658
1659static int delete_file(transport_type transport, char* serial, char* filename)
1660{
1661 char buf[4096];
1662 char* quoted;
1663
1664 snprintf(buf, sizeof(buf), "shell:rm ");
1665 quoted = dupAndQuote(filename);
1666 strncat(buf, quoted, sizeof(buf)-1);
1667 free(quoted);
1668
1669 send_shellcommand(transport, serial, buf);
1670 return 0;
1671}
1672
Kenny Root3802c992011-08-05 11:19:45 -07001673static const char* get_basename(const char* filename)
1674{
1675 const char* basename = adb_dirstop(filename);
1676 if (basename) {
1677 basename++;
1678 return basename;
1679 } else {
1680 return filename;
1681 }
1682}
1683
1684static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001685{
1686 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001687
Kenny Root3802c992011-08-05 11:19:45 -07001688 if (filename == NULL) {
1689 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001690 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001691
Kenny Root3802c992011-08-05 11:19:45 -07001692 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001693 fprintf(stderr, "can't find '%s' to install\n", filename);
1694 return 1;
1695 }
Kenny Root3802c992011-08-05 11:19:45 -07001696
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001697 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001698 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001699 return 1;
1700 }
1701
Kenny Root3802c992011-08-05 11:19:45 -07001702 return 0;
1703}
1704
1705int install_app(transport_type transport, char* serial, int argc, char** argv)
1706{
1707 static const char *const DATA_DEST = "/data/local/tmp/%s";
1708 static const char *const SD_DEST = "/sdcard/tmp/%s";
1709 const char* where = DATA_DEST;
1710 char apk_dest[PATH_MAX];
1711 char verification_dest[PATH_MAX];
1712 char* apk_file;
1713 char* verification_file = NULL;
1714 int file_arg = -1;
1715 int err;
1716 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001717 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001718
1719 for (i = 1; i < argc; i++) {
1720 if (*argv[i] != '-') {
1721 file_arg = i;
1722 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001723 } else if (!strcmp(argv[i], "-i")) {
1724 // Skip the installer package name.
1725 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001726 } else if (!strcmp(argv[i], "-s")) {
1727 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001728 } else if (!strcmp(argv[i], "--algo")) {
1729 verify_apk = 0;
1730 i++;
1731 } else if (!strcmp(argv[i], "--iv")) {
1732 verify_apk = 0;
1733 i++;
1734 } else if (!strcmp(argv[i], "--key")) {
1735 verify_apk = 0;
1736 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001737 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001738 }
1739
Kenny Root3802c992011-08-05 11:19:45 -07001740 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001741 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001742 return 1;
1743 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001744 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001745 return 1;
1746 }
1747
1748 apk_file = argv[file_arg];
1749
1750 if (file_arg != argc - 1) {
1751 verification_file = argv[file_arg + 1];
1752 }
1753
1754 if (check_file(apk_file) || check_file(verification_file)) {
1755 return 1;
1756 }
1757
1758 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1759 if (verification_file != NULL) {
1760 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1761
1762 if (!strcmp(apk_dest, verification_dest)) {
1763 fprintf(stderr, "APK and verification file can't have the same name\n");
1764 return 1;
1765 }
1766 }
1767
Mark Lindner9f9d1452014-03-11 17:55:59 -07001768 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001769 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001770 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001771 } else {
1772 argv[file_arg] = apk_dest; /* destination name, not source location */
1773 }
1774
1775 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001776 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1777 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001778 if (err) {
1779 goto cleanup_apk;
1780 } else {
1781 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1782 }
1783 }
1784
1785 pm_command(transport, serial, argc, argv);
1786
Kenny Root58d5f222012-03-26 16:14:02 -07001787cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001788 if (verification_file != NULL) {
1789 delete_file(transport, serial, verification_dest);
1790 }
1791
Kenny Root3802c992011-08-05 11:19:45 -07001792 delete_file(transport, serial, apk_dest);
1793
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001794 return err;
1795}