blob: 9cba7519dce3f72b4802ac15f5c5c5dd4143081a [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"
Lajos Molnar4b35c012013-04-19 12:41:09 -0700113 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700114 " - copy file/dir from device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnar4b35c012013-04-19 12:41:09 -0700116 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800117 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600118 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-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' Turner0d82fbf2012-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 Projectdd7bc332009-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' Turner0d82fbf2012-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"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100140 " adb reverse --list - list all reverse socket connections from device\n"
141 " adb reverse <remote> <local> - reverse socket connections\n"
142 " reverse specs are one of:\n"
143 " tcp:<port>\n"
144 " localabstract:<unix domain socket name>\n"
145 " localreserved:<unix domain socket name>\n"
146 " localfilesystem:<unix domain socket name>\n"
147 " adb reverse --norebind <remote> <local>\n"
148 " - same as 'adb reverse <remote> <local>' but fails\n"
149 " if <remote> is already reversed.\n"
150 " adb reverse --remove <remote>\n"
151 " - remove a specific reversed socket connection\n"
152 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800153 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700154 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
155 " - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 " ('-l' means forward-lock the app)\n"
157 " ('-r' means reinstall the app, keeping its data)\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
Lajos Molnar4b35c012013-04-19 12:41:09 -0700943static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
944 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700945 *show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -0700946 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700947
Lajos Molnar4b35c012013-04-19 12:41:09 -0700948 while (narg > 0) {
949 if (!strcmp(*arg, "-p")) {
950 *show_progress = 1;
951 } else if (!strcmp(*arg, "-a")) {
952 *copy_attrs = 1;
953 } else {
954 break;
955 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700956 ++arg;
957 --narg;
958 }
959
960 if (narg > 0) {
961 *path1 = *arg;
962 ++arg;
963 --narg;
964 }
965
966 if (narg > 0) {
967 *path2 = *arg;
968 }
969}
970
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800971int adb_commandline(int argc, char **argv)
972{
973 char buf[4096];
974 int no_daemon = 0;
975 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100976 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800977 int persist = 0;
978 int r;
979 int quote;
980 transport_type ttype = kTransportAny;
981 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100982 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800983
984 /* If defined, this should be an absolute path to
985 * the directory containing all of the various system images
986 * for a particular product. If not defined, and the adb
987 * command requires this information, then the user must
988 * specify the path using "-p".
989 */
990 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
991 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
992 gProductOutPath = NULL;
993 }
994 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
995
Nick Pellydb449262009-05-07 12:48:03 -0700996 serial = getenv("ANDROID_SERIAL");
997
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100998 /* Validate and assign the server port */
999 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1000 int server_port = DEFAULT_ADB_PORT;
1001 if (server_port_str && strlen(server_port_str) > 0) {
1002 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001003 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001004 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001005 "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 +01001006 server_port_str);
1007 return usage();
1008 }
1009 }
1010
1011 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001013 if(!strcmp(argv[0],"server")) {
1014 is_server = 1;
1015 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001016 no_daemon = 1;
1017 } else if (!strcmp(argv[0], "fork-server")) {
1018 /* this is a special flag used only when the ADB client launches the ADB Server */
1019 is_daemon = 1;
1020 } else if(!strcmp(argv[0],"persist")) {
1021 persist = 1;
1022 } else if(!strncmp(argv[0], "-p", 2)) {
1023 const char *product = NULL;
1024 if (argv[0][2] == '\0') {
1025 if (argc < 2) return usage();
1026 product = argv[1];
1027 argc--;
1028 argv++;
1029 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001030 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001031 }
1032 gProductOutPath = find_product_out_path(product);
1033 if (gProductOutPath == NULL) {
1034 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1035 product);
1036 return usage();
1037 }
1038 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1039 if (isdigit(argv[0][2])) {
1040 serial = argv[0] + 2;
1041 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001042 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001043 serial = argv[1];
1044 argc--;
1045 argv++;
1046 }
1047 } else if (!strcmp(argv[0],"-d")) {
1048 ttype = kTransportUsb;
1049 } else if (!strcmp(argv[0],"-e")) {
1050 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001051 } else if (!strcmp(argv[0],"-a")) {
1052 gListenAll = 1;
1053 } else if(!strncmp(argv[0], "-H", 2)) {
1054 const char *hostname = NULL;
1055 if (argv[0][2] == '\0') {
1056 if (argc < 2) return usage();
1057 hostname = argv[1];
1058 argc--;
1059 argv++;
1060 } else {
1061 hostname = argv[0] + 2;
1062 }
1063 adb_set_tcp_name(hostname);
1064
1065 } else if(!strncmp(argv[0], "-P", 2)) {
1066 if (argv[0][2] == '\0') {
1067 if (argc < 2) return usage();
1068 server_port_str = argv[1];
1069 argc--;
1070 argv++;
1071 } else {
1072 server_port_str = argv[0] + 2;
1073 }
1074 if (strlen(server_port_str) > 0) {
1075 server_port = (int) strtol(server_port_str, NULL, 0);
1076 if (server_port <= 0 || server_port > 65535) {
1077 fprintf(stderr,
1078 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1079 server_port_str);
1080 return usage();
1081 }
1082 } else {
1083 fprintf(stderr,
1084 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1085 return usage();
1086 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001087 } else {
1088 /* out of recognized modifiers and flags */
1089 break;
1090 }
1091 argc--;
1092 argv++;
1093 }
1094
1095 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001096 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001097
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001098 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001099 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001100 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001101 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001102 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001103 }
1104 if(r) {
1105 fprintf(stderr,"* could not start server *\n");
1106 }
1107 return r;
1108 }
1109
1110top:
1111 if(argc == 0) {
1112 return usage();
1113 }
1114
1115 /* adb_connect() commands */
1116
1117 if(!strcmp(argv[0], "devices")) {
1118 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001119 char *listopt;
1120 if (argc < 2)
1121 listopt = "";
1122 else if (argc == 2 && !strcmp(argv[1], "-l"))
1123 listopt = argv[1];
1124 else {
1125 fprintf(stderr, "Usage: adb devices [-l]\n");
1126 return 1;
1127 }
1128 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001129 tmp = adb_query(buf);
1130 if(tmp) {
1131 printf("List of devices attached \n");
1132 printf("%s\n", tmp);
1133 return 0;
1134 } else {
1135 return 1;
1136 }
1137 }
1138
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001139 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001140 char *tmp;
1141 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001142 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001143 return 1;
1144 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001145 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1146 tmp = adb_query(buf);
1147 if(tmp) {
1148 printf("%s\n", tmp);
1149 return 0;
1150 } else {
1151 return 1;
1152 }
1153 }
1154
1155 if(!strcmp(argv[0], "disconnect")) {
1156 char *tmp;
1157 if (argc > 2) {
1158 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1159 return 1;
1160 }
1161 if (argc == 2) {
1162 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1163 } else {
1164 snprintf(buf, sizeof buf, "host:disconnect:");
1165 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001166 tmp = adb_query(buf);
1167 if(tmp) {
1168 printf("%s\n", tmp);
1169 return 0;
1170 } else {
1171 return 1;
1172 }
1173 }
1174
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 if (!strcmp(argv[0], "emu")) {
1176 return adb_send_emulator_command(argc, argv);
1177 }
1178
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001179 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001180 int r;
1181 int fd;
1182
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001183 char h = (argv[0][0] == 'h');
1184
1185 if (h) {
1186 printf("\x1b[41;33m");
1187 fflush(stdout);
1188 }
1189
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001190 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001191 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001192 r = interactive_shell();
1193 if (h) {
1194 printf("\x1b[0m");
1195 fflush(stdout);
1196 }
1197 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001198 }
1199
1200 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1201 argc -= 2;
1202 argv += 2;
1203 while(argc-- > 0) {
1204 strcat(buf, " ");
1205
1206 /* quote empty strings and strings with spaces */
1207 quote = (**argv == 0 || strchr(*argv, ' '));
1208 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001209 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001210 strcat(buf, *argv++);
1211 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001212 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001213 }
1214
1215 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001216 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001217 fd = adb_connect(buf);
1218 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001219 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001221 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001222 adb_close(fd);
1223 r = 0;
1224 } else {
1225 fprintf(stderr,"error: %s\n", adb_error());
1226 r = -1;
1227 }
1228
1229 if(persist) {
1230 fprintf(stderr,"\n- waiting for device -\n");
1231 adb_sleep_ms(1000);
1232 do_cmd(ttype, serial, "wait-for-device", 0);
1233 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001234 if (h) {
1235 printf("\x1b[0m");
1236 fflush(stdout);
1237 }
JP Abgrall408fa572011-03-16 15:57:42 -07001238 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001239 return r;
1240 }
1241 }
1242 }
1243
1244 if(!strcmp(argv[0], "kill-server")) {
1245 int fd;
1246 fd = _adb_connect("host:kill");
1247 if(fd == -1) {
1248 fprintf(stderr,"* server not running *\n");
1249 return 1;
1250 }
1251 return 0;
1252 }
1253
Doug Zongker447f0612012-01-09 14:54:53 -08001254 if(!strcmp(argv[0], "sideload")) {
1255 if(argc != 2) return usage();
1256 if(adb_download("sideload", argv[1], 1)) {
1257 return 1;
1258 } else {
1259 return 0;
1260 }
1261 }
1262
Mike Lockwoodff196702009-08-24 15:58:40 -07001263 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001264 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001265 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001266 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001267 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001268 if (!strcmp(argv[0], "reboot-bootloader"))
1269 snprintf(command, sizeof(command), "reboot:bootloader");
1270 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001271 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001272 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001273 snprintf(command, sizeof(command), "%s:", argv[0]);
1274 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001275 if(fd >= 0) {
1276 read_and_dump(fd);
1277 adb_close(fd);
1278 return 0;
1279 }
1280 fprintf(stderr,"error: %s\n", adb_error());
1281 return 1;
1282 }
1283
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001284 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001285 if (argc != 1) return usage();
1286 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001287 return 0;
1288 }
1289
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001290 /* adb_command() wrapper commands */
1291
1292 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1293 char* service = argv[0];
1294 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1295 if (ttype == kTransportUsb) {
1296 service = "wait-for-usb";
1297 } else if (ttype == kTransportLocal) {
1298 service = "wait-for-local";
1299 } else {
1300 service = "wait-for-any";
1301 }
1302 }
1303
1304 format_host_command(buf, sizeof buf, service, ttype, serial);
1305
1306 if (adb_command(buf)) {
1307 D("failure: %s *\n",adb_error());
1308 fprintf(stderr,"error: %s\n", adb_error());
1309 return 1;
1310 }
1311
1312 /* Allow a command to be run after wait-for-device,
1313 * e.g. 'adb wait-for-device shell'.
1314 */
1315 if(argc > 1) {
1316 argc--;
1317 argv++;
1318 goto top;
1319 }
1320 return 0;
1321 }
1322
David 'Digit' Turner25258692013-03-21 21:07:42 +01001323 if(!strcmp(argv[0], "forward") ||
1324 !strcmp(argv[0], "reverse"))
1325 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001326 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001327 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001328 char remove = 0;
1329 char remove_all = 0;
1330 char list = 0;
1331 char no_rebind = 0;
1332
1333 // Parse options here.
1334 while (argc > 1 && argv[1][0] == '-') {
1335 if (!strcmp(argv[1], "--list"))
1336 list = 1;
1337 else if (!strcmp(argv[1], "--remove"))
1338 remove = 1;
1339 else if (!strcmp(argv[1], "--remove-all"))
1340 remove_all = 1;
1341 else if (!strcmp(argv[1], "--no-rebind"))
1342 no_rebind = 1;
1343 else {
1344 return usage();
1345 }
1346 argc--;
1347 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001348 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001349
1350 // Ensure we can only use one option at a time.
1351 if (list + remove + remove_all + no_rebind > 1) {
1352 return usage();
1353 }
1354
1355 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001356 if (reverse) {
1357 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001358 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001359 if (serial) {
1360 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1361 serial);
1362 } else if (ttype == kTransportUsb) {
1363 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1364 } else if (ttype == kTransportLocal) {
1365 snprintf(host_prefix, sizeof host_prefix, "host-local");
1366 } else {
1367 snprintf(host_prefix, sizeof host_prefix, "host");
1368 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001369 }
1370
1371 // Implement forward --list
1372 if (list) {
1373 if (argc != 1)
1374 return usage();
1375 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1376 char* forwards = adb_query(buf);
1377 if (forwards == NULL) {
1378 fprintf(stderr, "error: %s\n", adb_error());
1379 return 1;
1380 }
1381 printf("%s", forwards);
1382 free(forwards);
1383 return 0;
1384 }
1385
1386 // Implement forward --remove-all
1387 else if (remove_all) {
1388 if (argc != 1)
1389 return usage();
1390 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1391 }
1392
1393 // Implement forward --remove <local>
1394 else if (remove) {
1395 if (argc != 2)
1396 return usage();
1397 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1398 }
1399 // Or implement one of:
1400 // forward <local> <remote>
1401 // forward --no-rebind <local> <remote>
1402 else
1403 {
1404 if (argc != 3)
1405 return usage();
1406 const char* command = no_rebind ? "forward:norebind:" : "forward";
1407 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1408 }
1409
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 if(adb_command(buf)) {
1411 fprintf(stderr,"error: %s\n", adb_error());
1412 return 1;
1413 }
1414 return 0;
1415 }
1416
1417 /* do_sync_*() commands */
1418
1419 if(!strcmp(argv[0], "ls")) {
1420 if(argc != 2) return usage();
1421 return do_sync_ls(argv[1]);
1422 }
1423
1424 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001425 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001426 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001427 const char* lpath = NULL, *rpath = NULL;
1428
Lajos Molnar4b35c012013-04-19 12:41:09 -07001429 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001430
1431 if ((lpath != NULL) && (rpath != NULL)) {
1432 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1433 }
1434
1435 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001436 }
1437
1438 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001439 int show_progress = 0;
Lajos Molnar4b35c012013-04-19 12:41:09 -07001440 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001441 const char* rpath = NULL, *lpath = ".";
1442
Lajos Molnar4b35c012013-04-19 12:41:09 -07001443 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001444
1445 if (rpath != NULL) {
Lajos Molnar4b35c012013-04-19 12:41:09 -07001446 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001447 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001448
1449 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001450 }
1451
1452 if(!strcmp(argv[0], "install")) {
1453 if (argc < 2) return usage();
1454 return install_app(ttype, serial, argc, argv);
1455 }
1456
1457 if(!strcmp(argv[0], "uninstall")) {
1458 if (argc < 2) return usage();
1459 return uninstall_app(ttype, serial, argc, argv);
1460 }
1461
1462 if(!strcmp(argv[0], "sync")) {
1463 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001464 int listonly = 0;
1465
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001466 int ret;
1467 if(argc < 2) {
1468 /* No local path was specified. */
1469 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001470 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1471 listonly = 1;
1472 if (argc == 3) {
1473 srcarg = argv[2];
1474 } else {
1475 srcarg = NULL;
1476 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477 } else if(argc == 2) {
1478 /* A local path or "android"/"data" arg was specified. */
1479 srcarg = argv[1];
1480 } else {
1481 return usage();
1482 }
1483 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1484 if(ret != 0) return usage();
1485
1486 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001487 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001488 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001489 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001490
1491 free(android_srcpath);
1492 free(data_srcpath);
1493 return ret;
1494 }
1495
1496 /* passthrough commands */
1497
1498 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001499 !strcmp(argv[0],"get-serialno") ||
1500 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001501 {
1502 char *tmp;
1503
1504 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1505 tmp = adb_query(buf);
1506 if(tmp) {
1507 printf("%s\n", tmp);
1508 return 0;
1509 } else {
1510 return 1;
1511 }
1512 }
1513
1514 /* other commands */
1515
1516 if(!strcmp(argv[0],"status-window")) {
1517 status_window(ttype, serial);
1518 return 0;
1519 }
1520
Christopher Tatedb0a8802011-11-30 13:00:33 -08001521 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001522 return logcat(ttype, serial, argc, argv);
1523 }
1524
1525 if(!strcmp(argv[0],"ppp")) {
1526 return ppp(argc, argv);
1527 }
1528
1529 if (!strcmp(argv[0], "start-server")) {
1530 return adb_connect("host:start-server");
1531 }
1532
Christopher Tated2f54152011-04-21 12:53:28 -07001533 if (!strcmp(argv[0], "backup")) {
1534 return backup(argc, argv);
1535 }
1536
Christopher Tate702967a2011-05-17 15:52:54 -07001537 if (!strcmp(argv[0], "restore")) {
1538 return restore(argc, argv);
1539 }
1540
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001541 if (!strcmp(argv[0], "jdwp")) {
1542 int fd = adb_connect("jdwp");
1543 if (fd >= 0) {
1544 read_and_dump(fd);
1545 adb_close(fd);
1546 return 0;
1547 } else {
1548 fprintf(stderr, "error: %s\n", adb_error());
1549 return -1;
1550 }
1551 }
1552
1553 /* "adb /?" is a common idiom under Windows */
1554 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1555 help();
1556 return 0;
1557 }
1558
1559 if(!strcmp(argv[0], "version")) {
1560 version(stdout);
1561 return 0;
1562 }
1563
1564 usage();
1565 return 1;
1566}
1567
1568static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1569{
1570 char *argv[16];
1571 int argc;
1572 va_list ap;
1573
1574 va_start(ap, cmd);
1575 argc = 0;
1576
1577 if (serial) {
1578 argv[argc++] = "-s";
1579 argv[argc++] = serial;
1580 } else if (ttype == kTransportUsb) {
1581 argv[argc++] = "-d";
1582 } else if (ttype == kTransportLocal) {
1583 argv[argc++] = "-e";
1584 }
1585
1586 argv[argc++] = cmd;
1587 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1588 va_end(ap);
1589
1590#if 0
1591 int n;
1592 fprintf(stderr,"argc = %d\n",argc);
1593 for(n = 0; n < argc; n++) {
1594 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1595 }
1596#endif
1597
1598 return adb_commandline(argc, argv);
1599}
1600
1601int find_sync_dirs(const char *srcarg,
1602 char **android_srcdir_out, char **data_srcdir_out)
1603{
1604 char *android_srcdir, *data_srcdir;
1605
1606 if(srcarg == NULL) {
1607 android_srcdir = product_file("system");
1608 data_srcdir = product_file("data");
1609 } else {
1610 /* srcarg may be "data", "system" or NULL.
1611 * if srcarg is NULL, then both data and system are synced
1612 */
1613 if(strcmp(srcarg, "system") == 0) {
1614 android_srcdir = product_file("system");
1615 data_srcdir = NULL;
1616 } else if(strcmp(srcarg, "data") == 0) {
1617 android_srcdir = NULL;
1618 data_srcdir = product_file("data");
1619 } else {
1620 /* It's not "system" or "data".
1621 */
1622 return 1;
1623 }
1624 }
1625
1626 if(android_srcdir_out != NULL)
1627 *android_srcdir_out = android_srcdir;
1628 else
1629 free(android_srcdir);
1630
1631 if(data_srcdir_out != NULL)
1632 *data_srcdir_out = data_srcdir;
1633 else
1634 free(data_srcdir);
1635
1636 return 0;
1637}
1638
1639static int pm_command(transport_type transport, char* serial,
1640 int argc, char** argv)
1641{
1642 char buf[4096];
1643
1644 snprintf(buf, sizeof(buf), "shell:pm");
1645
1646 while(argc-- > 0) {
1647 char *quoted;
1648
1649 quoted = dupAndQuote(*argv++);
1650
1651 strncat(buf, " ", sizeof(buf)-1);
1652 strncat(buf, quoted, sizeof(buf)-1);
1653 free(quoted);
1654 }
1655
1656 send_shellcommand(transport, serial, buf);
1657 return 0;
1658}
1659
1660int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1661{
1662 /* if the user choose the -k option, we refuse to do it until devices are
1663 out with the option to uninstall the remaining data somehow (adb/ui) */
1664 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1665 {
1666 printf(
1667 "The -k option uninstalls the application while retaining the data/cache.\n"
1668 "At the moment, there is no way to remove the remaining data.\n"
1669 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1670 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1671 return -1;
1672 }
1673
1674 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1675 return pm_command(transport, serial, argc, argv);
1676}
1677
1678static int delete_file(transport_type transport, char* serial, char* filename)
1679{
1680 char buf[4096];
1681 char* quoted;
1682
1683 snprintf(buf, sizeof(buf), "shell:rm ");
1684 quoted = dupAndQuote(filename);
1685 strncat(buf, quoted, sizeof(buf)-1);
1686 free(quoted);
1687
1688 send_shellcommand(transport, serial, buf);
1689 return 0;
1690}
1691
Kenny Root597ea5b2011-08-05 11:19:45 -07001692static const char* get_basename(const char* filename)
1693{
1694 const char* basename = adb_dirstop(filename);
1695 if (basename) {
1696 basename++;
1697 return basename;
1698 } else {
1699 return filename;
1700 }
1701}
1702
1703static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001704{
1705 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001706
Kenny Root597ea5b2011-08-05 11:19:45 -07001707 if (filename == NULL) {
1708 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001709 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001710
Kenny Root597ea5b2011-08-05 11:19:45 -07001711 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001712 fprintf(stderr, "can't find '%s' to install\n", filename);
1713 return 1;
1714 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001715
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001716 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001717 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001718 return 1;
1719 }
1720
Kenny Root597ea5b2011-08-05 11:19:45 -07001721 return 0;
1722}
1723
1724int install_app(transport_type transport, char* serial, int argc, char** argv)
1725{
1726 static const char *const DATA_DEST = "/data/local/tmp/%s";
1727 static const char *const SD_DEST = "/sdcard/tmp/%s";
1728 const char* where = DATA_DEST;
1729 char apk_dest[PATH_MAX];
1730 char verification_dest[PATH_MAX];
1731 char* apk_file;
1732 char* verification_file = NULL;
1733 int file_arg = -1;
1734 int err;
1735 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001736 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001737
1738 for (i = 1; i < argc; i++) {
1739 if (*argv[i] != '-') {
1740 file_arg = i;
1741 break;
Kenny Roota031a912011-09-23 12:46:39 -07001742 } else if (!strcmp(argv[i], "-i")) {
1743 // Skip the installer package name.
1744 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001745 } else if (!strcmp(argv[i], "-s")) {
1746 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001747 } else if (!strcmp(argv[i], "--algo")) {
1748 verify_apk = 0;
1749 i++;
1750 } else if (!strcmp(argv[i], "--iv")) {
1751 verify_apk = 0;
1752 i++;
1753 } else if (!strcmp(argv[i], "--key")) {
1754 verify_apk = 0;
1755 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001756 } else if (!strcmp(argv[i], "--abi")) {
1757 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001758 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001759 }
1760
Kenny Root597ea5b2011-08-05 11:19:45 -07001761 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001762 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001763 return 1;
1764 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001765 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001766 return 1;
1767 }
1768
1769 apk_file = argv[file_arg];
1770
1771 if (file_arg != argc - 1) {
1772 verification_file = argv[file_arg + 1];
1773 }
1774
1775 if (check_file(apk_file) || check_file(verification_file)) {
1776 return 1;
1777 }
1778
1779 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1780 if (verification_file != NULL) {
1781 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1782
1783 if (!strcmp(apk_dest, verification_dest)) {
1784 fprintf(stderr, "APK and verification file can't have the same name\n");
1785 return 1;
1786 }
1787 }
1788
Mark Lindner76f2a932014-03-11 17:55:59 -07001789 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001790 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001791 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001792 } else {
1793 argv[file_arg] = apk_dest; /* destination name, not source location */
1794 }
1795
1796 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001797 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1798 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001799 if (err) {
1800 goto cleanup_apk;
1801 } else {
1802 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1803 }
1804 }
1805
1806 pm_command(transport, serial, argc, argv);
1807
Kenny Root60733e92012-03-26 16:14:02 -07001808cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001809 if (verification_file != NULL) {
1810 delete_file(transport, serial, verification_dest);
1811 }
1812
Kenny Root597ea5b2011-08-05 11:19:45 -07001813 delete_file(transport, serial, apk_dest);
1814
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815 return err;
1816}