blob: 27e436dbcb6b5b2f8389292e427a72c895024ad2 [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
Doug Zongker71fe5842014-06-26 15:35:36 -0700504#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
505
506/*
507 * The sideload-host protocol serves the data in a file (given on the
508 * command line) to the client, using a simple protocol:
509 *
510 * - The connect message includes the total number of bytes in the
511 * file and a block size chosen by us.
512 *
513 * - The other side sends the desired block number as eight decimal
514 * digits (eg "00000023" for block 23). Blocks are numbered from
515 * zero.
516 *
517 * - We send back the data of the requested block. The last block is
518 * likely to be partial; when the last block is requested we only
519 * send the part of the block that exists, it's not padded up to the
520 * block size.
521 *
522 * - When the other side sends "DONEDONE" instead of a block number,
523 * we hang up.
524 */
525int adb_sideload_host(const char* fn) {
526 uint8_t* data;
527 unsigned sz;
528 size_t xfer = 0;
529 int status;
530
531 printf("loading: '%s'", fn);
532 fflush(stdout);
533 data = load_file(fn, &sz);
534 if (data == 0) {
535 printf("\n");
536 fprintf(stderr, "* cannot read '%s' *\n", fn);
537 return -1;
538 }
539
540 char buf[100];
541 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
542 int fd = adb_connect(buf);
543 if (fd < 0) {
544 // Try falling back to the older sideload method. Maybe this
545 // is an older device that doesn't support sideload-host.
546 printf("\n");
547 status = adb_download_buffer("sideload", fn, data, sz, 1);
548 goto done;
549 }
550
551 int opt = SIDELOAD_HOST_BLOCK_SIZE;
552 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
553
554 int last_percent = -1;
555 while (true) {
556 if (readx(fd, buf, 8)) {
557 fprintf(stderr, "* failed to read command: %s\n", adb_error());
558 status = -1;
559 goto done;
560 }
561
562 if (strncmp("DONEDONE", buf, 8) == 0) {
563 status = 0;
564 break;
565 }
566
567 buf[8] = '\0';
568 int block = strtol(buf, NULL, 10);
569
570 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
571 if (offset >= sz) {
572 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
573 status = -1;
574 goto done;
575 }
576 uint8_t* start = data + offset;
577 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
578 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
579 if (offset_end > sz) {
580 to_write = sz - offset;
581 }
582
583 if(writex(fd, start, to_write)) {
584 adb_status(fd);
585 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
586 status = -1;
587 goto done;
588 }
589 xfer += to_write;
590
591 // For normal OTA packages, we expect to transfer every byte
592 // twice, plus a bit of overhead (one read during
593 // verification, one read of each byte for installation, plus
594 // extra access to things like the zip central directory).
595 // This estimate of the completion becomes 100% when we've
596 // transferred ~2.13 (=100/47) times the package size.
597 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
598 if (percent != last_percent) {
599 printf("\rserving: '%s' (~%d%%) ", fn, percent);
600 fflush(stdout);
601 last_percent = percent;
602 }
603 }
604
605 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), strlen(fn)+10, "");
606
607 done:
608 if (fd >= 0) adb_close(fd);
609 free(data);
610 return status;
611}
612
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613static void status_window(transport_type ttype, const char* serial)
614{
615 char command[4096];
616 char *state = 0;
617 char *laststate = 0;
618
619 /* silence stderr */
620#ifdef _WIN32
621 /* XXX: TODO */
622#else
623 int fd;
624 fd = unix_open("/dev/null", O_WRONLY);
625 dup2(fd, 2);
626 adb_close(fd);
627#endif
628
629 format_host_command(command, sizeof command, "get-state", ttype, serial);
630
631 for(;;) {
632 adb_sleep_ms(250);
633
634 if(state) {
635 free(state);
636 state = 0;
637 }
638
639 state = adb_query(command);
640
641 if(state) {
642 if(laststate && !strcmp(state,laststate)){
643 continue;
644 } else {
645 if(laststate) free(laststate);
646 laststate = strdup(state);
647 }
648 }
649
650 printf("%c[2J%c[2H", 27, 27);
651 printf("Android Debug Bridge\n");
652 printf("State: %s\n", state ? state : "offline");
653 fflush(stdout);
654 }
655}
656
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700657/** Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700658static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800659{
660 const char *ts;
661 size_t alloc_len;
662 char *ret;
663 char *dest;
664
Jeff Sharkey7c460352014-06-10 16:22:17 -0700665 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700666 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800667 alloc_len++;
Jeff Sharkey7c460352014-06-10 16:22:17 -0700668 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800669 alloc_len++;
670 }
671 }
672
Jeff Sharkey7c460352014-06-10 16:22:17 -0700673 if (alloc_len == 0) {
674 // Preserve empty arguments
675 ret = (char *) malloc(3);
676 ret[0] = '\"';
677 ret[1] = '\"';
678 ret[2] = '\0';
679 return ret;
680 }
681
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700682 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800683 dest = ret;
684
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700685 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700686 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800687 *dest++ = '\\';
688 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800689 *dest++ = *ts;
690 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800691 *dest++ = '\0';
692
693 return ret;
694}
695
696/**
697 * Run ppp in "notty" mode against a resource listed as the first parameter
698 * eg:
699 *
700 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
701 *
702 */
703int ppp(int argc, char **argv)
704{
705#ifdef HAVE_WIN32_PROC
706 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
707 return -1;
708#else
709 char *adb_service_name;
710 pid_t pid;
711 int fd;
712
713 if (argc < 2) {
714 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
715 argv[0]);
716
717 return 1;
718 }
719
720 adb_service_name = argv[1];
721
722 fd = adb_connect(adb_service_name);
723
724 if(fd < 0) {
725 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
726 adb_service_name, adb_error());
727 return 1;
728 }
729
730 pid = fork();
731
732 if (pid < 0) {
733 perror("from fork()");
734 return 1;
735 } else if (pid == 0) {
736 int err;
737 int i;
738 const char **ppp_args;
739
740 // copy args
741 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
742 ppp_args[0] = "pppd";
743 for (i = 2 ; i < argc ; i++) {
744 //argv[2] and beyond become ppp_args[1] and beyond
745 ppp_args[i - 1] = argv[i];
746 }
747 ppp_args[i-1] = NULL;
748
749 // child side
750
751 dup2(fd, STDIN_FILENO);
752 dup2(fd, STDOUT_FILENO);
753 adb_close(STDERR_FILENO);
754 adb_close(fd);
755
756 err = execvp("pppd", (char * const *)ppp_args);
757
758 if (err < 0) {
759 perror("execing pppd");
760 }
761 exit(-1);
762 } else {
763 // parent side
764
765 adb_close(fd);
766 return 0;
767 }
768#endif /* !HAVE_WIN32_PROC */
769}
770
771static int send_shellcommand(transport_type transport, char* serial, char* buf)
772{
773 int fd, ret;
774
775 for(;;) {
776 fd = adb_connect(buf);
777 if(fd >= 0)
778 break;
779 fprintf(stderr,"- waiting for device -\n");
780 adb_sleep_ms(1000);
781 do_cmd(transport, serial, "wait-for-device", 0);
782 }
783
784 read_and_dump(fd);
785 ret = adb_close(fd);
786 if (ret)
787 perror("close");
788
789 return ret;
790}
791
792static int logcat(transport_type transport, char* serial, int argc, char **argv)
793{
794 char buf[4096];
795
796 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700797 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800798
799 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700800 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800801 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700802 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700803 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800804
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700805 if (!strcmp(argv[0], "longcat")) {
806 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800807 }
808
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800809 argc -= 1;
810 argv += 1;
811 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700812 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700813 strncat(buf, " ", sizeof(buf) - 1);
814 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800815 free(quoted);
816 }
817
818 send_shellcommand(transport, serial, buf);
819 return 0;
820}
821
Mark Salyzyn60299df2014-04-30 09:10:31 -0700822static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800823{
824 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700825 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800826
827 for(;;) {
828 x = adb_dirstart(x);
829 if(x == 0) return 0;
830 *x = 0;
831 ret = adb_mkdir(path, 0775);
832 *x = OS_PATH_SEPARATOR;
833 if((ret < 0) && (errno != EEXIST)) {
834 return ret;
835 }
836 x++;
837 }
838 return 0;
839}
840
Christopher Tated2f54152011-04-21 12:53:28 -0700841static int backup(int argc, char** argv) {
842 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800843 char default_name[32];
844 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700845 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700846 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700847
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700848 /* find, extract, and use any -f argument */
849 for (i = 1; i < argc; i++) {
850 if (!strcmp("-f", argv[i])) {
851 if (i == argc-1) {
852 fprintf(stderr, "adb: -f passed with no filename\n");
853 return usage();
854 }
855 filename = argv[i+1];
856 for (j = i+2; j <= argc; ) {
857 argv[i++] = argv[j++];
858 }
859 argc -= 2;
860 argv[argc] = NULL;
861 }
Christopher Tated2f54152011-04-21 12:53:28 -0700862 }
863
Christopher Tatebb86bc52011-08-22 17:12:08 -0700864 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
865 if (argc < 2) return usage();
866
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800867 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700868 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800869 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700870 if (outFd < 0) {
871 fprintf(stderr, "adb: unable to open file %s\n", filename);
872 return -1;
873 }
874
875 snprintf(buf, sizeof(buf), "backup");
876 for (argc--, argv++; argc; argc--, argv++) {
877 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
878 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
879 }
880
881 D("backup. filename=%s buf=%s\n", filename, buf);
882 fd = adb_connect(buf);
883 if (fd < 0) {
884 fprintf(stderr, "adb: unable to connect for backup\n");
885 adb_close(outFd);
886 return -1;
887 }
888
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800889 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700890 copy_to_file(fd, outFd);
891
892 adb_close(fd);
893 adb_close(outFd);
894 return 0;
895}
896
Christopher Tate702967a2011-05-17 15:52:54 -0700897static int restore(int argc, char** argv) {
898 const char* filename;
899 int fd, tarFd;
900
901 if (argc != 2) return usage();
902
903 filename = argv[1];
904 tarFd = adb_open(filename, O_RDONLY);
905 if (tarFd < 0) {
906 fprintf(stderr, "adb: unable to open file %s\n", filename);
907 return -1;
908 }
909
910 fd = adb_connect("restore:");
911 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700912 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700913 adb_close(tarFd);
914 return -1;
915 }
916
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800917 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700918 copy_to_file(tarFd, fd);
919
920 adb_close(fd);
921 adb_close(tarFd);
922 return 0;
923}
924
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800925#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
926static int top_works(const char *top)
927{
928 if (top != NULL && adb_is_absolute_host_path(top)) {
929 char path_buf[PATH_MAX];
930 snprintf(path_buf, sizeof(path_buf),
931 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
932 return access(path_buf, F_OK) == 0;
933 }
934 return 0;
935}
936
937static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
938{
939 strcpy(path_buf, indir);
940 while (1) {
941 if (top_works(path_buf)) {
942 return path_buf;
943 }
944 char *s = adb_dirstop(path_buf);
945 if (s != NULL) {
946 *s = '\0';
947 } else {
948 path_buf[0] = '\0';
949 return NULL;
950 }
951 }
952}
953
954static char *find_top(char path_buf[PATH_MAX])
955{
956 char *top = getenv("ANDROID_BUILD_TOP");
957 if (top != NULL && top[0] != '\0') {
958 if (!top_works(top)) {
959 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
960 return NULL;
961 }
962 } else {
963 top = getenv("TOP");
964 if (top != NULL && top[0] != '\0') {
965 if (!top_works(top)) {
966 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
967 return NULL;
968 }
969 } else {
970 top = NULL;
971 }
972 }
973
974 if (top != NULL) {
975 /* The environment pointed to a top directory that works.
976 */
977 strcpy(path_buf, top);
978 return path_buf;
979 }
980
981 /* The environment didn't help. Walk up the tree from the CWD
982 * to see if we can find the top.
983 */
984 char dir[PATH_MAX];
985 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
986 if (top == NULL) {
987 /* If the CWD isn't under a good-looking top, see if the
988 * executable is.
989 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100990 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800991 top = find_top_from(dir, path_buf);
992 }
993 return top;
994}
995
996/* <hint> may be:
997 * - A simple product name
998 * e.g., "sooner"
999TODO: debug? sooner-debug, sooner:debug?
1000 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1001 * e.g., "out/target/product/sooner"
1002 * - An absolute path to the PRODUCT_OUT dir
1003 * e.g., "/src/device/out/target/product/sooner"
1004 *
1005 * Given <hint>, try to construct an absolute path to the
1006 * ANDROID_PRODUCT_OUT dir.
1007 */
1008static const char *find_product_out_path(const char *hint)
1009{
1010 static char path_buf[PATH_MAX];
1011
1012 if (hint == NULL || hint[0] == '\0') {
1013 return NULL;
1014 }
1015
1016 /* If it's already absolute, don't bother doing any work.
1017 */
1018 if (adb_is_absolute_host_path(hint)) {
1019 strcpy(path_buf, hint);
1020 return path_buf;
1021 }
1022
1023 /* If there are any slashes in it, assume it's a relative path;
1024 * make it absolute.
1025 */
1026 if (adb_dirstart(hint) != NULL) {
1027 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1028 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1029 return NULL;
1030 }
1031 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1032 fprintf(stderr, "adb: Couldn't assemble path\n");
1033 return NULL;
1034 }
1035 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1036 strcat(path_buf, hint);
1037 return path_buf;
1038 }
1039
1040 /* It's a string without any slashes. Try to do something with it.
1041 *
1042 * Try to find the root of the build tree, and build a PRODUCT_OUT
1043 * path from there.
1044 */
1045 char top_buf[PATH_MAX];
1046 const char *top = find_top(top_buf);
1047 if (top == NULL) {
1048 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1049 return NULL;
1050 }
1051//TODO: if we have a way to indicate debug, look in out/debug/target/...
1052 snprintf(path_buf, sizeof(path_buf),
1053 "%s" OS_PATH_SEPARATOR_STR
1054 "out" OS_PATH_SEPARATOR_STR
1055 "target" OS_PATH_SEPARATOR_STR
1056 "product" OS_PATH_SEPARATOR_STR
1057 "%s", top_buf, hint);
1058 if (access(path_buf, F_OK) < 0) {
1059 fprintf(stderr, "adb: Couldn't find a product dir "
1060 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1061 return NULL;
1062 }
1063 return path_buf;
1064}
1065
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001066static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1067 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001068 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001069 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001070
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001071 while (narg > 0) {
1072 if (!strcmp(*arg, "-p")) {
1073 *show_progress = 1;
1074 } else if (!strcmp(*arg, "-a")) {
1075 *copy_attrs = 1;
1076 } else {
1077 break;
1078 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001079 ++arg;
1080 --narg;
1081 }
1082
1083 if (narg > 0) {
1084 *path1 = *arg;
1085 ++arg;
1086 --narg;
1087 }
1088
1089 if (narg > 0) {
1090 *path2 = *arg;
1091 }
1092}
1093
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001094int adb_commandline(int argc, char **argv)
1095{
1096 char buf[4096];
1097 int no_daemon = 0;
1098 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001099 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001100 int persist = 0;
1101 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001102 transport_type ttype = kTransportAny;
1103 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001104 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001105
1106 /* If defined, this should be an absolute path to
1107 * the directory containing all of the various system images
1108 * for a particular product. If not defined, and the adb
1109 * command requires this information, then the user must
1110 * specify the path using "-p".
1111 */
1112 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1113 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1114 gProductOutPath = NULL;
1115 }
1116 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1117
Nick Pellydb449262009-05-07 12:48:03 -07001118 serial = getenv("ANDROID_SERIAL");
1119
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001120 /* Validate and assign the server port */
1121 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1122 int server_port = DEFAULT_ADB_PORT;
1123 if (server_port_str && strlen(server_port_str) > 0) {
1124 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001125 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001126 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001127 "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 +01001128 server_port_str);
1129 return usage();
1130 }
1131 }
1132
1133 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001134 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001135 if(!strcmp(argv[0],"server")) {
1136 is_server = 1;
1137 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001138 no_daemon = 1;
1139 } else if (!strcmp(argv[0], "fork-server")) {
1140 /* this is a special flag used only when the ADB client launches the ADB Server */
1141 is_daemon = 1;
1142 } else if(!strcmp(argv[0],"persist")) {
1143 persist = 1;
1144 } else if(!strncmp(argv[0], "-p", 2)) {
1145 const char *product = NULL;
1146 if (argv[0][2] == '\0') {
1147 if (argc < 2) return usage();
1148 product = argv[1];
1149 argc--;
1150 argv++;
1151 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001152 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001153 }
1154 gProductOutPath = find_product_out_path(product);
1155 if (gProductOutPath == NULL) {
1156 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1157 product);
1158 return usage();
1159 }
1160 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1161 if (isdigit(argv[0][2])) {
1162 serial = argv[0] + 2;
1163 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001164 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001165 serial = argv[1];
1166 argc--;
1167 argv++;
1168 }
1169 } else if (!strcmp(argv[0],"-d")) {
1170 ttype = kTransportUsb;
1171 } else if (!strcmp(argv[0],"-e")) {
1172 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001173 } else if (!strcmp(argv[0],"-a")) {
1174 gListenAll = 1;
1175 } else if(!strncmp(argv[0], "-H", 2)) {
1176 const char *hostname = NULL;
1177 if (argv[0][2] == '\0') {
1178 if (argc < 2) return usage();
1179 hostname = argv[1];
1180 argc--;
1181 argv++;
1182 } else {
1183 hostname = argv[0] + 2;
1184 }
1185 adb_set_tcp_name(hostname);
1186
1187 } else if(!strncmp(argv[0], "-P", 2)) {
1188 if (argv[0][2] == '\0') {
1189 if (argc < 2) return usage();
1190 server_port_str = argv[1];
1191 argc--;
1192 argv++;
1193 } else {
1194 server_port_str = argv[0] + 2;
1195 }
1196 if (strlen(server_port_str) > 0) {
1197 server_port = (int) strtol(server_port_str, NULL, 0);
1198 if (server_port <= 0 || server_port > 65535) {
1199 fprintf(stderr,
1200 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1201 server_port_str);
1202 return usage();
1203 }
1204 } else {
1205 fprintf(stderr,
1206 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1207 return usage();
1208 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001209 } else {
1210 /* out of recognized modifiers and flags */
1211 break;
1212 }
1213 argc--;
1214 argv++;
1215 }
1216
1217 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001218 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001219
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001220 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001221 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001222 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001223 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001224 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001225 }
1226 if(r) {
1227 fprintf(stderr,"* could not start server *\n");
1228 }
1229 return r;
1230 }
1231
1232top:
1233 if(argc == 0) {
1234 return usage();
1235 }
1236
1237 /* adb_connect() commands */
1238
1239 if(!strcmp(argv[0], "devices")) {
1240 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001241 char *listopt;
1242 if (argc < 2)
1243 listopt = "";
1244 else if (argc == 2 && !strcmp(argv[1], "-l"))
1245 listopt = argv[1];
1246 else {
1247 fprintf(stderr, "Usage: adb devices [-l]\n");
1248 return 1;
1249 }
1250 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001251 tmp = adb_query(buf);
1252 if(tmp) {
1253 printf("List of devices attached \n");
1254 printf("%s\n", tmp);
1255 return 0;
1256 } else {
1257 return 1;
1258 }
1259 }
1260
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001261 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001262 char *tmp;
1263 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001264 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001265 return 1;
1266 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001267 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1268 tmp = adb_query(buf);
1269 if(tmp) {
1270 printf("%s\n", tmp);
1271 return 0;
1272 } else {
1273 return 1;
1274 }
1275 }
1276
1277 if(!strcmp(argv[0], "disconnect")) {
1278 char *tmp;
1279 if (argc > 2) {
1280 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1281 return 1;
1282 }
1283 if (argc == 2) {
1284 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1285 } else {
1286 snprintf(buf, sizeof buf, "host:disconnect:");
1287 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001288 tmp = adb_query(buf);
1289 if(tmp) {
1290 printf("%s\n", tmp);
1291 return 0;
1292 } else {
1293 return 1;
1294 }
1295 }
1296
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001297 if (!strcmp(argv[0], "emu")) {
1298 return adb_send_emulator_command(argc, argv);
1299 }
1300
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001301 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001302 int r;
1303 int fd;
1304
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001305 char h = (argv[0][0] == 'h');
1306
1307 if (h) {
1308 printf("\x1b[41;33m");
1309 fflush(stdout);
1310 }
1311
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001312 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001313 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001314 r = interactive_shell();
1315 if (h) {
1316 printf("\x1b[0m");
1317 fflush(stdout);
1318 }
1319 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 }
1321
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001322 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001323 argc -= 2;
1324 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001325 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001326 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001327 strncat(buf, " ", sizeof(buf) - 1);
1328 strncat(buf, quoted, sizeof(buf) - 1);
1329 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 }
1331
1332 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001333 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001334 fd = adb_connect(buf);
1335 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001336 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001337 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001338 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001339 adb_close(fd);
1340 r = 0;
1341 } else {
1342 fprintf(stderr,"error: %s\n", adb_error());
1343 r = -1;
1344 }
1345
1346 if(persist) {
1347 fprintf(stderr,"\n- waiting for device -\n");
1348 adb_sleep_ms(1000);
1349 do_cmd(ttype, serial, "wait-for-device", 0);
1350 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001351 if (h) {
1352 printf("\x1b[0m");
1353 fflush(stdout);
1354 }
JP Abgrall408fa572011-03-16 15:57:42 -07001355 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001356 return r;
1357 }
1358 }
1359 }
1360
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001361 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1362 int exec_in = !strcmp(argv[0], "exec-in");
1363 int fd;
1364
1365 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1366 argc -= 2;
1367 argv += 2;
1368 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001369 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001370 strncat(buf, " ", sizeof(buf) - 1);
1371 strncat(buf, quoted, sizeof(buf) - 1);
1372 free(quoted);
1373 }
1374
1375 fd = adb_connect(buf);
1376 if (fd < 0) {
1377 fprintf(stderr, "error: %s\n", adb_error());
1378 return -1;
1379 }
1380
1381 if (exec_in) {
1382 copy_to_file(STDIN_FILENO, fd);
1383 } else {
1384 copy_to_file(fd, STDOUT_FILENO);
1385 }
1386
1387 adb_close(fd);
1388 return 0;
1389 }
1390
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001391 if(!strcmp(argv[0], "kill-server")) {
1392 int fd;
1393 fd = _adb_connect("host:kill");
1394 if(fd == -1) {
1395 fprintf(stderr,"* server not running *\n");
1396 return 1;
1397 }
1398 return 0;
1399 }
1400
Doug Zongker447f0612012-01-09 14:54:53 -08001401 if(!strcmp(argv[0], "sideload")) {
1402 if(argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001403 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001404 return 1;
1405 } else {
1406 return 0;
1407 }
1408 }
1409
Mike Lockwoodff196702009-08-24 15:58:40 -07001410 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001411 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001412 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001413 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001414 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001415 if (!strcmp(argv[0], "reboot-bootloader"))
1416 snprintf(command, sizeof(command), "reboot:bootloader");
1417 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001418 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001419 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001420 snprintf(command, sizeof(command), "%s:", argv[0]);
1421 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001422 if(fd >= 0) {
1423 read_and_dump(fd);
1424 adb_close(fd);
1425 return 0;
1426 }
1427 fprintf(stderr,"error: %s\n", adb_error());
1428 return 1;
1429 }
1430
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001431 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001432 if (argc != 1) return usage();
1433 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001434 return 0;
1435 }
1436
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001437 /* adb_command() wrapper commands */
1438
1439 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1440 char* service = argv[0];
1441 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1442 if (ttype == kTransportUsb) {
1443 service = "wait-for-usb";
1444 } else if (ttype == kTransportLocal) {
1445 service = "wait-for-local";
1446 } else {
1447 service = "wait-for-any";
1448 }
1449 }
1450
1451 format_host_command(buf, sizeof buf, service, ttype, serial);
1452
1453 if (adb_command(buf)) {
1454 D("failure: %s *\n",adb_error());
1455 fprintf(stderr,"error: %s\n", adb_error());
1456 return 1;
1457 }
1458
1459 /* Allow a command to be run after wait-for-device,
1460 * e.g. 'adb wait-for-device shell'.
1461 */
1462 if(argc > 1) {
1463 argc--;
1464 argv++;
1465 goto top;
1466 }
1467 return 0;
1468 }
1469
David 'Digit' Turner25258692013-03-21 21:07:42 +01001470 if(!strcmp(argv[0], "forward") ||
1471 !strcmp(argv[0], "reverse"))
1472 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001473 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001474 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001475 char remove = 0;
1476 char remove_all = 0;
1477 char list = 0;
1478 char no_rebind = 0;
1479
1480 // Parse options here.
1481 while (argc > 1 && argv[1][0] == '-') {
1482 if (!strcmp(argv[1], "--list"))
1483 list = 1;
1484 else if (!strcmp(argv[1], "--remove"))
1485 remove = 1;
1486 else if (!strcmp(argv[1], "--remove-all"))
1487 remove_all = 1;
1488 else if (!strcmp(argv[1], "--no-rebind"))
1489 no_rebind = 1;
1490 else {
1491 return usage();
1492 }
1493 argc--;
1494 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001495 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001496
1497 // Ensure we can only use one option at a time.
1498 if (list + remove + remove_all + no_rebind > 1) {
1499 return usage();
1500 }
1501
1502 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001503 if (reverse) {
1504 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001505 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001506 if (serial) {
1507 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1508 serial);
1509 } else if (ttype == kTransportUsb) {
1510 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1511 } else if (ttype == kTransportLocal) {
1512 snprintf(host_prefix, sizeof host_prefix, "host-local");
1513 } else {
1514 snprintf(host_prefix, sizeof host_prefix, "host");
1515 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001516 }
1517
1518 // Implement forward --list
1519 if (list) {
1520 if (argc != 1)
1521 return usage();
1522 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1523 char* forwards = adb_query(buf);
1524 if (forwards == NULL) {
1525 fprintf(stderr, "error: %s\n", adb_error());
1526 return 1;
1527 }
1528 printf("%s", forwards);
1529 free(forwards);
1530 return 0;
1531 }
1532
1533 // Implement forward --remove-all
1534 else if (remove_all) {
1535 if (argc != 1)
1536 return usage();
1537 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1538 }
1539
1540 // Implement forward --remove <local>
1541 else if (remove) {
1542 if (argc != 2)
1543 return usage();
1544 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1545 }
1546 // Or implement one of:
1547 // forward <local> <remote>
1548 // forward --no-rebind <local> <remote>
1549 else
1550 {
1551 if (argc != 3)
1552 return usage();
1553 const char* command = no_rebind ? "forward:norebind:" : "forward";
1554 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1555 }
1556
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001557 if(adb_command(buf)) {
1558 fprintf(stderr,"error: %s\n", adb_error());
1559 return 1;
1560 }
1561 return 0;
1562 }
1563
1564 /* do_sync_*() commands */
1565
1566 if(!strcmp(argv[0], "ls")) {
1567 if(argc != 2) return usage();
1568 return do_sync_ls(argv[1]);
1569 }
1570
1571 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001572 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001573 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001574 const char* lpath = NULL, *rpath = NULL;
1575
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001576 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001577
1578 if ((lpath != NULL) && (rpath != NULL)) {
1579 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1580 }
1581
1582 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001583 }
1584
1585 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001586 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001587 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001588 const char* rpath = NULL, *lpath = ".";
1589
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001590 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001591
1592 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001593 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001594 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001595
1596 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001597 }
1598
1599 if(!strcmp(argv[0], "install")) {
1600 if (argc < 2) return usage();
1601 return install_app(ttype, serial, argc, argv);
1602 }
1603
1604 if(!strcmp(argv[0], "uninstall")) {
1605 if (argc < 2) return usage();
1606 return uninstall_app(ttype, serial, argc, argv);
1607 }
1608
1609 if(!strcmp(argv[0], "sync")) {
1610 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001611 int listonly = 0;
1612
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001613 int ret;
1614 if(argc < 2) {
1615 /* No local path was specified. */
1616 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001617 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1618 listonly = 1;
1619 if (argc == 3) {
1620 srcarg = argv[2];
1621 } else {
1622 srcarg = NULL;
1623 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624 } else if(argc == 2) {
1625 /* A local path or "android"/"data" arg was specified. */
1626 srcarg = argv[1];
1627 } else {
1628 return usage();
1629 }
1630 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1631 if(ret != 0) return usage();
1632
1633 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001634 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001635 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001636 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637
1638 free(android_srcpath);
1639 free(data_srcpath);
1640 return ret;
1641 }
1642
1643 /* passthrough commands */
1644
1645 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001646 !strcmp(argv[0],"get-serialno") ||
1647 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001648 {
1649 char *tmp;
1650
1651 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1652 tmp = adb_query(buf);
1653 if(tmp) {
1654 printf("%s\n", tmp);
1655 return 0;
1656 } else {
1657 return 1;
1658 }
1659 }
1660
1661 /* other commands */
1662
1663 if(!strcmp(argv[0],"status-window")) {
1664 status_window(ttype, serial);
1665 return 0;
1666 }
1667
Christopher Tatedb0a8802011-11-30 13:00:33 -08001668 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001669 return logcat(ttype, serial, argc, argv);
1670 }
1671
1672 if(!strcmp(argv[0],"ppp")) {
1673 return ppp(argc, argv);
1674 }
1675
1676 if (!strcmp(argv[0], "start-server")) {
1677 return adb_connect("host:start-server");
1678 }
1679
Christopher Tated2f54152011-04-21 12:53:28 -07001680 if (!strcmp(argv[0], "backup")) {
1681 return backup(argc, argv);
1682 }
1683
Christopher Tate702967a2011-05-17 15:52:54 -07001684 if (!strcmp(argv[0], "restore")) {
1685 return restore(argc, argv);
1686 }
1687
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 if (!strcmp(argv[0], "jdwp")) {
1689 int fd = adb_connect("jdwp");
1690 if (fd >= 0) {
1691 read_and_dump(fd);
1692 adb_close(fd);
1693 return 0;
1694 } else {
1695 fprintf(stderr, "error: %s\n", adb_error());
1696 return -1;
1697 }
1698 }
1699
1700 /* "adb /?" is a common idiom under Windows */
1701 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1702 help();
1703 return 0;
1704 }
1705
1706 if(!strcmp(argv[0], "version")) {
1707 version(stdout);
1708 return 0;
1709 }
1710
1711 usage();
1712 return 1;
1713}
1714
1715static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1716{
1717 char *argv[16];
1718 int argc;
1719 va_list ap;
1720
1721 va_start(ap, cmd);
1722 argc = 0;
1723
1724 if (serial) {
1725 argv[argc++] = "-s";
1726 argv[argc++] = serial;
1727 } else if (ttype == kTransportUsb) {
1728 argv[argc++] = "-d";
1729 } else if (ttype == kTransportLocal) {
1730 argv[argc++] = "-e";
1731 }
1732
1733 argv[argc++] = cmd;
1734 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1735 va_end(ap);
1736
1737#if 0
1738 int n;
1739 fprintf(stderr,"argc = %d\n",argc);
1740 for(n = 0; n < argc; n++) {
1741 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1742 }
1743#endif
1744
1745 return adb_commandline(argc, argv);
1746}
1747
1748int find_sync_dirs(const char *srcarg,
1749 char **android_srcdir_out, char **data_srcdir_out)
1750{
1751 char *android_srcdir, *data_srcdir;
1752
1753 if(srcarg == NULL) {
1754 android_srcdir = product_file("system");
1755 data_srcdir = product_file("data");
1756 } else {
1757 /* srcarg may be "data", "system" or NULL.
1758 * if srcarg is NULL, then both data and system are synced
1759 */
1760 if(strcmp(srcarg, "system") == 0) {
1761 android_srcdir = product_file("system");
1762 data_srcdir = NULL;
1763 } else if(strcmp(srcarg, "data") == 0) {
1764 android_srcdir = NULL;
1765 data_srcdir = product_file("data");
1766 } else {
1767 /* It's not "system" or "data".
1768 */
1769 return 1;
1770 }
1771 }
1772
1773 if(android_srcdir_out != NULL)
1774 *android_srcdir_out = android_srcdir;
1775 else
1776 free(android_srcdir);
1777
1778 if(data_srcdir_out != NULL)
1779 *data_srcdir_out = data_srcdir;
1780 else
1781 free(data_srcdir);
1782
1783 return 0;
1784}
1785
1786static int pm_command(transport_type transport, char* serial,
1787 int argc, char** argv)
1788{
1789 char buf[4096];
1790
1791 snprintf(buf, sizeof(buf), "shell:pm");
1792
1793 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001794 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001795 strncat(buf, " ", sizeof(buf) - 1);
1796 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001797 free(quoted);
1798 }
1799
1800 send_shellcommand(transport, serial, buf);
1801 return 0;
1802}
1803
1804int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1805{
1806 /* if the user choose the -k option, we refuse to do it until devices are
1807 out with the option to uninstall the remaining data somehow (adb/ui) */
1808 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1809 {
1810 printf(
1811 "The -k option uninstalls the application while retaining the data/cache.\n"
1812 "At the moment, there is no way to remove the remaining data.\n"
1813 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1814 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1815 return -1;
1816 }
1817
1818 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1819 return pm_command(transport, serial, argc, argv);
1820}
1821
1822static int delete_file(transport_type transport, char* serial, char* filename)
1823{
1824 char buf[4096];
1825 char* quoted;
1826
1827 snprintf(buf, sizeof(buf), "shell:rm ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001828 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001829 strncat(buf, quoted, sizeof(buf)-1);
1830 free(quoted);
1831
1832 send_shellcommand(transport, serial, buf);
1833 return 0;
1834}
1835
Kenny Root597ea5b2011-08-05 11:19:45 -07001836static const char* get_basename(const char* filename)
1837{
1838 const char* basename = adb_dirstop(filename);
1839 if (basename) {
1840 basename++;
1841 return basename;
1842 } else {
1843 return filename;
1844 }
1845}
1846
1847static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001848{
1849 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001850
Kenny Root597ea5b2011-08-05 11:19:45 -07001851 if (filename == NULL) {
1852 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001853 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001854
Kenny Root597ea5b2011-08-05 11:19:45 -07001855 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001856 fprintf(stderr, "can't find '%s' to install\n", filename);
1857 return 1;
1858 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001859
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001860 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001861 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001862 return 1;
1863 }
1864
Kenny Root597ea5b2011-08-05 11:19:45 -07001865 return 0;
1866}
1867
1868int install_app(transport_type transport, char* serial, int argc, char** argv)
1869{
1870 static const char *const DATA_DEST = "/data/local/tmp/%s";
1871 static const char *const SD_DEST = "/sdcard/tmp/%s";
1872 const char* where = DATA_DEST;
1873 char apk_dest[PATH_MAX];
1874 char verification_dest[PATH_MAX];
1875 char* apk_file;
1876 char* verification_file = NULL;
1877 int file_arg = -1;
1878 int err;
1879 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001880 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001881
1882 for (i = 1; i < argc; i++) {
1883 if (*argv[i] != '-') {
1884 file_arg = i;
1885 break;
Kenny Roota031a912011-09-23 12:46:39 -07001886 } else if (!strcmp(argv[i], "-i")) {
1887 // Skip the installer package name.
1888 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001889 } else if (!strcmp(argv[i], "-s")) {
1890 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001891 } else if (!strcmp(argv[i], "--algo")) {
1892 verify_apk = 0;
1893 i++;
1894 } else if (!strcmp(argv[i], "--iv")) {
1895 verify_apk = 0;
1896 i++;
1897 } else if (!strcmp(argv[i], "--key")) {
1898 verify_apk = 0;
1899 i++;
Narayan Kamatha284f8b2014-05-29 15:52:02 +01001900 } else if (!strcmp(argv[i], "--abi")) {
1901 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001902 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001903 }
1904
Kenny Root597ea5b2011-08-05 11:19:45 -07001905 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001906 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001907 return 1;
1908 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001909 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001910 return 1;
1911 }
1912
1913 apk_file = argv[file_arg];
1914
1915 if (file_arg != argc - 1) {
1916 verification_file = argv[file_arg + 1];
1917 }
1918
1919 if (check_file(apk_file) || check_file(verification_file)) {
1920 return 1;
1921 }
1922
1923 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1924 if (verification_file != NULL) {
1925 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1926
1927 if (!strcmp(apk_dest, verification_dest)) {
1928 fprintf(stderr, "APK and verification file can't have the same name\n");
1929 return 1;
1930 }
1931 }
1932
Mark Lindner76f2a932014-03-11 17:55:59 -07001933 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001934 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001935 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 } else {
1937 argv[file_arg] = apk_dest; /* destination name, not source location */
1938 }
1939
1940 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001941 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1942 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001943 if (err) {
1944 goto cleanup_apk;
1945 } else {
1946 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1947 }
1948 }
1949
1950 pm_command(transport, serial, argc, argv);
1951
Kenny Root60733e92012-03-26 16:14:02 -07001952cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001953 if (verification_file != NULL) {
1954 delete_file(transport, serial, verification_dest);
1955 }
1956
Kenny Root597ea5b2011-08-05 11:19:45 -07001957 delete_file(transport, serial, apk_dest);
1958
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001959 return err;
1960}