blob: 4f2d40fbba793b56648001966cd8a3a412a33aef [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 Molnarde8ff4a2013-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 Molnarde8ff4a2013-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"
Jeff Browna77bef42014-04-15 13:34:04 -0700154 " adb install [-l] [-r] [-d] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700155 " - 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"
Jeff Browna77bef42014-04-15 13:34:04 -0700158 " ('-d' means allow version code downgrade)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500159 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700160 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800161 " adb uninstall [-k] <package> - remove this app package from the device\n"
162 " ('-k' means keep the data and cache directories)\n"
163 " adb bugreport - return all information from the device\n"
164 " that should be included in a bug report.\n"
165 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800166 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700167 " - write an archive of the device's data to <file>.\n"
168 " If no -f option is supplied then the data is written\n"
169 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700170 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700171 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800172 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
173 " (aka .obb) files associated with each application; the default\n"
174 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700175 " (-shared|-noshared enable/disable backup of the device's\n"
176 " shared storage / SD card contents; the default is noshared.)\n"
177 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700178 " (-system|-nosystem toggles whether -all automatically includes\n"
179 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700180 " (<packages...> is the list of applications to be backed up. If\n"
181 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700182 " list is optional. Applications explicitly given on the\n"
183 " command line will be included even if -nosystem would\n"
184 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700185 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700186 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700187 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800188 " adb help - show this help message\n"
189 " adb version - show version num\n"
190 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800191 "scripting:\n"
192 " adb wait-for-device - block until device is online\n"
193 " adb start-server - ensure that there is a server running\n"
194 " adb kill-server - kill the server if it is running\n"
195 " adb get-state - prints: offline | bootloader | device\n"
196 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700197 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800198 " adb status-window - continuously print device status for a specified device\n"
199 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400200 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800201 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700202 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800203 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700204 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800205 "\n"
206 "networking:\n"
207 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500208 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
210 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
211 "\n"
212 "adb sync notes: adb sync [ <directory> ]\n"
213 " <localdir> can be interpreted in several ways:\n"
214 "\n"
215 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
216 "\n"
217 " - If it is \"system\" or \"data\", only the corresponding partition\n"
218 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000219 "\n"
220 "environmental variables:\n"
221 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
222 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
223 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
224 " 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 -0800225 );
226}
227
228int usage()
229{
230 help();
231 return 1;
232}
233
234#ifdef HAVE_TERMIO_H
235static struct termios tio_save;
236
237static void stdin_raw_init(int fd)
238{
239 struct termios tio;
240
241 if(tcgetattr(fd, &tio)) return;
242 if(tcgetattr(fd, &tio_save)) return;
243
244 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
245
246 /* no timeout but request at least one character per read */
247 tio.c_cc[VTIME] = 0;
248 tio.c_cc[VMIN] = 1;
249
250 tcsetattr(fd, TCSANOW, &tio);
251 tcflush(fd, TCIFLUSH);
252}
253
254static void stdin_raw_restore(int fd)
255{
256 tcsetattr(fd, TCSANOW, &tio_save);
257 tcflush(fd, TCIFLUSH);
258}
259#endif
260
261static void read_and_dump(int fd)
262{
263 char buf[4096];
264 int len;
265
266 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700267 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800268 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700269 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270 if(len == 0) {
271 break;
272 }
273
274 if(len < 0) {
275 if(errno == EINTR) continue;
276 break;
277 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400278 fwrite(buf, 1, len, stdout);
279 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800280 }
281}
282
Christopher Tated2f54152011-04-21 12:53:28 -0700283static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700284 const size_t BUFSIZE = 32 * 1024;
285 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700286 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700287 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700288
289 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700290#ifdef HAVE_TERMIO_H
291 if (inFd == STDIN_FILENO) {
292 stdin_raw_init(STDIN_FILENO);
293 }
294#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700295 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700296 if (inFd == STDIN_FILENO) {
297 len = unix_read(inFd, buf, BUFSIZE);
298 } else {
299 len = adb_read(inFd, buf, BUFSIZE);
300 }
Christopher Tated2f54152011-04-21 12:53:28 -0700301 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700302 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700303 break;
304 }
305 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700306 if (errno == EINTR) {
307 D("copy_to_file() : EINTR, retrying\n");
308 continue;
309 }
Christopher Tated2f54152011-04-21 12:53:28 -0700310 D("copy_to_file() : error %d\n", errno);
311 break;
312 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700313 if (outFd == STDOUT_FILENO) {
314 fwrite(buf, 1, len, stdout);
315 fflush(stdout);
316 } else {
317 adb_write(outFd, buf, len);
318 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700319 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700320 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700321#ifdef HAVE_TERMIO_H
322 if (inFd == STDIN_FILENO) {
323 stdin_raw_restore(STDIN_FILENO);
324 }
325#endif
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700326 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700327 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700328}
329
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800330static void *stdin_read_thread(void *x)
331{
332 int fd, fdi;
333 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800334 int r, n;
335 int state = 0;
336
337 int *fds = (int*) x;
338 fd = fds[0];
339 fdi = fds[1];
340 free(fds);
341
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800342 for(;;) {
343 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700344 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800345 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700346 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800347 if(r == 0) break;
348 if(r < 0) {
349 if(errno == EINTR) continue;
350 break;
351 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400352 for(n = 0; n < r; n++){
353 switch(buf[n]) {
354 case '\n':
355 state = 1;
356 break;
357 case '\r':
358 state = 1;
359 break;
360 case '~':
361 if(state == 1) state++;
362 break;
363 case '.':
364 if(state == 2) {
365 fprintf(stderr,"\n* disconnect *\n");
366#ifdef HAVE_TERMIO_H
367 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800368#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400369 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400371 default:
372 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 r = adb_write(fd, buf, r);
376 if(r <= 0) {
377 break;
378 }
379 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380 return 0;
381}
382
383int interactive_shell(void)
384{
385 adb_thread_t thr;
386 int fdi, fd;
387 int *fds;
388
389 fd = adb_connect("shell:");
390 if(fd < 0) {
391 fprintf(stderr,"error: %s\n", adb_error());
392 return 1;
393 }
394 fdi = 0; //dup(0);
395
396 fds = malloc(sizeof(int) * 2);
397 fds[0] = fd;
398 fds[1] = fdi;
399
400#ifdef HAVE_TERMIO_H
401 stdin_raw_init(fdi);
402#endif
403 adb_thread_create(&thr, stdin_read_thread, fds);
404 read_and_dump(fd);
405#ifdef HAVE_TERMIO_H
406 stdin_raw_restore(fdi);
407#endif
408 return 0;
409}
410
411
412static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
413{
414 if (serial) {
415 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
416 } else {
417 const char* prefix = "host";
418 if (ttype == kTransportUsb)
419 prefix = "host-usb";
420 else if (ttype == kTransportLocal)
421 prefix = "host-local";
422
423 snprintf(buffer, buflen, "%s:%s", prefix, command);
424 }
425}
426
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100427int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800428 unsigned progress)
429{
430 char buf[4096];
431 unsigned total;
432 int fd;
433 const unsigned char *ptr;
434
435 sprintf(buf,"%s:%d", service, sz);
436 fd = adb_connect(buf);
437 if(fd < 0) {
438 fprintf(stderr,"error: %s\n", adb_error());
439 return -1;
440 }
441
442 int opt = CHUNK_SIZE;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700443 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800444
445 total = sz;
446 ptr = data;
447
448 if(progress) {
449 char *x = strrchr(service, ':');
450 if(x) service = x + 1;
451 }
452
453 while(sz > 0) {
454 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
455 if(writex(fd, ptr, xfer)) {
456 adb_status(fd);
457 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
458 return -1;
459 }
460 sz -= xfer;
461 ptr += xfer;
462 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100463 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800464 fflush(stdout);
465 }
466 }
467 if(progress) {
468 printf("\n");
469 }
470
471 if(readx(fd, buf, 4)){
472 fprintf(stderr,"* error reading response *\n");
473 adb_close(fd);
474 return -1;
475 }
476 if(memcmp(buf, "OKAY", 4)) {
477 buf[4] = 0;
478 fprintf(stderr,"* error response '%s' *\n", buf);
479 adb_close(fd);
480 return -1;
481 }
482
483 adb_close(fd);
484 return 0;
485}
486
487
488int adb_download(const char *service, const char *fn, unsigned progress)
489{
490 void *data;
491 unsigned sz;
492
493 data = load_file(fn, &sz);
494 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100495 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800496 return -1;
497 }
498
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100499 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800500 free(data);
501 return status;
502}
503
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800504static void status_window(transport_type ttype, const char* serial)
505{
506 char command[4096];
507 char *state = 0;
508 char *laststate = 0;
509
510 /* silence stderr */
511#ifdef _WIN32
512 /* XXX: TODO */
513#else
514 int fd;
515 fd = unix_open("/dev/null", O_WRONLY);
516 dup2(fd, 2);
517 adb_close(fd);
518#endif
519
520 format_host_command(command, sizeof command, "get-state", ttype, serial);
521
522 for(;;) {
523 adb_sleep_ms(250);
524
525 if(state) {
526 free(state);
527 state = 0;
528 }
529
530 state = adb_query(command);
531
532 if(state) {
533 if(laststate && !strcmp(state,laststate)){
534 continue;
535 } else {
536 if(laststate) free(laststate);
537 laststate = strdup(state);
538 }
539 }
540
541 printf("%c[2J%c[2H", 27, 27);
542 printf("Android Debug Bridge\n");
543 printf("State: %s\n", state ? state : "offline");
544 fflush(stdout);
545 }
546}
547
548/** duplicate string and quote all \ " ( ) chars + space character. */
549static char *
550dupAndQuote(const char *s)
551{
552 const char *ts;
553 size_t alloc_len;
554 char *ret;
555 char *dest;
556
557 ts = s;
558
559 alloc_len = 0;
560
561 for( ;*ts != '\0'; ts++) {
562 alloc_len++;
563 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
564 alloc_len++;
565 }
566 }
567
568 ret = (char *)malloc(alloc_len + 1);
569
570 ts = s;
571 dest = ret;
572
573 for ( ;*ts != '\0'; ts++) {
574 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
575 *dest++ = '\\';
576 }
577
578 *dest++ = *ts;
579 }
580
581 *dest++ = '\0';
582
583 return ret;
584}
585
586/**
587 * Run ppp in "notty" mode against a resource listed as the first parameter
588 * eg:
589 *
590 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
591 *
592 */
593int ppp(int argc, char **argv)
594{
595#ifdef HAVE_WIN32_PROC
596 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
597 return -1;
598#else
599 char *adb_service_name;
600 pid_t pid;
601 int fd;
602
603 if (argc < 2) {
604 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
605 argv[0]);
606
607 return 1;
608 }
609
610 adb_service_name = argv[1];
611
612 fd = adb_connect(adb_service_name);
613
614 if(fd < 0) {
615 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
616 adb_service_name, adb_error());
617 return 1;
618 }
619
620 pid = fork();
621
622 if (pid < 0) {
623 perror("from fork()");
624 return 1;
625 } else if (pid == 0) {
626 int err;
627 int i;
628 const char **ppp_args;
629
630 // copy args
631 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
632 ppp_args[0] = "pppd";
633 for (i = 2 ; i < argc ; i++) {
634 //argv[2] and beyond become ppp_args[1] and beyond
635 ppp_args[i - 1] = argv[i];
636 }
637 ppp_args[i-1] = NULL;
638
639 // child side
640
641 dup2(fd, STDIN_FILENO);
642 dup2(fd, STDOUT_FILENO);
643 adb_close(STDERR_FILENO);
644 adb_close(fd);
645
646 err = execvp("pppd", (char * const *)ppp_args);
647
648 if (err < 0) {
649 perror("execing pppd");
650 }
651 exit(-1);
652 } else {
653 // parent side
654
655 adb_close(fd);
656 return 0;
657 }
658#endif /* !HAVE_WIN32_PROC */
659}
660
661static int send_shellcommand(transport_type transport, char* serial, char* buf)
662{
663 int fd, ret;
664
665 for(;;) {
666 fd = adb_connect(buf);
667 if(fd >= 0)
668 break;
669 fprintf(stderr,"- waiting for device -\n");
670 adb_sleep_ms(1000);
671 do_cmd(transport, serial, "wait-for-device", 0);
672 }
673
674 read_and_dump(fd);
675 ret = adb_close(fd);
676 if (ret)
677 perror("close");
678
679 return ret;
680}
681
682static int logcat(transport_type transport, char* serial, int argc, char **argv)
683{
684 char buf[4096];
685
686 char *log_tags;
687 char *quoted_log_tags;
688
689 log_tags = getenv("ANDROID_LOG_TAGS");
690 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
691
692 snprintf(buf, sizeof(buf),
693 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
694 quoted_log_tags);
695
696 free(quoted_log_tags);
697
Christopher Tatedb0a8802011-11-30 13:00:33 -0800698 if (!strcmp(argv[0],"longcat")) {
699 strncat(buf, " -v long", sizeof(buf)-1);
700 }
701
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800702 argc -= 1;
703 argv += 1;
704 while(argc-- > 0) {
705 char *quoted;
706
707 quoted = dupAndQuote (*argv++);
708
709 strncat(buf, " ", sizeof(buf)-1);
710 strncat(buf, quoted, sizeof(buf)-1);
711 free(quoted);
712 }
713
714 send_shellcommand(transport, serial, buf);
715 return 0;
716}
717
Mark Salyzyn60299df2014-04-30 09:10:31 -0700718static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800719{
720 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700721 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800722
723 for(;;) {
724 x = adb_dirstart(x);
725 if(x == 0) return 0;
726 *x = 0;
727 ret = adb_mkdir(path, 0775);
728 *x = OS_PATH_SEPARATOR;
729 if((ret < 0) && (errno != EEXIST)) {
730 return ret;
731 }
732 x++;
733 }
734 return 0;
735}
736
Christopher Tated2f54152011-04-21 12:53:28 -0700737static int backup(int argc, char** argv) {
738 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800739 char default_name[32];
740 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700741 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700742 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700743
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700744 /* find, extract, and use any -f argument */
745 for (i = 1; i < argc; i++) {
746 if (!strcmp("-f", argv[i])) {
747 if (i == argc-1) {
748 fprintf(stderr, "adb: -f passed with no filename\n");
749 return usage();
750 }
751 filename = argv[i+1];
752 for (j = i+2; j <= argc; ) {
753 argv[i++] = argv[j++];
754 }
755 argc -= 2;
756 argv[argc] = NULL;
757 }
Christopher Tated2f54152011-04-21 12:53:28 -0700758 }
759
Christopher Tatebb86bc52011-08-22 17:12:08 -0700760 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
761 if (argc < 2) return usage();
762
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800763 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700764 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800765 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700766 if (outFd < 0) {
767 fprintf(stderr, "adb: unable to open file %s\n", filename);
768 return -1;
769 }
770
771 snprintf(buf, sizeof(buf), "backup");
772 for (argc--, argv++; argc; argc--, argv++) {
773 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
774 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
775 }
776
777 D("backup. filename=%s buf=%s\n", filename, buf);
778 fd = adb_connect(buf);
779 if (fd < 0) {
780 fprintf(stderr, "adb: unable to connect for backup\n");
781 adb_close(outFd);
782 return -1;
783 }
784
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800785 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700786 copy_to_file(fd, outFd);
787
788 adb_close(fd);
789 adb_close(outFd);
790 return 0;
791}
792
Christopher Tate702967a2011-05-17 15:52:54 -0700793static int restore(int argc, char** argv) {
794 const char* filename;
795 int fd, tarFd;
796
797 if (argc != 2) return usage();
798
799 filename = argv[1];
800 tarFd = adb_open(filename, O_RDONLY);
801 if (tarFd < 0) {
802 fprintf(stderr, "adb: unable to open file %s\n", filename);
803 return -1;
804 }
805
806 fd = adb_connect("restore:");
807 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700808 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700809 adb_close(tarFd);
810 return -1;
811 }
812
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800813 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700814 copy_to_file(tarFd, fd);
815
816 adb_close(fd);
817 adb_close(tarFd);
818 return 0;
819}
820
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800821#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
822static int top_works(const char *top)
823{
824 if (top != NULL && adb_is_absolute_host_path(top)) {
825 char path_buf[PATH_MAX];
826 snprintf(path_buf, sizeof(path_buf),
827 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
828 return access(path_buf, F_OK) == 0;
829 }
830 return 0;
831}
832
833static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
834{
835 strcpy(path_buf, indir);
836 while (1) {
837 if (top_works(path_buf)) {
838 return path_buf;
839 }
840 char *s = adb_dirstop(path_buf);
841 if (s != NULL) {
842 *s = '\0';
843 } else {
844 path_buf[0] = '\0';
845 return NULL;
846 }
847 }
848}
849
850static char *find_top(char path_buf[PATH_MAX])
851{
852 char *top = getenv("ANDROID_BUILD_TOP");
853 if (top != NULL && top[0] != '\0') {
854 if (!top_works(top)) {
855 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
856 return NULL;
857 }
858 } else {
859 top = getenv("TOP");
860 if (top != NULL && top[0] != '\0') {
861 if (!top_works(top)) {
862 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
863 return NULL;
864 }
865 } else {
866 top = NULL;
867 }
868 }
869
870 if (top != NULL) {
871 /* The environment pointed to a top directory that works.
872 */
873 strcpy(path_buf, top);
874 return path_buf;
875 }
876
877 /* The environment didn't help. Walk up the tree from the CWD
878 * to see if we can find the top.
879 */
880 char dir[PATH_MAX];
881 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
882 if (top == NULL) {
883 /* If the CWD isn't under a good-looking top, see if the
884 * executable is.
885 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100886 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800887 top = find_top_from(dir, path_buf);
888 }
889 return top;
890}
891
892/* <hint> may be:
893 * - A simple product name
894 * e.g., "sooner"
895TODO: debug? sooner-debug, sooner:debug?
896 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
897 * e.g., "out/target/product/sooner"
898 * - An absolute path to the PRODUCT_OUT dir
899 * e.g., "/src/device/out/target/product/sooner"
900 *
901 * Given <hint>, try to construct an absolute path to the
902 * ANDROID_PRODUCT_OUT dir.
903 */
904static const char *find_product_out_path(const char *hint)
905{
906 static char path_buf[PATH_MAX];
907
908 if (hint == NULL || hint[0] == '\0') {
909 return NULL;
910 }
911
912 /* If it's already absolute, don't bother doing any work.
913 */
914 if (adb_is_absolute_host_path(hint)) {
915 strcpy(path_buf, hint);
916 return path_buf;
917 }
918
919 /* If there are any slashes in it, assume it's a relative path;
920 * make it absolute.
921 */
922 if (adb_dirstart(hint) != NULL) {
923 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
924 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
925 return NULL;
926 }
927 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
928 fprintf(stderr, "adb: Couldn't assemble path\n");
929 return NULL;
930 }
931 strcat(path_buf, OS_PATH_SEPARATOR_STR);
932 strcat(path_buf, hint);
933 return path_buf;
934 }
935
936 /* It's a string without any slashes. Try to do something with it.
937 *
938 * Try to find the root of the build tree, and build a PRODUCT_OUT
939 * path from there.
940 */
941 char top_buf[PATH_MAX];
942 const char *top = find_top(top_buf);
943 if (top == NULL) {
944 fprintf(stderr, "adb: Couldn't find top of build tree\n");
945 return NULL;
946 }
947//TODO: if we have a way to indicate debug, look in out/debug/target/...
948 snprintf(path_buf, sizeof(path_buf),
949 "%s" OS_PATH_SEPARATOR_STR
950 "out" OS_PATH_SEPARATOR_STR
951 "target" OS_PATH_SEPARATOR_STR
952 "product" OS_PATH_SEPARATOR_STR
953 "%s", top_buf, hint);
954 if (access(path_buf, F_OK) < 0) {
955 fprintf(stderr, "adb: Couldn't find a product dir "
956 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
957 return NULL;
958 }
959 return path_buf;
960}
961
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700962static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
963 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700964 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700965 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700966
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700967 while (narg > 0) {
968 if (!strcmp(*arg, "-p")) {
969 *show_progress = 1;
970 } else if (!strcmp(*arg, "-a")) {
971 *copy_attrs = 1;
972 } else {
973 break;
974 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700975 ++arg;
976 --narg;
977 }
978
979 if (narg > 0) {
980 *path1 = *arg;
981 ++arg;
982 --narg;
983 }
984
985 if (narg > 0) {
986 *path2 = *arg;
987 }
988}
989
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800990int adb_commandline(int argc, char **argv)
991{
992 char buf[4096];
993 int no_daemon = 0;
994 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100995 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 int persist = 0;
997 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800998 transport_type ttype = kTransportAny;
999 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001000 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001001
1002 /* If defined, this should be an absolute path to
1003 * the directory containing all of the various system images
1004 * for a particular product. If not defined, and the adb
1005 * command requires this information, then the user must
1006 * specify the path using "-p".
1007 */
1008 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1009 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1010 gProductOutPath = NULL;
1011 }
1012 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1013
Nick Pellydb449262009-05-07 12:48:03 -07001014 serial = getenv("ANDROID_SERIAL");
1015
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001016 /* Validate and assign the server port */
1017 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1018 int server_port = DEFAULT_ADB_PORT;
1019 if (server_port_str && strlen(server_port_str) > 0) {
1020 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001021 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001022 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001023 "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 +01001024 server_port_str);
1025 return usage();
1026 }
1027 }
1028
1029 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001030 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001031 if(!strcmp(argv[0],"server")) {
1032 is_server = 1;
1033 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001034 no_daemon = 1;
1035 } else if (!strcmp(argv[0], "fork-server")) {
1036 /* this is a special flag used only when the ADB client launches the ADB Server */
1037 is_daemon = 1;
1038 } else if(!strcmp(argv[0],"persist")) {
1039 persist = 1;
1040 } else if(!strncmp(argv[0], "-p", 2)) {
1041 const char *product = NULL;
1042 if (argv[0][2] == '\0') {
1043 if (argc < 2) return usage();
1044 product = argv[1];
1045 argc--;
1046 argv++;
1047 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001048 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001049 }
1050 gProductOutPath = find_product_out_path(product);
1051 if (gProductOutPath == NULL) {
1052 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1053 product);
1054 return usage();
1055 }
1056 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1057 if (isdigit(argv[0][2])) {
1058 serial = argv[0] + 2;
1059 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001060 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001061 serial = argv[1];
1062 argc--;
1063 argv++;
1064 }
1065 } else if (!strcmp(argv[0],"-d")) {
1066 ttype = kTransportUsb;
1067 } else if (!strcmp(argv[0],"-e")) {
1068 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001069 } else if (!strcmp(argv[0],"-a")) {
1070 gListenAll = 1;
1071 } else if(!strncmp(argv[0], "-H", 2)) {
1072 const char *hostname = NULL;
1073 if (argv[0][2] == '\0') {
1074 if (argc < 2) return usage();
1075 hostname = argv[1];
1076 argc--;
1077 argv++;
1078 } else {
1079 hostname = argv[0] + 2;
1080 }
1081 adb_set_tcp_name(hostname);
1082
1083 } else if(!strncmp(argv[0], "-P", 2)) {
1084 if (argv[0][2] == '\0') {
1085 if (argc < 2) return usage();
1086 server_port_str = argv[1];
1087 argc--;
1088 argv++;
1089 } else {
1090 server_port_str = argv[0] + 2;
1091 }
1092 if (strlen(server_port_str) > 0) {
1093 server_port = (int) strtol(server_port_str, NULL, 0);
1094 if (server_port <= 0 || server_port > 65535) {
1095 fprintf(stderr,
1096 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1097 server_port_str);
1098 return usage();
1099 }
1100 } else {
1101 fprintf(stderr,
1102 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1103 return usage();
1104 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001105 } else {
1106 /* out of recognized modifiers and flags */
1107 break;
1108 }
1109 argc--;
1110 argv++;
1111 }
1112
1113 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001114 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001115
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001116 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001117 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001118 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001119 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001120 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001121 }
1122 if(r) {
1123 fprintf(stderr,"* could not start server *\n");
1124 }
1125 return r;
1126 }
1127
1128top:
1129 if(argc == 0) {
1130 return usage();
1131 }
1132
1133 /* adb_connect() commands */
1134
1135 if(!strcmp(argv[0], "devices")) {
1136 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001137 char *listopt;
1138 if (argc < 2)
1139 listopt = "";
1140 else if (argc == 2 && !strcmp(argv[1], "-l"))
1141 listopt = argv[1];
1142 else {
1143 fprintf(stderr, "Usage: adb devices [-l]\n");
1144 return 1;
1145 }
1146 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001147 tmp = adb_query(buf);
1148 if(tmp) {
1149 printf("List of devices attached \n");
1150 printf("%s\n", tmp);
1151 return 0;
1152 } else {
1153 return 1;
1154 }
1155 }
1156
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001157 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001158 char *tmp;
1159 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001160 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001161 return 1;
1162 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001163 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1164 tmp = adb_query(buf);
1165 if(tmp) {
1166 printf("%s\n", tmp);
1167 return 0;
1168 } else {
1169 return 1;
1170 }
1171 }
1172
1173 if(!strcmp(argv[0], "disconnect")) {
1174 char *tmp;
1175 if (argc > 2) {
1176 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1177 return 1;
1178 }
1179 if (argc == 2) {
1180 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1181 } else {
1182 snprintf(buf, sizeof buf, "host:disconnect:");
1183 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001184 tmp = adb_query(buf);
1185 if(tmp) {
1186 printf("%s\n", tmp);
1187 return 0;
1188 } else {
1189 return 1;
1190 }
1191 }
1192
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001193 if (!strcmp(argv[0], "emu")) {
1194 return adb_send_emulator_command(argc, argv);
1195 }
1196
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001197 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001198 int r;
1199 int fd;
1200
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001201 char h = (argv[0][0] == 'h');
1202
1203 if (h) {
1204 printf("\x1b[41;33m");
1205 fflush(stdout);
1206 }
1207
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001208 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001209 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001210 r = interactive_shell();
1211 if (h) {
1212 printf("\x1b[0m");
1213 fflush(stdout);
1214 }
1215 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001216 }
1217
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001218 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001219 argc -= 2;
1220 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001221 while (argc-- > 0) {
1222 char *quoted = dupAndQuote(*argv++);
1223 strncat(buf, " ", sizeof(buf) - 1);
1224 strncat(buf, quoted, sizeof(buf) - 1);
1225 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001226 }
1227
1228 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001229 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001230 fd = adb_connect(buf);
1231 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001232 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001233 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001234 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001235 adb_close(fd);
1236 r = 0;
1237 } else {
1238 fprintf(stderr,"error: %s\n", adb_error());
1239 r = -1;
1240 }
1241
1242 if(persist) {
1243 fprintf(stderr,"\n- waiting for device -\n");
1244 adb_sleep_ms(1000);
1245 do_cmd(ttype, serial, "wait-for-device", 0);
1246 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001247 if (h) {
1248 printf("\x1b[0m");
1249 fflush(stdout);
1250 }
JP Abgrall408fa572011-03-16 15:57:42 -07001251 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001252 return r;
1253 }
1254 }
1255 }
1256
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001257 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1258 int exec_in = !strcmp(argv[0], "exec-in");
1259 int fd;
1260
1261 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1262 argc -= 2;
1263 argv += 2;
1264 while (argc-- > 0) {
1265 char *quoted = dupAndQuote(*argv++);
1266 strncat(buf, " ", sizeof(buf) - 1);
1267 strncat(buf, quoted, sizeof(buf) - 1);
1268 free(quoted);
1269 }
1270
1271 fd = adb_connect(buf);
1272 if (fd < 0) {
1273 fprintf(stderr, "error: %s\n", adb_error());
1274 return -1;
1275 }
1276
1277 if (exec_in) {
1278 copy_to_file(STDIN_FILENO, fd);
1279 } else {
1280 copy_to_file(fd, STDOUT_FILENO);
1281 }
1282
1283 adb_close(fd);
1284 return 0;
1285 }
1286
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001287 if(!strcmp(argv[0], "kill-server")) {
1288 int fd;
1289 fd = _adb_connect("host:kill");
1290 if(fd == -1) {
1291 fprintf(stderr,"* server not running *\n");
1292 return 1;
1293 }
1294 return 0;
1295 }
1296
Doug Zongker447f0612012-01-09 14:54:53 -08001297 if(!strcmp(argv[0], "sideload")) {
1298 if(argc != 2) return usage();
1299 if(adb_download("sideload", argv[1], 1)) {
1300 return 1;
1301 } else {
1302 return 0;
1303 }
1304 }
1305
Mike Lockwoodff196702009-08-24 15:58:40 -07001306 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001307 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001308 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001309 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001310 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001311 if (!strcmp(argv[0], "reboot-bootloader"))
1312 snprintf(command, sizeof(command), "reboot:bootloader");
1313 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001314 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001315 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001316 snprintf(command, sizeof(command), "%s:", argv[0]);
1317 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001318 if(fd >= 0) {
1319 read_and_dump(fd);
1320 adb_close(fd);
1321 return 0;
1322 }
1323 fprintf(stderr,"error: %s\n", adb_error());
1324 return 1;
1325 }
1326
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001327 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001328 if (argc != 1) return usage();
1329 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001330 return 0;
1331 }
1332
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001333 /* adb_command() wrapper commands */
1334
1335 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1336 char* service = argv[0];
1337 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1338 if (ttype == kTransportUsb) {
1339 service = "wait-for-usb";
1340 } else if (ttype == kTransportLocal) {
1341 service = "wait-for-local";
1342 } else {
1343 service = "wait-for-any";
1344 }
1345 }
1346
1347 format_host_command(buf, sizeof buf, service, ttype, serial);
1348
1349 if (adb_command(buf)) {
1350 D("failure: %s *\n",adb_error());
1351 fprintf(stderr,"error: %s\n", adb_error());
1352 return 1;
1353 }
1354
1355 /* Allow a command to be run after wait-for-device,
1356 * e.g. 'adb wait-for-device shell'.
1357 */
1358 if(argc > 1) {
1359 argc--;
1360 argv++;
1361 goto top;
1362 }
1363 return 0;
1364 }
1365
David 'Digit' Turner25258692013-03-21 21:07:42 +01001366 if(!strcmp(argv[0], "forward") ||
1367 !strcmp(argv[0], "reverse"))
1368 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001369 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001370 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001371 char remove = 0;
1372 char remove_all = 0;
1373 char list = 0;
1374 char no_rebind = 0;
1375
1376 // Parse options here.
1377 while (argc > 1 && argv[1][0] == '-') {
1378 if (!strcmp(argv[1], "--list"))
1379 list = 1;
1380 else if (!strcmp(argv[1], "--remove"))
1381 remove = 1;
1382 else if (!strcmp(argv[1], "--remove-all"))
1383 remove_all = 1;
1384 else if (!strcmp(argv[1], "--no-rebind"))
1385 no_rebind = 1;
1386 else {
1387 return usage();
1388 }
1389 argc--;
1390 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001391 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001392
1393 // Ensure we can only use one option at a time.
1394 if (list + remove + remove_all + no_rebind > 1) {
1395 return usage();
1396 }
1397
1398 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001399 if (reverse) {
1400 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001401 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001402 if (serial) {
1403 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1404 serial);
1405 } else if (ttype == kTransportUsb) {
1406 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1407 } else if (ttype == kTransportLocal) {
1408 snprintf(host_prefix, sizeof host_prefix, "host-local");
1409 } else {
1410 snprintf(host_prefix, sizeof host_prefix, "host");
1411 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001412 }
1413
1414 // Implement forward --list
1415 if (list) {
1416 if (argc != 1)
1417 return usage();
1418 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1419 char* forwards = adb_query(buf);
1420 if (forwards == NULL) {
1421 fprintf(stderr, "error: %s\n", adb_error());
1422 return 1;
1423 }
1424 printf("%s", forwards);
1425 free(forwards);
1426 return 0;
1427 }
1428
1429 // Implement forward --remove-all
1430 else if (remove_all) {
1431 if (argc != 1)
1432 return usage();
1433 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1434 }
1435
1436 // Implement forward --remove <local>
1437 else if (remove) {
1438 if (argc != 2)
1439 return usage();
1440 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1441 }
1442 // Or implement one of:
1443 // forward <local> <remote>
1444 // forward --no-rebind <local> <remote>
1445 else
1446 {
1447 if (argc != 3)
1448 return usage();
1449 const char* command = no_rebind ? "forward:norebind:" : "forward";
1450 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1451 }
1452
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001453 if(adb_command(buf)) {
1454 fprintf(stderr,"error: %s\n", adb_error());
1455 return 1;
1456 }
1457 return 0;
1458 }
1459
1460 /* do_sync_*() commands */
1461
1462 if(!strcmp(argv[0], "ls")) {
1463 if(argc != 2) return usage();
1464 return do_sync_ls(argv[1]);
1465 }
1466
1467 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001468 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001469 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001470 const char* lpath = NULL, *rpath = NULL;
1471
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001472 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001473
1474 if ((lpath != NULL) && (rpath != NULL)) {
1475 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1476 }
1477
1478 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001479 }
1480
1481 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001482 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001483 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001484 const char* rpath = NULL, *lpath = ".";
1485
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001486 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001487
1488 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001489 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001490 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001491
1492 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001493 }
1494
1495 if(!strcmp(argv[0], "install")) {
1496 if (argc < 2) return usage();
1497 return install_app(ttype, serial, argc, argv);
1498 }
1499
1500 if(!strcmp(argv[0], "uninstall")) {
1501 if (argc < 2) return usage();
1502 return uninstall_app(ttype, serial, argc, argv);
1503 }
1504
1505 if(!strcmp(argv[0], "sync")) {
1506 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001507 int listonly = 0;
1508
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001509 int ret;
1510 if(argc < 2) {
1511 /* No local path was specified. */
1512 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001513 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1514 listonly = 1;
1515 if (argc == 3) {
1516 srcarg = argv[2];
1517 } else {
1518 srcarg = NULL;
1519 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001520 } else if(argc == 2) {
1521 /* A local path or "android"/"data" arg was specified. */
1522 srcarg = argv[1];
1523 } else {
1524 return usage();
1525 }
1526 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1527 if(ret != 0) return usage();
1528
1529 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001530 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001532 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001533
1534 free(android_srcpath);
1535 free(data_srcpath);
1536 return ret;
1537 }
1538
1539 /* passthrough commands */
1540
1541 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001542 !strcmp(argv[0],"get-serialno") ||
1543 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001544 {
1545 char *tmp;
1546
1547 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1548 tmp = adb_query(buf);
1549 if(tmp) {
1550 printf("%s\n", tmp);
1551 return 0;
1552 } else {
1553 return 1;
1554 }
1555 }
1556
1557 /* other commands */
1558
1559 if(!strcmp(argv[0],"status-window")) {
1560 status_window(ttype, serial);
1561 return 0;
1562 }
1563
Christopher Tatedb0a8802011-11-30 13:00:33 -08001564 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001565 return logcat(ttype, serial, argc, argv);
1566 }
1567
1568 if(!strcmp(argv[0],"ppp")) {
1569 return ppp(argc, argv);
1570 }
1571
1572 if (!strcmp(argv[0], "start-server")) {
1573 return adb_connect("host:start-server");
1574 }
1575
Christopher Tated2f54152011-04-21 12:53:28 -07001576 if (!strcmp(argv[0], "backup")) {
1577 return backup(argc, argv);
1578 }
1579
Christopher Tate702967a2011-05-17 15:52:54 -07001580 if (!strcmp(argv[0], "restore")) {
1581 return restore(argc, argv);
1582 }
1583
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001584 if (!strcmp(argv[0], "jdwp")) {
1585 int fd = adb_connect("jdwp");
1586 if (fd >= 0) {
1587 read_and_dump(fd);
1588 adb_close(fd);
1589 return 0;
1590 } else {
1591 fprintf(stderr, "error: %s\n", adb_error());
1592 return -1;
1593 }
1594 }
1595
1596 /* "adb /?" is a common idiom under Windows */
1597 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1598 help();
1599 return 0;
1600 }
1601
1602 if(!strcmp(argv[0], "version")) {
1603 version(stdout);
1604 return 0;
1605 }
1606
1607 usage();
1608 return 1;
1609}
1610
1611static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1612{
1613 char *argv[16];
1614 int argc;
1615 va_list ap;
1616
1617 va_start(ap, cmd);
1618 argc = 0;
1619
1620 if (serial) {
1621 argv[argc++] = "-s";
1622 argv[argc++] = serial;
1623 } else if (ttype == kTransportUsb) {
1624 argv[argc++] = "-d";
1625 } else if (ttype == kTransportLocal) {
1626 argv[argc++] = "-e";
1627 }
1628
1629 argv[argc++] = cmd;
1630 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1631 va_end(ap);
1632
1633#if 0
1634 int n;
1635 fprintf(stderr,"argc = %d\n",argc);
1636 for(n = 0; n < argc; n++) {
1637 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1638 }
1639#endif
1640
1641 return adb_commandline(argc, argv);
1642}
1643
1644int find_sync_dirs(const char *srcarg,
1645 char **android_srcdir_out, char **data_srcdir_out)
1646{
1647 char *android_srcdir, *data_srcdir;
1648
1649 if(srcarg == NULL) {
1650 android_srcdir = product_file("system");
1651 data_srcdir = product_file("data");
1652 } else {
1653 /* srcarg may be "data", "system" or NULL.
1654 * if srcarg is NULL, then both data and system are synced
1655 */
1656 if(strcmp(srcarg, "system") == 0) {
1657 android_srcdir = product_file("system");
1658 data_srcdir = NULL;
1659 } else if(strcmp(srcarg, "data") == 0) {
1660 android_srcdir = NULL;
1661 data_srcdir = product_file("data");
1662 } else {
1663 /* It's not "system" or "data".
1664 */
1665 return 1;
1666 }
1667 }
1668
1669 if(android_srcdir_out != NULL)
1670 *android_srcdir_out = android_srcdir;
1671 else
1672 free(android_srcdir);
1673
1674 if(data_srcdir_out != NULL)
1675 *data_srcdir_out = data_srcdir;
1676 else
1677 free(data_srcdir);
1678
1679 return 0;
1680}
1681
1682static int pm_command(transport_type transport, char* serial,
1683 int argc, char** argv)
1684{
1685 char buf[4096];
1686
1687 snprintf(buf, sizeof(buf), "shell:pm");
1688
1689 while(argc-- > 0) {
1690 char *quoted;
1691
1692 quoted = dupAndQuote(*argv++);
1693
1694 strncat(buf, " ", sizeof(buf)-1);
1695 strncat(buf, quoted, sizeof(buf)-1);
1696 free(quoted);
1697 }
1698
1699 send_shellcommand(transport, serial, buf);
1700 return 0;
1701}
1702
1703int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1704{
1705 /* if the user choose the -k option, we refuse to do it until devices are
1706 out with the option to uninstall the remaining data somehow (adb/ui) */
1707 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1708 {
1709 printf(
1710 "The -k option uninstalls the application while retaining the data/cache.\n"
1711 "At the moment, there is no way to remove the remaining data.\n"
1712 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1713 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1714 return -1;
1715 }
1716
1717 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1718 return pm_command(transport, serial, argc, argv);
1719}
1720
1721static int delete_file(transport_type transport, char* serial, char* filename)
1722{
1723 char buf[4096];
1724 char* quoted;
1725
1726 snprintf(buf, sizeof(buf), "shell:rm ");
1727 quoted = dupAndQuote(filename);
1728 strncat(buf, quoted, sizeof(buf)-1);
1729 free(quoted);
1730
1731 send_shellcommand(transport, serial, buf);
1732 return 0;
1733}
1734
Kenny Root597ea5b2011-08-05 11:19:45 -07001735static const char* get_basename(const char* filename)
1736{
1737 const char* basename = adb_dirstop(filename);
1738 if (basename) {
1739 basename++;
1740 return basename;
1741 } else {
1742 return filename;
1743 }
1744}
1745
1746static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001747{
1748 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001749
Kenny Root597ea5b2011-08-05 11:19:45 -07001750 if (filename == NULL) {
1751 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001752 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001753
Kenny Root597ea5b2011-08-05 11:19:45 -07001754 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001755 fprintf(stderr, "can't find '%s' to install\n", filename);
1756 return 1;
1757 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001758
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001759 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001760 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001761 return 1;
1762 }
1763
Kenny Root597ea5b2011-08-05 11:19:45 -07001764 return 0;
1765}
1766
1767int install_app(transport_type transport, char* serial, int argc, char** argv)
1768{
1769 static const char *const DATA_DEST = "/data/local/tmp/%s";
1770 static const char *const SD_DEST = "/sdcard/tmp/%s";
1771 const char* where = DATA_DEST;
1772 char apk_dest[PATH_MAX];
1773 char verification_dest[PATH_MAX];
1774 char* apk_file;
1775 char* verification_file = NULL;
1776 int file_arg = -1;
1777 int err;
1778 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001779 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001780
1781 for (i = 1; i < argc; i++) {
1782 if (*argv[i] != '-') {
1783 file_arg = i;
1784 break;
Kenny Roota031a912011-09-23 12:46:39 -07001785 } else if (!strcmp(argv[i], "-i")) {
1786 // Skip the installer package name.
1787 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001788 } else if (!strcmp(argv[i], "-s")) {
1789 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001790 } else if (!strcmp(argv[i], "--algo")) {
1791 verify_apk = 0;
1792 i++;
1793 } else if (!strcmp(argv[i], "--iv")) {
1794 verify_apk = 0;
1795 i++;
1796 } else if (!strcmp(argv[i], "--key")) {
1797 verify_apk = 0;
1798 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001799 } else if (!strcmp(argv[i], "--abi")) {
1800 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001801 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 }
1803
Kenny Root597ea5b2011-08-05 11:19:45 -07001804 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001805 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001806 return 1;
1807 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001808 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001809 return 1;
1810 }
1811
1812 apk_file = argv[file_arg];
1813
1814 if (file_arg != argc - 1) {
1815 verification_file = argv[file_arg + 1];
1816 }
1817
1818 if (check_file(apk_file) || check_file(verification_file)) {
1819 return 1;
1820 }
1821
1822 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1823 if (verification_file != NULL) {
1824 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1825
1826 if (!strcmp(apk_dest, verification_dest)) {
1827 fprintf(stderr, "APK and verification file can't have the same name\n");
1828 return 1;
1829 }
1830 }
1831
Mark Lindner76f2a932014-03-11 17:55:59 -07001832 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001833 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001834 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001835 } else {
1836 argv[file_arg] = apk_dest; /* destination name, not source location */
1837 }
1838
1839 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001840 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1841 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001842 if (err) {
1843 goto cleanup_apk;
1844 } else {
1845 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1846 }
1847 }
1848
1849 pm_command(transport, serial, argc, argv);
1850
Kenny Root60733e92012-03-26 16:14:02 -07001851cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001852 if (verification_file != NULL) {
1853 delete_file(transport, serial, verification_dest);
1854 }
1855
Kenny Root597ea5b2011-08-05 11:19:45 -07001856 delete_file(transport, serial, apk_dest);
1857
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001858 return err;
1859}