blob: 2cadc72acf360a2485fb91653732322f9365ba0a [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);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700277#ifdef HAVE_TERMIO_H
278 if (inFd == STDIN_FILENO) {
279 stdin_raw_init(STDIN_FILENO);
280 }
281#endif
Christopher Tate73779122011-04-21 12:53:28 -0700282 for (;;) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700283 if (inFd == STDIN_FILENO) {
284 len = unix_read(inFd, buf, BUFSIZE);
285 } else {
286 len = adb_read(inFd, buf, BUFSIZE);
287 }
Christopher Tate73779122011-04-21 12:53:28 -0700288 if (len == 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700289 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tate73779122011-04-21 12:53:28 -0700290 break;
291 }
292 if (len < 0) {
Christopher Tatea162e242011-06-10 11:38:37 -0700293 if (errno == EINTR) {
294 D("copy_to_file() : EINTR, retrying\n");
295 continue;
296 }
Christopher Tate73779122011-04-21 12:53:28 -0700297 D("copy_to_file() : error %d\n", errno);
298 break;
299 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700300 if (outFd == STDOUT_FILENO) {
301 fwrite(buf, 1, len, stdout);
302 fflush(stdout);
303 } else {
304 adb_write(outFd, buf, len);
305 }
Christopher Tatefba22972011-06-01 17:56:23 -0700306 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700307 }
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700308#ifdef HAVE_TERMIO_H
309 if (inFd == STDIN_FILENO) {
310 stdin_raw_restore(STDIN_FILENO);
311 }
312#endif
Christopher Tatefba22972011-06-01 17:56:23 -0700313 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700314 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700315}
316
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800317static void *stdin_read_thread(void *x)
318{
319 int fd, fdi;
320 unsigned char buf[1024];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800321 int r, n;
322 int state = 0;
323
324 int *fds = (int*) x;
325 fd = fds[0];
326 fdi = fds[1];
327 free(fds);
328
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800329 for(;;) {
330 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700331 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800332 r = unix_read(fdi, buf, 1024);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700333 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800334 if(r == 0) break;
335 if(r < 0) {
336 if(errno == EINTR) continue;
337 break;
338 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400339 for(n = 0; n < r; n++){
340 switch(buf[n]) {
341 case '\n':
342 state = 1;
343 break;
344 case '\r':
345 state = 1;
346 break;
347 case '~':
348 if(state == 1) state++;
349 break;
350 case '.':
351 if(state == 2) {
352 fprintf(stderr,"\n* disconnect *\n");
353#ifdef HAVE_TERMIO_H
354 stdin_raw_restore(fdi);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800355#endif
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400356 exit(0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800357 }
Mike Lockwood18ab0d62010-05-25 13:40:15 -0400358 default:
359 state = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800360 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800361 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800362 r = adb_write(fd, buf, r);
363 if(r <= 0) {
364 break;
365 }
366 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800367 return 0;
368}
369
370int interactive_shell(void)
371{
372 adb_thread_t thr;
373 int fdi, fd;
374 int *fds;
375
376 fd = adb_connect("shell:");
377 if(fd < 0) {
378 fprintf(stderr,"error: %s\n", adb_error());
379 return 1;
380 }
381 fdi = 0; //dup(0);
382
383 fds = malloc(sizeof(int) * 2);
384 fds[0] = fd;
385 fds[1] = fdi;
386
387#ifdef HAVE_TERMIO_H
388 stdin_raw_init(fdi);
389#endif
390 adb_thread_create(&thr, stdin_read_thread, fds);
391 read_and_dump(fd);
392#ifdef HAVE_TERMIO_H
393 stdin_raw_restore(fdi);
394#endif
395 return 0;
396}
397
398
399static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
400{
401 if (serial) {
402 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
403 } else {
404 const char* prefix = "host";
405 if (ttype == kTransportUsb)
406 prefix = "host-usb";
407 else if (ttype == kTransportLocal)
408 prefix = "host-local";
409
410 snprintf(buffer, buflen, "%s:%s", prefix, command);
411 }
412}
413
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100414int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker6b217ed2012-01-09 14:54:53 -0800415 unsigned progress)
416{
417 char buf[4096];
418 unsigned total;
419 int fd;
420 const unsigned char *ptr;
421
422 sprintf(buf,"%s:%d", service, sz);
423 fd = adb_connect(buf);
424 if(fd < 0) {
425 fprintf(stderr,"error: %s\n", adb_error());
426 return -1;
427 }
428
429 int opt = CHUNK_SIZE;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700430 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800431
432 total = sz;
433 ptr = data;
434
435 if(progress) {
436 char *x = strrchr(service, ':');
437 if(x) service = x + 1;
438 }
439
440 while(sz > 0) {
441 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
442 if(writex(fd, ptr, xfer)) {
443 adb_status(fd);
444 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
445 return -1;
446 }
447 sz -= xfer;
448 ptr += xfer;
449 if(progress) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100450 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800451 fflush(stdout);
452 }
453 }
454 if(progress) {
455 printf("\n");
456 }
457
458 if(readx(fd, buf, 4)){
459 fprintf(stderr,"* error reading response *\n");
460 adb_close(fd);
461 return -1;
462 }
463 if(memcmp(buf, "OKAY", 4)) {
464 buf[4] = 0;
465 fprintf(stderr,"* error response '%s' *\n", buf);
466 adb_close(fd);
467 return -1;
468 }
469
470 adb_close(fd);
471 return 0;
472}
473
474
475int adb_download(const char *service, const char *fn, unsigned progress)
476{
477 void *data;
478 unsigned sz;
479
480 data = load_file(fn, &sz);
481 if(data == 0) {
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100482 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800483 return -1;
484 }
485
Magnus Erikssoncb30cc62013-03-05 07:37:32 +0100486 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800487 free(data);
488 return status;
489}
490
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800491static void status_window(transport_type ttype, const char* serial)
492{
493 char command[4096];
494 char *state = 0;
495 char *laststate = 0;
496
497 /* silence stderr */
498#ifdef _WIN32
499 /* XXX: TODO */
500#else
501 int fd;
502 fd = unix_open("/dev/null", O_WRONLY);
503 dup2(fd, 2);
504 adb_close(fd);
505#endif
506
507 format_host_command(command, sizeof command, "get-state", ttype, serial);
508
509 for(;;) {
510 adb_sleep_ms(250);
511
512 if(state) {
513 free(state);
514 state = 0;
515 }
516
517 state = adb_query(command);
518
519 if(state) {
520 if(laststate && !strcmp(state,laststate)){
521 continue;
522 } else {
523 if(laststate) free(laststate);
524 laststate = strdup(state);
525 }
526 }
527
528 printf("%c[2J%c[2H", 27, 27);
529 printf("Android Debug Bridge\n");
530 printf("State: %s\n", state ? state : "offline");
531 fflush(stdout);
532 }
533}
534
535/** duplicate string and quote all \ " ( ) chars + space character. */
536static char *
537dupAndQuote(const char *s)
538{
539 const char *ts;
540 size_t alloc_len;
541 char *ret;
542 char *dest;
543
544 ts = s;
545
546 alloc_len = 0;
547
548 for( ;*ts != '\0'; ts++) {
549 alloc_len++;
550 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
551 alloc_len++;
552 }
553 }
554
555 ret = (char *)malloc(alloc_len + 1);
556
557 ts = s;
558 dest = ret;
559
560 for ( ;*ts != '\0'; ts++) {
561 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
562 *dest++ = '\\';
563 }
564
565 *dest++ = *ts;
566 }
567
568 *dest++ = '\0';
569
570 return ret;
571}
572
573/**
574 * Run ppp in "notty" mode against a resource listed as the first parameter
575 * eg:
576 *
577 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
578 *
579 */
580int ppp(int argc, char **argv)
581{
582#ifdef HAVE_WIN32_PROC
583 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
584 return -1;
585#else
586 char *adb_service_name;
587 pid_t pid;
588 int fd;
589
590 if (argc < 2) {
591 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
592 argv[0]);
593
594 return 1;
595 }
596
597 adb_service_name = argv[1];
598
599 fd = adb_connect(adb_service_name);
600
601 if(fd < 0) {
602 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
603 adb_service_name, adb_error());
604 return 1;
605 }
606
607 pid = fork();
608
609 if (pid < 0) {
610 perror("from fork()");
611 return 1;
612 } else if (pid == 0) {
613 int err;
614 int i;
615 const char **ppp_args;
616
617 // copy args
618 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
619 ppp_args[0] = "pppd";
620 for (i = 2 ; i < argc ; i++) {
621 //argv[2] and beyond become ppp_args[1] and beyond
622 ppp_args[i - 1] = argv[i];
623 }
624 ppp_args[i-1] = NULL;
625
626 // child side
627
628 dup2(fd, STDIN_FILENO);
629 dup2(fd, STDOUT_FILENO);
630 adb_close(STDERR_FILENO);
631 adb_close(fd);
632
633 err = execvp("pppd", (char * const *)ppp_args);
634
635 if (err < 0) {
636 perror("execing pppd");
637 }
638 exit(-1);
639 } else {
640 // parent side
641
642 adb_close(fd);
643 return 0;
644 }
645#endif /* !HAVE_WIN32_PROC */
646}
647
648static int send_shellcommand(transport_type transport, char* serial, char* buf)
649{
650 int fd, ret;
651
652 for(;;) {
653 fd = adb_connect(buf);
654 if(fd >= 0)
655 break;
656 fprintf(stderr,"- waiting for device -\n");
657 adb_sleep_ms(1000);
658 do_cmd(transport, serial, "wait-for-device", 0);
659 }
660
661 read_and_dump(fd);
662 ret = adb_close(fd);
663 if (ret)
664 perror("close");
665
666 return ret;
667}
668
669static int logcat(transport_type transport, char* serial, int argc, char **argv)
670{
671 char buf[4096];
672
673 char *log_tags;
674 char *quoted_log_tags;
675
676 log_tags = getenv("ANDROID_LOG_TAGS");
677 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
678
679 snprintf(buf, sizeof(buf),
680 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
681 quoted_log_tags);
682
683 free(quoted_log_tags);
684
Christopher Tate7b9b5162011-11-30 13:00:33 -0800685 if (!strcmp(argv[0],"longcat")) {
686 strncat(buf, " -v long", sizeof(buf)-1);
687 }
688
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800689 argc -= 1;
690 argv += 1;
691 while(argc-- > 0) {
692 char *quoted;
693
694 quoted = dupAndQuote (*argv++);
695
696 strncat(buf, " ", sizeof(buf)-1);
697 strncat(buf, quoted, sizeof(buf)-1);
698 free(quoted);
699 }
700
701 send_shellcommand(transport, serial, buf);
702 return 0;
703}
704
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700705static int mkdirs(const char *path)
Christopher Tate1e9f2392011-12-08 19:04:34 -0800706{
707 int ret;
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700708 char *x = (char *)path + 1;
Christopher Tate1e9f2392011-12-08 19:04:34 -0800709
710 for(;;) {
711 x = adb_dirstart(x);
712 if(x == 0) return 0;
713 *x = 0;
714 ret = adb_mkdir(path, 0775);
715 *x = OS_PATH_SEPARATOR;
716 if((ret < 0) && (errno != EEXIST)) {
717 return ret;
718 }
719 x++;
720 }
721 return 0;
722}
723
Christopher Tate73779122011-04-21 12:53:28 -0700724static int backup(int argc, char** argv) {
725 char buf[4096];
Christopher Tate1e9f2392011-12-08 19:04:34 -0800726 char default_name[32];
727 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tate73779122011-04-21 12:53:28 -0700728 int fd, outFd;
Christopher Tatefba22972011-06-01 17:56:23 -0700729 int i, j;
Christopher Tate73779122011-04-21 12:53:28 -0700730
Christopher Tatefba22972011-06-01 17:56:23 -0700731 /* find, extract, and use any -f argument */
732 for (i = 1; i < argc; i++) {
733 if (!strcmp("-f", argv[i])) {
734 if (i == argc-1) {
735 fprintf(stderr, "adb: -f passed with no filename\n");
736 return usage();
737 }
738 filename = argv[i+1];
739 for (j = i+2; j <= argc; ) {
740 argv[i++] = argv[j++];
741 }
742 argc -= 2;
743 argv[argc] = NULL;
744 }
Christopher Tate73779122011-04-21 12:53:28 -0700745 }
746
Christopher Tatecf4f16a2011-08-22 17:12:08 -0700747 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
748 if (argc < 2) return usage();
749
Christopher Tate1e9f2392011-12-08 19:04:34 -0800750 adb_unlink(filename);
Mark Salyzyn63e39f22014-04-30 09:10:31 -0700751 mkdirs(filename);
Christopher Tate1e9f2392011-12-08 19:04:34 -0800752 outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -0700753 if (outFd < 0) {
754 fprintf(stderr, "adb: unable to open file %s\n", filename);
755 return -1;
756 }
757
758 snprintf(buf, sizeof(buf), "backup");
759 for (argc--, argv++; argc; argc--, argv++) {
760 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
761 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
762 }
763
764 D("backup. filename=%s buf=%s\n", filename, buf);
765 fd = adb_connect(buf);
766 if (fd < 0) {
767 fprintf(stderr, "adb: unable to connect for backup\n");
768 adb_close(outFd);
769 return -1;
770 }
771
Christopher Tate9c829102012-01-06 15:43:03 -0800772 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tate73779122011-04-21 12:53:28 -0700773 copy_to_file(fd, outFd);
774
775 adb_close(fd);
776 adb_close(outFd);
777 return 0;
778}
779
Christopher Tatecf5379b2011-05-17 15:52:54 -0700780static int restore(int argc, char** argv) {
781 const char* filename;
782 int fd, tarFd;
783
784 if (argc != 2) return usage();
785
786 filename = argv[1];
787 tarFd = adb_open(filename, O_RDONLY);
788 if (tarFd < 0) {
789 fprintf(stderr, "adb: unable to open file %s\n", filename);
790 return -1;
791 }
792
793 fd = adb_connect("restore:");
794 if (fd < 0) {
Brian Carlstromcad81322013-10-18 13:58:48 -0700795 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700796 adb_close(tarFd);
797 return -1;
798 }
799
Christopher Tate9c829102012-01-06 15:43:03 -0800800 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tatecf5379b2011-05-17 15:52:54 -0700801 copy_to_file(tarFd, fd);
802
803 adb_close(fd);
804 adb_close(tarFd);
805 return 0;
806}
807
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800808#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
809static int top_works(const char *top)
810{
811 if (top != NULL && adb_is_absolute_host_path(top)) {
812 char path_buf[PATH_MAX];
813 snprintf(path_buf, sizeof(path_buf),
814 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
815 return access(path_buf, F_OK) == 0;
816 }
817 return 0;
818}
819
820static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
821{
822 strcpy(path_buf, indir);
823 while (1) {
824 if (top_works(path_buf)) {
825 return path_buf;
826 }
827 char *s = adb_dirstop(path_buf);
828 if (s != NULL) {
829 *s = '\0';
830 } else {
831 path_buf[0] = '\0';
832 return NULL;
833 }
834 }
835}
836
837static char *find_top(char path_buf[PATH_MAX])
838{
839 char *top = getenv("ANDROID_BUILD_TOP");
840 if (top != NULL && top[0] != '\0') {
841 if (!top_works(top)) {
842 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
843 return NULL;
844 }
845 } else {
846 top = getenv("TOP");
847 if (top != NULL && top[0] != '\0') {
848 if (!top_works(top)) {
849 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
850 return NULL;
851 }
852 } else {
853 top = NULL;
854 }
855 }
856
857 if (top != NULL) {
858 /* The environment pointed to a top directory that works.
859 */
860 strcpy(path_buf, top);
861 return path_buf;
862 }
863
864 /* The environment didn't help. Walk up the tree from the CWD
865 * to see if we can find the top.
866 */
867 char dir[PATH_MAX];
868 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
869 if (top == NULL) {
870 /* If the CWD isn't under a good-looking top, see if the
871 * executable is.
872 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100873 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800874 top = find_top_from(dir, path_buf);
875 }
876 return top;
877}
878
879/* <hint> may be:
880 * - A simple product name
881 * e.g., "sooner"
882TODO: debug? sooner-debug, sooner:debug?
883 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
884 * e.g., "out/target/product/sooner"
885 * - An absolute path to the PRODUCT_OUT dir
886 * e.g., "/src/device/out/target/product/sooner"
887 *
888 * Given <hint>, try to construct an absolute path to the
889 * ANDROID_PRODUCT_OUT dir.
890 */
891static const char *find_product_out_path(const char *hint)
892{
893 static char path_buf[PATH_MAX];
894
895 if (hint == NULL || hint[0] == '\0') {
896 return NULL;
897 }
898
899 /* If it's already absolute, don't bother doing any work.
900 */
901 if (adb_is_absolute_host_path(hint)) {
902 strcpy(path_buf, hint);
903 return path_buf;
904 }
905
906 /* If there are any slashes in it, assume it's a relative path;
907 * make it absolute.
908 */
909 if (adb_dirstart(hint) != NULL) {
910 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
911 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
912 return NULL;
913 }
914 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
915 fprintf(stderr, "adb: Couldn't assemble path\n");
916 return NULL;
917 }
918 strcat(path_buf, OS_PATH_SEPARATOR_STR);
919 strcat(path_buf, hint);
920 return path_buf;
921 }
922
923 /* It's a string without any slashes. Try to do something with it.
924 *
925 * Try to find the root of the build tree, and build a PRODUCT_OUT
926 * path from there.
927 */
928 char top_buf[PATH_MAX];
929 const char *top = find_top(top_buf);
930 if (top == NULL) {
931 fprintf(stderr, "adb: Couldn't find top of build tree\n");
932 return NULL;
933 }
934//TODO: if we have a way to indicate debug, look in out/debug/target/...
935 snprintf(path_buf, sizeof(path_buf),
936 "%s" OS_PATH_SEPARATOR_STR
937 "out" OS_PATH_SEPARATOR_STR
938 "target" OS_PATH_SEPARATOR_STR
939 "product" OS_PATH_SEPARATOR_STR
940 "%s", top_buf, hint);
941 if (access(path_buf, F_OK) < 0) {
942 fprintf(stderr, "adb: Couldn't find a product dir "
943 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
944 return NULL;
945 }
946 return path_buf;
947}
948
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700949static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
950 int *show_progress, int *copy_attrs) {
Mark Lindner9f9d1452014-03-11 17:55:59 -0700951 *show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700952 *copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700953
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700954 while (narg > 0) {
955 if (!strcmp(*arg, "-p")) {
956 *show_progress = 1;
957 } else if (!strcmp(*arg, "-a")) {
958 *copy_attrs = 1;
959 } else {
960 break;
961 }
Mark Lindner9f9d1452014-03-11 17:55:59 -0700962 ++arg;
963 --narg;
964 }
965
966 if (narg > 0) {
967 *path1 = *arg;
968 ++arg;
969 --narg;
970 }
971
972 if (narg > 0) {
973 *path2 = *arg;
974 }
975}
976
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800977int adb_commandline(int argc, char **argv)
978{
979 char buf[4096];
980 int no_daemon = 0;
981 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +0100982 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800983 int persist = 0;
984 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800985 transport_type ttype = kTransportAny;
986 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100987 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800988
989 /* If defined, this should be an absolute path to
990 * the directory containing all of the various system images
991 * for a particular product. If not defined, and the adb
992 * command requires this information, then the user must
993 * specify the path using "-p".
994 */
995 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
996 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
997 gProductOutPath = NULL;
998 }
999 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1000
Nick Pellyaf2fe9b2009-05-07 12:48:03 -07001001 serial = getenv("ANDROID_SERIAL");
1002
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001003 /* Validate and assign the server port */
1004 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1005 int server_port = DEFAULT_ADB_PORT;
1006 if (server_port_str && strlen(server_port_str) > 0) {
1007 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbel411775c2012-11-14 10:16:17 -08001008 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001009 fprintf(stderr,
Matt Gumbel411775c2012-11-14 10:16:17 -08001010 "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 +01001011 server_port_str);
1012 return usage();
1013 }
1014 }
1015
1016 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001017 while(argc > 0) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001018 if(!strcmp(argv[0],"server")) {
1019 is_server = 1;
1020 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001021 no_daemon = 1;
1022 } else if (!strcmp(argv[0], "fork-server")) {
1023 /* this is a special flag used only when the ADB client launches the ADB Server */
1024 is_daemon = 1;
1025 } else if(!strcmp(argv[0],"persist")) {
1026 persist = 1;
1027 } else if(!strncmp(argv[0], "-p", 2)) {
1028 const char *product = NULL;
1029 if (argv[0][2] == '\0') {
1030 if (argc < 2) return usage();
1031 product = argv[1];
1032 argc--;
1033 argv++;
1034 } else {
Vairavan Srinivasanadc39402012-08-04 16:40:50 -07001035 product = argv[0] + 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001036 }
1037 gProductOutPath = find_product_out_path(product);
1038 if (gProductOutPath == NULL) {
1039 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1040 product);
1041 return usage();
1042 }
1043 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1044 if (isdigit(argv[0][2])) {
1045 serial = argv[0] + 2;
1046 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001047 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001048 serial = argv[1];
1049 argc--;
1050 argv++;
1051 }
1052 } else if (!strcmp(argv[0],"-d")) {
1053 ttype = kTransportUsb;
1054 } else if (!strcmp(argv[0],"-e")) {
1055 ttype = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001056 } else if (!strcmp(argv[0],"-a")) {
1057 gListenAll = 1;
1058 } else if(!strncmp(argv[0], "-H", 2)) {
1059 const char *hostname = NULL;
1060 if (argv[0][2] == '\0') {
1061 if (argc < 2) return usage();
1062 hostname = argv[1];
1063 argc--;
1064 argv++;
1065 } else {
1066 hostname = argv[0] + 2;
1067 }
1068 adb_set_tcp_name(hostname);
1069
1070 } else if(!strncmp(argv[0], "-P", 2)) {
1071 if (argv[0][2] == '\0') {
1072 if (argc < 2) return usage();
1073 server_port_str = argv[1];
1074 argc--;
1075 argv++;
1076 } else {
1077 server_port_str = argv[0] + 2;
1078 }
1079 if (strlen(server_port_str) > 0) {
1080 server_port = (int) strtol(server_port_str, NULL, 0);
1081 if (server_port <= 0 || server_port > 65535) {
1082 fprintf(stderr,
1083 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1084 server_port_str);
1085 return usage();
1086 }
1087 } else {
1088 fprintf(stderr,
1089 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1090 return usage();
1091 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001092 } else {
1093 /* out of recognized modifiers and flags */
1094 break;
1095 }
1096 argc--;
1097 argv++;
1098 }
1099
1100 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001101 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001102
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001103 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001104 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001105 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001106 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +01001107 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001108 }
1109 if(r) {
1110 fprintf(stderr,"* could not start server *\n");
1111 }
1112 return r;
1113 }
1114
1115top:
1116 if(argc == 0) {
1117 return usage();
1118 }
1119
1120 /* adb_connect() commands */
1121
1122 if(!strcmp(argv[0], "devices")) {
1123 char *tmp;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001124 char *listopt;
1125 if (argc < 2)
1126 listopt = "";
1127 else if (argc == 2 && !strcmp(argv[1], "-l"))
1128 listopt = argv[1];
1129 else {
1130 fprintf(stderr, "Usage: adb devices [-l]\n");
1131 return 1;
1132 }
1133 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001134 tmp = adb_query(buf);
1135 if(tmp) {
1136 printf("List of devices attached \n");
1137 printf("%s\n", tmp);
1138 return 0;
1139 } else {
1140 return 1;
1141 }
1142 }
1143
Mike Lockwood01c2c302010-05-24 10:44:35 -04001144 if(!strcmp(argv[0], "connect")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001145 char *tmp;
1146 if (argc != 2) {
Mike Lockwood01c2c302010-05-24 10:44:35 -04001147 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood26b88e32009-08-24 15:58:40 -07001148 return 1;
1149 }
Mike Lockwood01c2c302010-05-24 10:44:35 -04001150 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1151 tmp = adb_query(buf);
1152 if(tmp) {
1153 printf("%s\n", tmp);
1154 return 0;
1155 } else {
1156 return 1;
1157 }
1158 }
1159
1160 if(!strcmp(argv[0], "disconnect")) {
1161 char *tmp;
1162 if (argc > 2) {
1163 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1164 return 1;
1165 }
1166 if (argc == 2) {
1167 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1168 } else {
1169 snprintf(buf, sizeof buf, "host:disconnect:");
1170 }
Mike Lockwood26b88e32009-08-24 15:58:40 -07001171 tmp = adb_query(buf);
1172 if(tmp) {
1173 printf("%s\n", tmp);
1174 return 0;
1175 } else {
1176 return 1;
1177 }
1178 }
1179
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001180 if (!strcmp(argv[0], "emu")) {
1181 return adb_send_emulator_command(argc, argv);
1182 }
1183
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001184 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001185 int r;
1186 int fd;
1187
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001188 char h = (argv[0][0] == 'h');
1189
1190 if (h) {
1191 printf("\x1b[41;33m");
1192 fflush(stdout);
1193 }
1194
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001195 if(argc < 2) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001196 D("starting interactive shell\n");
Daniel Sandlerd9bc2372010-08-19 01:10:18 -04001197 r = interactive_shell();
1198 if (h) {
1199 printf("\x1b[0m");
1200 fflush(stdout);
1201 }
1202 return r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001203 }
1204
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001205 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001206 argc -= 2;
1207 argv += 2;
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001208 while (argc-- > 0) {
1209 char *quoted = dupAndQuote(*argv++);
1210 strncat(buf, " ", sizeof(buf) - 1);
1211 strncat(buf, quoted, sizeof(buf) - 1);
1212 free(quoted);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001213 }
1214
1215 for(;;) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001216 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001217 fd = adb_connect(buf);
1218 if(fd >= 0) {
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001219 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001220 read_and_dump(fd);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001221 D("read_and_dump() done.\n");
The Android Open Source Project9ca14dc2009-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 Sandlerd9bc2372010-08-19 01:10:18 -04001234 if (h) {
1235 printf("\x1b[0m");
1236 fflush(stdout);
1237 }
JP Abgrall2e5dd6e2011-03-16 15:57:42 -07001238 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001239 return r;
1240 }
1241 }
1242 }
1243
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001244 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1245 int exec_in = !strcmp(argv[0], "exec-in");
1246 int fd;
1247
1248 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1249 argc -= 2;
1250 argv += 2;
1251 while (argc-- > 0) {
1252 char *quoted = dupAndQuote(*argv++);
1253 strncat(buf, " ", sizeof(buf) - 1);
1254 strncat(buf, quoted, sizeof(buf) - 1);
1255 free(quoted);
1256 }
1257
1258 fd = adb_connect(buf);
1259 if (fd < 0) {
1260 fprintf(stderr, "error: %s\n", adb_error());
1261 return -1;
1262 }
1263
1264 if (exec_in) {
1265 copy_to_file(STDIN_FILENO, fd);
1266 } else {
1267 copy_to_file(fd, STDOUT_FILENO);
1268 }
1269
1270 adb_close(fd);
1271 return 0;
1272 }
1273
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001274 if(!strcmp(argv[0], "kill-server")) {
1275 int fd;
1276 fd = _adb_connect("host:kill");
1277 if(fd == -1) {
1278 fprintf(stderr,"* server not running *\n");
1279 return 1;
1280 }
1281 return 0;
1282 }
1283
Doug Zongker6b217ed2012-01-09 14:54:53 -08001284 if(!strcmp(argv[0], "sideload")) {
1285 if(argc != 2) return usage();
1286 if(adb_download("sideload", argv[1], 1)) {
1287 return 1;
1288 } else {
1289 return 0;
1290 }
1291 }
1292
Mike Lockwood26b88e32009-08-24 15:58:40 -07001293 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guyf925d912009-12-14 14:42:17 -08001294 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood26b88e32009-08-24 15:58:40 -07001295 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwood78589f32009-09-03 14:54:58 -04001296 || !strcmp(argv[0], "root")) {
Mike Lockwood26b88e32009-08-24 15:58:40 -07001297 char command[100];
Romain Guyf925d912009-12-14 14:42:17 -08001298 if (!strcmp(argv[0], "reboot-bootloader"))
1299 snprintf(command, sizeof(command), "reboot:bootloader");
1300 else if (argc > 1)
Mike Lockwood26b88e32009-08-24 15:58:40 -07001301 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood12a35ea2009-08-04 20:37:51 -04001302 else
Mike Lockwood26b88e32009-08-24 15:58:40 -07001303 snprintf(command, sizeof(command), "%s:", argv[0]);
1304 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001305 if(fd >= 0) {
1306 read_and_dump(fd);
1307 adb_close(fd);
1308 return 0;
1309 }
1310 fprintf(stderr,"error: %s\n", adb_error());
1311 return 1;
1312 }
1313
Mike Lockwood78589f32009-09-03 14:54:58 -04001314 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor2857f312010-01-20 13:50:36 -08001315 if (argc != 1) return usage();
1316 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwood78589f32009-09-03 14:54:58 -04001317 return 0;
1318 }
1319
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001320 /* adb_command() wrapper commands */
1321
1322 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1323 char* service = argv[0];
1324 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1325 if (ttype == kTransportUsb) {
1326 service = "wait-for-usb";
1327 } else if (ttype == kTransportLocal) {
1328 service = "wait-for-local";
1329 } else {
1330 service = "wait-for-any";
1331 }
1332 }
1333
1334 format_host_command(buf, sizeof buf, service, ttype, serial);
1335
1336 if (adb_command(buf)) {
1337 D("failure: %s *\n",adb_error());
1338 fprintf(stderr,"error: %s\n", adb_error());
1339 return 1;
1340 }
1341
1342 /* Allow a command to be run after wait-for-device,
1343 * e.g. 'adb wait-for-device shell'.
1344 */
1345 if(argc > 1) {
1346 argc--;
1347 argv++;
1348 goto top;
1349 }
1350 return 0;
1351 }
1352
1353 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001354 char host_prefix[64];
1355 char remove = 0;
1356 char remove_all = 0;
1357 char list = 0;
1358 char no_rebind = 0;
1359
1360 // Parse options here.
1361 while (argc > 1 && argv[1][0] == '-') {
1362 if (!strcmp(argv[1], "--list"))
1363 list = 1;
1364 else if (!strcmp(argv[1], "--remove"))
1365 remove = 1;
1366 else if (!strcmp(argv[1], "--remove-all"))
1367 remove_all = 1;
1368 else if (!strcmp(argv[1], "--no-rebind"))
1369 no_rebind = 1;
1370 else {
1371 return usage();
1372 }
1373 argc--;
1374 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001375 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001376
1377 // Ensure we can only use one option at a time.
1378 if (list + remove + remove_all + no_rebind > 1) {
1379 return usage();
1380 }
1381
1382 // Determine the <host-prefix> for this command.
1383 if (serial) {
1384 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1385 serial);
1386 } else if (ttype == kTransportUsb) {
1387 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1388 } else if (ttype == kTransportLocal) {
1389 snprintf(host_prefix, sizeof host_prefix, "host-local");
1390 } else {
1391 snprintf(host_prefix, sizeof host_prefix, "host");
1392 }
1393
1394 // Implement forward --list
1395 if (list) {
1396 if (argc != 1)
1397 return usage();
1398 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1399 char* forwards = adb_query(buf);
1400 if (forwards == NULL) {
1401 fprintf(stderr, "error: %s\n", adb_error());
1402 return 1;
1403 }
1404 printf("%s", forwards);
1405 free(forwards);
1406 return 0;
1407 }
1408
1409 // Implement forward --remove-all
1410 else if (remove_all) {
1411 if (argc != 1)
1412 return usage();
1413 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1414 }
1415
1416 // Implement forward --remove <local>
1417 else if (remove) {
1418 if (argc != 2)
1419 return usage();
1420 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1421 }
1422 // Or implement one of:
1423 // forward <local> <remote>
1424 // forward --no-rebind <local> <remote>
1425 else
1426 {
1427 if (argc != 3)
1428 return usage();
1429 const char* command = no_rebind ? "forward:norebind:" : "forward";
1430 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1431 }
1432
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001433 if(adb_command(buf)) {
1434 fprintf(stderr,"error: %s\n", adb_error());
1435 return 1;
1436 }
1437 return 0;
1438 }
1439
1440 /* do_sync_*() commands */
1441
1442 if(!strcmp(argv[0], "ls")) {
1443 if(argc != 2) return usage();
1444 return do_sync_ls(argv[1]);
1445 }
1446
1447 if(!strcmp(argv[0], "push")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001448 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001449 int copy_attrs = 0; // unused
Mark Lindner9f9d1452014-03-11 17:55:59 -07001450 const char* lpath = NULL, *rpath = NULL;
1451
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001452 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001453
1454 if ((lpath != NULL) && (rpath != NULL)) {
1455 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1456 }
1457
1458 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001459 }
1460
1461 if(!strcmp(argv[0], "pull")) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001462 int show_progress = 0;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001463 int copy_attrs = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001464 const char* rpath = NULL, *lpath = ".";
1465
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001466 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner9f9d1452014-03-11 17:55:59 -07001467
1468 if (rpath != NULL) {
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001469 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato23595b02010-01-05 13:42:25 -08001470 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001471
1472 return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001473 }
1474
1475 if(!strcmp(argv[0], "install")) {
1476 if (argc < 2) return usage();
1477 return install_app(ttype, serial, argc, argv);
1478 }
1479
1480 if(!strcmp(argv[0], "uninstall")) {
1481 if (argc < 2) return usage();
1482 return uninstall_app(ttype, serial, argc, argv);
1483 }
1484
1485 if(!strcmp(argv[0], "sync")) {
1486 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001487 int listonly = 0;
1488
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001489 int ret;
1490 if(argc < 2) {
1491 /* No local path was specified. */
1492 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001493 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1494 listonly = 1;
1495 if (argc == 3) {
1496 srcarg = argv[2];
1497 } else {
1498 srcarg = NULL;
1499 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001500 } else if(argc == 2) {
1501 /* A local path or "android"/"data" arg was specified. */
1502 srcarg = argv[1];
1503 } else {
1504 return usage();
1505 }
1506 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1507 if(ret != 0) return usage();
1508
1509 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001510 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001511 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001512 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001513
1514 free(android_srcpath);
1515 free(data_srcpath);
1516 return ret;
1517 }
1518
1519 /* passthrough commands */
1520
1521 if(!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001522 !strcmp(argv[0],"get-serialno") ||
1523 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001524 {
1525 char *tmp;
1526
1527 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1528 tmp = adb_query(buf);
1529 if(tmp) {
1530 printf("%s\n", tmp);
1531 return 0;
1532 } else {
1533 return 1;
1534 }
1535 }
1536
1537 /* other commands */
1538
1539 if(!strcmp(argv[0],"status-window")) {
1540 status_window(ttype, serial);
1541 return 0;
1542 }
1543
Christopher Tate7b9b5162011-11-30 13:00:33 -08001544 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001545 return logcat(ttype, serial, argc, argv);
1546 }
1547
1548 if(!strcmp(argv[0],"ppp")) {
1549 return ppp(argc, argv);
1550 }
1551
1552 if (!strcmp(argv[0], "start-server")) {
1553 return adb_connect("host:start-server");
1554 }
1555
Christopher Tate73779122011-04-21 12:53:28 -07001556 if (!strcmp(argv[0], "backup")) {
1557 return backup(argc, argv);
1558 }
1559
Christopher Tatecf5379b2011-05-17 15:52:54 -07001560 if (!strcmp(argv[0], "restore")) {
1561 return restore(argc, argv);
1562 }
1563
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001564 if (!strcmp(argv[0], "jdwp")) {
1565 int fd = adb_connect("jdwp");
1566 if (fd >= 0) {
1567 read_and_dump(fd);
1568 adb_close(fd);
1569 return 0;
1570 } else {
1571 fprintf(stderr, "error: %s\n", adb_error());
1572 return -1;
1573 }
1574 }
1575
1576 /* "adb /?" is a common idiom under Windows */
1577 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1578 help();
1579 return 0;
1580 }
1581
1582 if(!strcmp(argv[0], "version")) {
1583 version(stdout);
1584 return 0;
1585 }
1586
1587 usage();
1588 return 1;
1589}
1590
1591static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1592{
1593 char *argv[16];
1594 int argc;
1595 va_list ap;
1596
1597 va_start(ap, cmd);
1598 argc = 0;
1599
1600 if (serial) {
1601 argv[argc++] = "-s";
1602 argv[argc++] = serial;
1603 } else if (ttype == kTransportUsb) {
1604 argv[argc++] = "-d";
1605 } else if (ttype == kTransportLocal) {
1606 argv[argc++] = "-e";
1607 }
1608
1609 argv[argc++] = cmd;
1610 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1611 va_end(ap);
1612
1613#if 0
1614 int n;
1615 fprintf(stderr,"argc = %d\n",argc);
1616 for(n = 0; n < argc; n++) {
1617 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1618 }
1619#endif
1620
1621 return adb_commandline(argc, argv);
1622}
1623
1624int find_sync_dirs(const char *srcarg,
1625 char **android_srcdir_out, char **data_srcdir_out)
1626{
1627 char *android_srcdir, *data_srcdir;
1628
1629 if(srcarg == NULL) {
1630 android_srcdir = product_file("system");
1631 data_srcdir = product_file("data");
1632 } else {
1633 /* srcarg may be "data", "system" or NULL.
1634 * if srcarg is NULL, then both data and system are synced
1635 */
1636 if(strcmp(srcarg, "system") == 0) {
1637 android_srcdir = product_file("system");
1638 data_srcdir = NULL;
1639 } else if(strcmp(srcarg, "data") == 0) {
1640 android_srcdir = NULL;
1641 data_srcdir = product_file("data");
1642 } else {
1643 /* It's not "system" or "data".
1644 */
1645 return 1;
1646 }
1647 }
1648
1649 if(android_srcdir_out != NULL)
1650 *android_srcdir_out = android_srcdir;
1651 else
1652 free(android_srcdir);
1653
1654 if(data_srcdir_out != NULL)
1655 *data_srcdir_out = data_srcdir;
1656 else
1657 free(data_srcdir);
1658
1659 return 0;
1660}
1661
1662static int pm_command(transport_type transport, char* serial,
1663 int argc, char** argv)
1664{
1665 char buf[4096];
1666
1667 snprintf(buf, sizeof(buf), "shell:pm");
1668
1669 while(argc-- > 0) {
1670 char *quoted;
1671
1672 quoted = dupAndQuote(*argv++);
1673
1674 strncat(buf, " ", sizeof(buf)-1);
1675 strncat(buf, quoted, sizeof(buf)-1);
1676 free(quoted);
1677 }
1678
1679 send_shellcommand(transport, serial, buf);
1680 return 0;
1681}
1682
1683int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1684{
1685 /* if the user choose the -k option, we refuse to do it until devices are
1686 out with the option to uninstall the remaining data somehow (adb/ui) */
1687 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1688 {
1689 printf(
1690 "The -k option uninstalls the application while retaining the data/cache.\n"
1691 "At the moment, there is no way to remove the remaining data.\n"
1692 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1693 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1694 return -1;
1695 }
1696
1697 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1698 return pm_command(transport, serial, argc, argv);
1699}
1700
1701static int delete_file(transport_type transport, char* serial, char* filename)
1702{
1703 char buf[4096];
1704 char* quoted;
1705
1706 snprintf(buf, sizeof(buf), "shell:rm ");
1707 quoted = dupAndQuote(filename);
1708 strncat(buf, quoted, sizeof(buf)-1);
1709 free(quoted);
1710
1711 send_shellcommand(transport, serial, buf);
1712 return 0;
1713}
1714
Kenny Root3802c992011-08-05 11:19:45 -07001715static const char* get_basename(const char* filename)
1716{
1717 const char* basename = adb_dirstop(filename);
1718 if (basename) {
1719 basename++;
1720 return basename;
1721 } else {
1722 return filename;
1723 }
1724}
1725
1726static int check_file(const char* filename)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001727{
1728 struct stat st;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001729
Kenny Root3802c992011-08-05 11:19:45 -07001730 if (filename == NULL) {
1731 return 0;
Mike Lockwood4cc5c012010-02-19 17:53:27 -05001732 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001733
Kenny Root3802c992011-08-05 11:19:45 -07001734 if (stat(filename, &st) != 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001735 fprintf(stderr, "can't find '%s' to install\n", filename);
1736 return 1;
1737 }
Kenny Root3802c992011-08-05 11:19:45 -07001738
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001739 if (!S_ISREG(st.st_mode)) {
Kenny Root3802c992011-08-05 11:19:45 -07001740 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001741 return 1;
1742 }
1743
Kenny Root3802c992011-08-05 11:19:45 -07001744 return 0;
1745}
1746
1747int install_app(transport_type transport, char* serial, int argc, char** argv)
1748{
1749 static const char *const DATA_DEST = "/data/local/tmp/%s";
1750 static const char *const SD_DEST = "/sdcard/tmp/%s";
1751 const char* where = DATA_DEST;
1752 char apk_dest[PATH_MAX];
1753 char verification_dest[PATH_MAX];
1754 char* apk_file;
1755 char* verification_file = NULL;
1756 int file_arg = -1;
1757 int err;
1758 int i;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001759 int verify_apk = 1;
Kenny Root3802c992011-08-05 11:19:45 -07001760
1761 for (i = 1; i < argc; i++) {
1762 if (*argv[i] != '-') {
1763 file_arg = i;
1764 break;
Kenny Root500b15a2011-09-23 12:46:39 -07001765 } else if (!strcmp(argv[i], "-i")) {
1766 // Skip the installer package name.
1767 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001768 } else if (!strcmp(argv[i], "-s")) {
1769 where = SD_DEST;
Anonymous Coward5fe7ec22012-04-24 10:43:41 -07001770 } else if (!strcmp(argv[i], "--algo")) {
1771 verify_apk = 0;
1772 i++;
1773 } else if (!strcmp(argv[i], "--iv")) {
1774 verify_apk = 0;
1775 i++;
1776 } else if (!strcmp(argv[i], "--key")) {
1777 verify_apk = 0;
1778 i++;
Kenny Root3802c992011-08-05 11:19:45 -07001779 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001780 }
1781
Kenny Root3802c992011-08-05 11:19:45 -07001782 if (file_arg < 0) {
Kenny Root500b15a2011-09-23 12:46:39 -07001783 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root3802c992011-08-05 11:19:45 -07001784 return 1;
1785 } else if (file_arg + 2 < argc) {
Kenny Root500b15a2011-09-23 12:46:39 -07001786 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root3802c992011-08-05 11:19:45 -07001787 return 1;
1788 }
1789
1790 apk_file = argv[file_arg];
1791
1792 if (file_arg != argc - 1) {
1793 verification_file = argv[file_arg + 1];
1794 }
1795
1796 if (check_file(apk_file) || check_file(verification_file)) {
1797 return 1;
1798 }
1799
1800 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1801 if (verification_file != NULL) {
1802 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1803
1804 if (!strcmp(apk_dest, verification_dest)) {
1805 fprintf(stderr, "APK and verification file can't have the same name\n");
1806 return 1;
1807 }
1808 }
1809
Mark Lindner9f9d1452014-03-11 17:55:59 -07001810 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001811 if (err) {
Kenny Root58d5f222012-03-26 16:14:02 -07001812 goto cleanup_apk;
Kenny Root3802c992011-08-05 11:19:45 -07001813 } else {
1814 argv[file_arg] = apk_dest; /* destination name, not source location */
1815 }
1816
1817 if (verification_file != NULL) {
Mark Lindner9f9d1452014-03-11 17:55:59 -07001818 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1819 0 /* no show progress */);
Kenny Root3802c992011-08-05 11:19:45 -07001820 if (err) {
1821 goto cleanup_apk;
1822 } else {
1823 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1824 }
1825 }
1826
1827 pm_command(transport, serial, argc, argv);
1828
Kenny Root58d5f222012-03-26 16:14:02 -07001829cleanup_apk:
Kenny Root3802c992011-08-05 11:19:45 -07001830 if (verification_file != NULL) {
1831 delete_file(transport, serial, verification_dest);
1832 }
1833
Kenny Root3802c992011-08-05 11:19:45 -07001834 delete_file(transport, serial, apk_dest);
1835
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001836 return err;
1837}