blob: a8ad7bd9f73d8915f2fc63dc8346b9657db1e5cc [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
Dan Albert76649012015-02-24 15:51:19 -080017#include <assert.h>
18#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080020#include <limits.h>
21#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080022#include <stdint.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
Yabin Cuid325e862014-11-17 14:48:25 -080029#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080031#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032#endif
33
Dan Albert76649012015-02-24 15:51:19 -080034#include "sysdeps.h"
35
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036#define TRACE_TAG TRACE_ADB
37#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080038#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080039#include "adb_client.h"
40#include "adb_io.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#include "file_sync_service.h"
42
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
44
Alexey Tarasov31664102009-10-22 02:55:00 +110045void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -070047 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey960df972014-06-09 17:30:57 -070049int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
51
52static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080053extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054
55static char *product_file(const char *extra)
56{
57 int n;
58 char *x;
59
60 if (gProductOutPath == NULL) {
61 fprintf(stderr, "adb: Product directory not specified; "
62 "use -p or define ANDROID_PRODUCT_OUT\n");
63 exit(1);
64 }
65
66 n = strlen(gProductOutPath) + strlen(extra) + 2;
67 x = malloc(n);
68 if (x == 0) {
69 fprintf(stderr, "adb: Out of memory (product_file())\n");
70 exit(1);
71 }
72
73 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
74 return x;
75}
76
77void version(FILE * out) {
78 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
79 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
80}
81
82void help()
83{
84 version(stderr);
85
86 fprintf(stderr,
87 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080088 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080089 " -d - directs command to the only connected USB device\n"
90 " returns an error if more than one USB device is present.\n"
91 " -e - directs command to the only running emulator.\n"
92 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070093 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070094 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070095 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096 " -p <product name or path> - simple product name like 'sooner', or\n"
97 " a relative/absolute path to a product\n"
98 " out directory like 'out/target/product/sooner'.\n"
99 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
100 " environment variable is used, which must\n"
101 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800102 " -H - Name of adb server host (default: localhost)\n"
103 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700104 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700105 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400106 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
107 " Port 5555 is used by default if no port number is specified.\n"
108 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
109 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200110 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400111 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800112 "\n"
113 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700114 " adb push [-p] <local> <remote>\n"
115 " - copy file/dir to device\n"
116 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700117 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700118 " - copy file/dir from device\n"
119 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700120 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600122 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800123 " (see 'adb help all')\n"
124 " adb shell - run remote shell interactively\n"
125 " adb shell <command> - run remote shell command\n"
126 " adb emu <command> - run emulator console command\n"
127 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100128 " adb forward --list - list all forward socket connections.\n"
129 " the format is a list of lines with the following format:\n"
130 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800131 " adb forward <local> <remote> - forward socket connections\n"
132 " forward specs are one of: \n"
133 " tcp:<port>\n"
134 " localabstract:<unix domain socket name>\n"
135 " localreserved:<unix domain socket name>\n"
136 " localfilesystem:<unix domain socket name>\n"
137 " dev:<character device name>\n"
138 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100139 " adb forward --no-rebind <local> <remote>\n"
140 " - same as 'adb forward <local> <remote>' but fails\n"
141 " if <local> is already forwarded\n"
142 " adb forward --remove <local> - remove a specific forward socket connection\n"
143 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100144 " adb reverse --list - list all reverse socket connections from device\n"
145 " adb reverse <remote> <local> - reverse socket connections\n"
146 " reverse specs are one of:\n"
147 " tcp:<port>\n"
148 " localabstract:<unix domain socket name>\n"
149 " localreserved:<unix domain socket name>\n"
150 " localfilesystem:<unix domain socket name>\n"
151 " adb reverse --norebind <remote> <local>\n"
152 " - same as 'adb reverse <remote> <local>' but fails\n"
153 " if <remote> is already reversed.\n"
154 " adb reverse --remove <remote>\n"
155 " - remove a specific reversed socket connection\n"
156 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700158 " adb install [-lrtsd] <file>\n"
159 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700160 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700161 " (-l: forward lock application)\n"
162 " (-r: replace existing application)\n"
163 " (-t: allow test packages)\n"
164 " (-s: install application on sdcard)\n"
165 " (-d: allow version code downgrade)\n"
166 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 " adb uninstall [-k] <package> - remove this app package from the device\n"
168 " ('-k' means keep the data and cache directories)\n"
169 " adb bugreport - return all information from the device\n"
170 " that should be included in a bug report.\n"
171 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800172 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700173 " - write an archive of the device's data to <file>.\n"
174 " If no -f option is supplied then the data is written\n"
175 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700177 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800178 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
179 " (aka .obb) files associated with each application; the default\n"
180 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (-shared|-noshared enable/disable backup of the device's\n"
182 " shared storage / SD card contents; the default is noshared.)\n"
183 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700184 " (-system|-nosystem toggles whether -all automatically includes\n"
185 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 " (<packages...> is the list of applications to be backed up. If\n"
187 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700188 " list is optional. Applications explicitly given on the\n"
189 " command line will be included even if -nosystem would\n"
190 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700191 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700192 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700193 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800194 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
195 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800196 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
197 " and the public key is stored in <file>.pub. Any existing files\n"
198 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800199 " adb help - show this help message\n"
200 " adb version - show version num\n"
201 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800202 "scripting:\n"
203 " adb wait-for-device - block until device is online\n"
204 " adb start-server - ensure that there is a server running\n"
205 " adb kill-server - kill the server if it is running\n"
206 " adb get-state - prints: offline | bootloader | device\n"
207 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700208 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700210 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400211 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800212 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700213 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500214 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800215 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000216 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800217 "networking:\n"
218 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500219 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800220 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
221 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
222 "\n"
223 "adb sync notes: adb sync [ <directory> ]\n"
224 " <localdir> can be interpreted in several ways:\n"
225 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700226 " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700228 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000230 "\n"
231 "environmental variables:\n"
232 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
233 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
234 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
235 " 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 -0800236 );
237}
238
239int usage()
240{
241 help();
242 return 1;
243}
244
Yabin Cuid325e862014-11-17 14:48:25 -0800245#if defined(_WIN32)
246
247// Windows does not have <termio.h>.
248static void stdin_raw_init(int fd) {
249
250}
251
252static void stdin_raw_restore(int fd) {
253
254}
255
256#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257static struct termios tio_save;
258
259static void stdin_raw_init(int fd)
260{
261 struct termios tio;
262
263 if(tcgetattr(fd, &tio)) return;
264 if(tcgetattr(fd, &tio_save)) return;
265
266 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
267
268 /* no timeout but request at least one character per read */
269 tio.c_cc[VTIME] = 0;
270 tio.c_cc[VMIN] = 1;
271
272 tcsetattr(fd, TCSANOW, &tio);
273 tcflush(fd, TCIFLUSH);
274}
275
276static void stdin_raw_restore(int fd)
277{
278 tcsetattr(fd, TCSANOW, &tio_save);
279 tcflush(fd, TCIFLUSH);
280}
281#endif
282
283static void read_and_dump(int fd)
284{
285 char buf[4096];
286 int len;
287
288 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700291 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 if(len == 0) {
293 break;
294 }
295
296 if(len < 0) {
297 if(errno == EINTR) continue;
298 break;
299 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400300 fwrite(buf, 1, len, stdout);
301 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800302 }
303}
304
Jeff Sharkey960df972014-06-09 17:30:57 -0700305static void read_status_line(int fd, char* buf, size_t count)
306{
307 count--;
308 while (count > 0) {
309 int len = adb_read(fd, buf, count);
310 if (len == 0) {
311 break;
312 } else if (len < 0) {
313 if (errno == EINTR) continue;
314 break;
315 }
316
317 buf += len;
318 count -= len;
319 }
320 *buf = '\0';
321}
322
Christopher Tated2f54152011-04-21 12:53:28 -0700323static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700324 const size_t BUFSIZE = 32 * 1024;
325 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700326 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700327 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700328
329 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800330
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700331 if (inFd == STDIN_FILENO) {
332 stdin_raw_init(STDIN_FILENO);
333 }
Yabin Cuid325e862014-11-17 14:48:25 -0800334
Christopher Tated2f54152011-04-21 12:53:28 -0700335 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700336 if (inFd == STDIN_FILENO) {
337 len = unix_read(inFd, buf, BUFSIZE);
338 } else {
339 len = adb_read(inFd, buf, BUFSIZE);
340 }
Christopher Tated2f54152011-04-21 12:53:28 -0700341 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700342 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700343 break;
344 }
345 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700346 if (errno == EINTR) {
347 D("copy_to_file() : EINTR, retrying\n");
348 continue;
349 }
Christopher Tated2f54152011-04-21 12:53:28 -0700350 D("copy_to_file() : error %d\n", errno);
351 break;
352 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700353 if (outFd == STDOUT_FILENO) {
354 fwrite(buf, 1, len, stdout);
355 fflush(stdout);
356 } else {
357 adb_write(outFd, buf, len);
358 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700359 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700360 }
Yabin Cuid325e862014-11-17 14:48:25 -0800361
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700362 if (inFd == STDIN_FILENO) {
363 stdin_raw_restore(STDIN_FILENO);
364 }
Yabin Cuid325e862014-11-17 14:48:25 -0800365
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700366 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700367 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700368}
369
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370static void *stdin_read_thread(void *x)
371{
372 int fd, fdi;
373 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 int r, n;
375 int state = 0;
376
377 int *fds = (int*) x;
378 fd = fds[0];
379 fdi = fds[1];
380 free(fds);
381
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800382 for(;;) {
383 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700384 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700386 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800387 if(r == 0) break;
388 if(r < 0) {
389 if(errno == EINTR) continue;
390 break;
391 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400392 for(n = 0; n < r; n++){
393 switch(buf[n]) {
394 case '\n':
395 state = 1;
396 break;
397 case '\r':
398 state = 1;
399 break;
400 case '~':
401 if(state == 1) state++;
402 break;
403 case '.':
404 if(state == 2) {
405 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400406 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400409 default:
410 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 r = adb_write(fd, buf, r);
414 if(r <= 0) {
415 break;
416 }
417 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800418 return 0;
419}
420
421int interactive_shell(void)
422{
423 adb_thread_t thr;
424 int fdi, fd;
425 int *fds;
426
427 fd = adb_connect("shell:");
428 if(fd < 0) {
429 fprintf(stderr,"error: %s\n", adb_error());
430 return 1;
431 }
432 fdi = 0; //dup(0);
433
434 fds = malloc(sizeof(int) * 2);
435 fds[0] = fd;
436 fds[1] = fdi;
437
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 adb_thread_create(&thr, stdin_read_thread, fds);
440 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800442 return 0;
443}
444
445
446static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
447{
448 if (serial) {
449 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
450 } else {
451 const char* prefix = "host";
452 if (ttype == kTransportUsb)
453 prefix = "host-usb";
454 else if (ttype == kTransportLocal)
455 prefix = "host-local";
456
457 snprintf(buffer, buflen, "%s:%s", prefix, command);
458 }
459}
460
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100461int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800462 unsigned progress)
463{
464 char buf[4096];
465 unsigned total;
466 int fd;
467 const unsigned char *ptr;
468
469 sprintf(buf,"%s:%d", service, sz);
470 fd = adb_connect(buf);
471 if(fd < 0) {
472 fprintf(stderr,"error: %s\n", adb_error());
473 return -1;
474 }
475
476 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800477 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800478
479 total = sz;
480 ptr = data;
481
482 if(progress) {
483 char *x = strrchr(service, ':');
484 if(x) service = x + 1;
485 }
486
487 while(sz > 0) {
488 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800489 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800490 adb_status(fd);
491 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
492 return -1;
493 }
494 sz -= xfer;
495 ptr += xfer;
496 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100497 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800498 fflush(stdout);
499 }
500 }
501 if(progress) {
502 printf("\n");
503 }
504
Dan Albertcc731cc2015-02-24 21:26:58 -0800505 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800506 fprintf(stderr,"* error reading response *\n");
507 adb_close(fd);
508 return -1;
509 }
510 if(memcmp(buf, "OKAY", 4)) {
511 buf[4] = 0;
512 fprintf(stderr,"* error response '%s' *\n", buf);
513 adb_close(fd);
514 return -1;
515 }
516
517 adb_close(fd);
518 return 0;
519}
520
521
522int adb_download(const char *service, const char *fn, unsigned progress)
523{
524 void *data;
525 unsigned sz;
526
527 data = load_file(fn, &sz);
528 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100529 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800530 return -1;
531 }
532
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100533 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800534 free(data);
535 return status;
536}
537
Doug Zongker71fe5842014-06-26 15:35:36 -0700538#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
539
540/*
541 * The sideload-host protocol serves the data in a file (given on the
542 * command line) to the client, using a simple protocol:
543 *
544 * - The connect message includes the total number of bytes in the
545 * file and a block size chosen by us.
546 *
547 * - The other side sends the desired block number as eight decimal
548 * digits (eg "00000023" for block 23). Blocks are numbered from
549 * zero.
550 *
551 * - We send back the data of the requested block. The last block is
552 * likely to be partial; when the last block is requested we only
553 * send the part of the block that exists, it's not padded up to the
554 * block size.
555 *
556 * - When the other side sends "DONEDONE" instead of a block number,
557 * we hang up.
558 */
559int adb_sideload_host(const char* fn) {
560 uint8_t* data;
561 unsigned sz;
562 size_t xfer = 0;
563 int status;
564
565 printf("loading: '%s'", fn);
566 fflush(stdout);
567 data = load_file(fn, &sz);
568 if (data == 0) {
569 printf("\n");
570 fprintf(stderr, "* cannot read '%s' *\n", fn);
571 return -1;
572 }
573
574 char buf[100];
575 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
576 int fd = adb_connect(buf);
577 if (fd < 0) {
578 // Try falling back to the older sideload method. Maybe this
579 // is an older device that doesn't support sideload-host.
580 printf("\n");
581 status = adb_download_buffer("sideload", fn, data, sz, 1);
582 goto done;
583 }
584
585 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800586 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700587
588 int last_percent = -1;
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700589 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800590 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700591 fprintf(stderr, "* failed to read command: %s\n", adb_error());
592 status = -1;
593 goto done;
594 }
595
596 if (strncmp("DONEDONE", buf, 8) == 0) {
597 status = 0;
598 break;
599 }
600
601 buf[8] = '\0';
602 int block = strtol(buf, NULL, 10);
603
604 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
605 if (offset >= sz) {
606 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
607 status = -1;
608 goto done;
609 }
610 uint8_t* start = data + offset;
611 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
612 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
613 if (offset_end > sz) {
614 to_write = sz - offset;
615 }
616
Dan Albertcc731cc2015-02-24 21:26:58 -0800617 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700618 adb_status(fd);
619 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
620 status = -1;
621 goto done;
622 }
623 xfer += to_write;
624
625 // For normal OTA packages, we expect to transfer every byte
626 // twice, plus a bit of overhead (one read during
627 // verification, one read of each byte for installation, plus
628 // extra access to things like the zip central directory).
629 // This estimate of the completion becomes 100% when we've
630 // transferred ~2.13 (=100/47) times the package size.
631 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
632 if (percent != last_percent) {
633 printf("\rserving: '%s' (~%d%%) ", fn, percent);
634 fflush(stdout);
635 last_percent = percent;
636 }
637 }
638
Colin Cross6d6a8982014-07-07 14:12:41 -0700639 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700640
641 done:
642 if (fd >= 0) adb_close(fd);
643 free(data);
644 return status;
645}
646
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800647static void status_window(transport_type ttype, const char* serial)
648{
649 char command[4096];
650 char *state = 0;
651 char *laststate = 0;
652
653 /* silence stderr */
654#ifdef _WIN32
655 /* XXX: TODO */
656#else
657 int fd;
658 fd = unix_open("/dev/null", O_WRONLY);
659 dup2(fd, 2);
660 adb_close(fd);
661#endif
662
663 format_host_command(command, sizeof command, "get-state", ttype, serial);
664
665 for(;;) {
666 adb_sleep_ms(250);
667
668 if(state) {
669 free(state);
670 state = 0;
671 }
672
673 state = adb_query(command);
674
675 if(state) {
676 if(laststate && !strcmp(state,laststate)){
677 continue;
678 } else {
679 if(laststate) free(laststate);
680 laststate = strdup(state);
681 }
682 }
683
684 printf("%c[2J%c[2H", 27, 27);
685 printf("Android Debug Bridge\n");
686 printf("State: %s\n", state ? state : "offline");
687 fflush(stdout);
688 }
689}
690
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700691static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700692{
693 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
694}
695
696/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700697static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800698{
699 const char *ts;
700 size_t alloc_len;
701 char *ret;
702 char *dest;
703
Jeff Sharkey7c460352014-06-10 16:22:17 -0700704 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700705 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700707 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800708 alloc_len++;
709 }
710 }
711
Jeff Sharkey7c460352014-06-10 16:22:17 -0700712 if (alloc_len == 0) {
713 // Preserve empty arguments
714 ret = (char *) malloc(3);
715 ret[0] = '\"';
716 ret[1] = '\"';
717 ret[2] = '\0';
718 return ret;
719 }
720
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700721 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800722 dest = ret;
723
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700724 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700725 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800726 *dest++ = '\\';
727 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800728 *dest++ = *ts;
729 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800730 *dest++ = '\0';
731
732 return ret;
733}
734
735/**
736 * Run ppp in "notty" mode against a resource listed as the first parameter
737 * eg:
738 *
739 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
740 *
741 */
742int ppp(int argc, char **argv)
743{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800744#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800745 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
746 return -1;
747#else
748 char *adb_service_name;
749 pid_t pid;
750 int fd;
751
752 if (argc < 2) {
753 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
754 argv[0]);
755
756 return 1;
757 }
758
759 adb_service_name = argv[1];
760
761 fd = adb_connect(adb_service_name);
762
763 if(fd < 0) {
764 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
765 adb_service_name, adb_error());
766 return 1;
767 }
768
769 pid = fork();
770
771 if (pid < 0) {
772 perror("from fork()");
773 return 1;
774 } else if (pid == 0) {
775 int err;
776 int i;
777 const char **ppp_args;
778
779 // copy args
780 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
781 ppp_args[0] = "pppd";
782 for (i = 2 ; i < argc ; i++) {
783 //argv[2] and beyond become ppp_args[1] and beyond
784 ppp_args[i - 1] = argv[i];
785 }
786 ppp_args[i-1] = NULL;
787
788 // child side
789
790 dup2(fd, STDIN_FILENO);
791 dup2(fd, STDOUT_FILENO);
792 adb_close(STDERR_FILENO);
793 adb_close(fd);
794
795 err = execvp("pppd", (char * const *)ppp_args);
796
797 if (err < 0) {
798 perror("execing pppd");
799 }
800 exit(-1);
801 } else {
802 // parent side
803
804 adb_close(fd);
805 return 0;
806 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800807#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800808}
809
810static int send_shellcommand(transport_type transport, char* serial, char* buf)
811{
812 int fd, ret;
813
814 for(;;) {
815 fd = adb_connect(buf);
816 if(fd >= 0)
817 break;
818 fprintf(stderr,"- waiting for device -\n");
819 adb_sleep_ms(1000);
820 do_cmd(transport, serial, "wait-for-device", 0);
821 }
822
823 read_and_dump(fd);
824 ret = adb_close(fd);
825 if (ret)
826 perror("close");
827
828 return ret;
829}
830
831static int logcat(transport_type transport, char* serial, int argc, char **argv)
832{
833 char buf[4096];
834
835 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700836 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800837
838 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700839 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800840 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700841 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700842 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800843
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700844 if (!strcmp(argv[0], "longcat")) {
845 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800846 }
847
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800848 argc -= 1;
849 argv += 1;
850 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700851 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700852 strncat(buf, " ", sizeof(buf) - 1);
853 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800854 free(quoted);
855 }
856
857 send_shellcommand(transport, serial, buf);
858 return 0;
859}
860
Mark Salyzyn60299df2014-04-30 09:10:31 -0700861static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800862{
863 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700864 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800865
866 for(;;) {
867 x = adb_dirstart(x);
868 if(x == 0) return 0;
869 *x = 0;
870 ret = adb_mkdir(path, 0775);
871 *x = OS_PATH_SEPARATOR;
872 if((ret < 0) && (errno != EEXIST)) {
873 return ret;
874 }
875 x++;
876 }
877 return 0;
878}
879
Christopher Tated2f54152011-04-21 12:53:28 -0700880static int backup(int argc, char** argv) {
881 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800882 char default_name[32];
883 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700884 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700885 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700886
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700887 /* find, extract, and use any -f argument */
888 for (i = 1; i < argc; i++) {
889 if (!strcmp("-f", argv[i])) {
890 if (i == argc-1) {
891 fprintf(stderr, "adb: -f passed with no filename\n");
892 return usage();
893 }
894 filename = argv[i+1];
895 for (j = i+2; j <= argc; ) {
896 argv[i++] = argv[j++];
897 }
898 argc -= 2;
899 argv[argc] = NULL;
900 }
Christopher Tated2f54152011-04-21 12:53:28 -0700901 }
902
Christopher Tatebb86bc52011-08-22 17:12:08 -0700903 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
904 if (argc < 2) return usage();
905
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800906 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700907 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800908 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700909 if (outFd < 0) {
910 fprintf(stderr, "adb: unable to open file %s\n", filename);
911 return -1;
912 }
913
914 snprintf(buf, sizeof(buf), "backup");
915 for (argc--, argv++; argc; argc--, argv++) {
916 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
917 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
918 }
919
920 D("backup. filename=%s buf=%s\n", filename, buf);
921 fd = adb_connect(buf);
922 if (fd < 0) {
923 fprintf(stderr, "adb: unable to connect for backup\n");
924 adb_close(outFd);
925 return -1;
926 }
927
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800928 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700929 copy_to_file(fd, outFd);
930
931 adb_close(fd);
932 adb_close(outFd);
933 return 0;
934}
935
Christopher Tate702967a2011-05-17 15:52:54 -0700936static int restore(int argc, char** argv) {
937 const char* filename;
938 int fd, tarFd;
939
940 if (argc != 2) return usage();
941
942 filename = argv[1];
943 tarFd = adb_open(filename, O_RDONLY);
944 if (tarFd < 0) {
945 fprintf(stderr, "adb: unable to open file %s\n", filename);
946 return -1;
947 }
948
949 fd = adb_connect("restore:");
950 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700951 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700952 adb_close(tarFd);
953 return -1;
954 }
955
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800956 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700957 copy_to_file(tarFd, fd);
958
959 adb_close(fd);
960 adb_close(tarFd);
961 return 0;
962}
963
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
965static int top_works(const char *top)
966{
967 if (top != NULL && adb_is_absolute_host_path(top)) {
968 char path_buf[PATH_MAX];
969 snprintf(path_buf, sizeof(path_buf),
970 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
971 return access(path_buf, F_OK) == 0;
972 }
973 return 0;
974}
975
976static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
977{
978 strcpy(path_buf, indir);
979 while (1) {
980 if (top_works(path_buf)) {
981 return path_buf;
982 }
983 char *s = adb_dirstop(path_buf);
984 if (s != NULL) {
985 *s = '\0';
986 } else {
987 path_buf[0] = '\0';
988 return NULL;
989 }
990 }
991}
992
993static char *find_top(char path_buf[PATH_MAX])
994{
995 char *top = getenv("ANDROID_BUILD_TOP");
996 if (top != NULL && top[0] != '\0') {
997 if (!top_works(top)) {
998 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
999 return NULL;
1000 }
1001 } else {
1002 top = getenv("TOP");
1003 if (top != NULL && top[0] != '\0') {
1004 if (!top_works(top)) {
1005 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1006 return NULL;
1007 }
1008 } else {
1009 top = NULL;
1010 }
1011 }
1012
1013 if (top != NULL) {
1014 /* The environment pointed to a top directory that works.
1015 */
1016 strcpy(path_buf, top);
1017 return path_buf;
1018 }
1019
1020 /* The environment didn't help. Walk up the tree from the CWD
1021 * to see if we can find the top.
1022 */
1023 char dir[PATH_MAX];
1024 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1025 if (top == NULL) {
1026 /* If the CWD isn't under a good-looking top, see if the
1027 * executable is.
1028 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001029 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001030 top = find_top_from(dir, path_buf);
1031 }
1032 return top;
1033}
1034
1035/* <hint> may be:
1036 * - A simple product name
1037 * e.g., "sooner"
1038TODO: debug? sooner-debug, sooner:debug?
1039 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1040 * e.g., "out/target/product/sooner"
1041 * - An absolute path to the PRODUCT_OUT dir
1042 * e.g., "/src/device/out/target/product/sooner"
1043 *
1044 * Given <hint>, try to construct an absolute path to the
1045 * ANDROID_PRODUCT_OUT dir.
1046 */
1047static const char *find_product_out_path(const char *hint)
1048{
1049 static char path_buf[PATH_MAX];
1050
1051 if (hint == NULL || hint[0] == '\0') {
1052 return NULL;
1053 }
1054
1055 /* If it's already absolute, don't bother doing any work.
1056 */
1057 if (adb_is_absolute_host_path(hint)) {
1058 strcpy(path_buf, hint);
1059 return path_buf;
1060 }
1061
1062 /* If there are any slashes in it, assume it's a relative path;
1063 * make it absolute.
1064 */
1065 if (adb_dirstart(hint) != NULL) {
1066 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1067 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1068 return NULL;
1069 }
1070 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1071 fprintf(stderr, "adb: Couldn't assemble path\n");
1072 return NULL;
1073 }
1074 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1075 strcat(path_buf, hint);
1076 return path_buf;
1077 }
1078
1079 /* It's a string without any slashes. Try to do something with it.
1080 *
1081 * Try to find the root of the build tree, and build a PRODUCT_OUT
1082 * path from there.
1083 */
1084 char top_buf[PATH_MAX];
1085 const char *top = find_top(top_buf);
1086 if (top == NULL) {
1087 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1088 return NULL;
1089 }
1090//TODO: if we have a way to indicate debug, look in out/debug/target/...
1091 snprintf(path_buf, sizeof(path_buf),
1092 "%s" OS_PATH_SEPARATOR_STR
1093 "out" OS_PATH_SEPARATOR_STR
1094 "target" OS_PATH_SEPARATOR_STR
1095 "product" OS_PATH_SEPARATOR_STR
1096 "%s", top_buf, hint);
1097 if (access(path_buf, F_OK) < 0) {
1098 fprintf(stderr, "adb: Couldn't find a product dir "
1099 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1100 return NULL;
1101 }
1102 return path_buf;
1103}
1104
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001105static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1106 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001107 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001108 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001109
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001110 while (narg > 0) {
1111 if (!strcmp(*arg, "-p")) {
1112 *show_progress = 1;
1113 } else if (!strcmp(*arg, "-a")) {
1114 *copy_attrs = 1;
1115 } else {
1116 break;
1117 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001118 ++arg;
1119 --narg;
1120 }
1121
1122 if (narg > 0) {
1123 *path1 = *arg;
1124 ++arg;
1125 --narg;
1126 }
1127
1128 if (narg > 0) {
1129 *path2 = *arg;
1130 }
1131}
1132
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133int adb_commandline(int argc, char **argv)
1134{
1135 char buf[4096];
1136 int no_daemon = 0;
1137 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001138 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139 int persist = 0;
1140 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141 transport_type ttype = kTransportAny;
1142 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001143 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001144
1145 /* If defined, this should be an absolute path to
1146 * the directory containing all of the various system images
1147 * for a particular product. If not defined, and the adb
1148 * command requires this information, then the user must
1149 * specify the path using "-p".
1150 */
1151 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1152 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1153 gProductOutPath = NULL;
1154 }
1155 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1156
Nick Pellydb449262009-05-07 12:48:03 -07001157 serial = getenv("ANDROID_SERIAL");
1158
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001159 /* Validate and assign the server port */
1160 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1161 int server_port = DEFAULT_ADB_PORT;
1162 if (server_port_str && strlen(server_port_str) > 0) {
1163 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001164 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001165 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001166 "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 +01001167 server_port_str);
1168 return usage();
1169 }
1170 }
1171
1172 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001173 while (argc > 0) {
1174 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001175 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001176 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001177 no_daemon = 1;
1178 } else if (!strcmp(argv[0], "fork-server")) {
1179 /* this is a special flag used only when the ADB client launches the ADB Server */
1180 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001181 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001182 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001183 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001184 const char *product = NULL;
1185 if (argv[0][2] == '\0') {
1186 if (argc < 2) return usage();
1187 product = argv[1];
1188 argc--;
1189 argv++;
1190 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001191 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 }
1193 gProductOutPath = find_product_out_path(product);
1194 if (gProductOutPath == NULL) {
1195 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1196 product);
1197 return usage();
1198 }
1199 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1200 if (isdigit(argv[0][2])) {
1201 serial = argv[0] + 2;
1202 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001203 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001204 serial = argv[1];
1205 argc--;
1206 argv++;
1207 }
1208 } else if (!strcmp(argv[0],"-d")) {
1209 ttype = kTransportUsb;
1210 } else if (!strcmp(argv[0],"-e")) {
1211 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001212 } else if (!strcmp(argv[0],"-a")) {
1213 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001214 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001215 const char *hostname = NULL;
1216 if (argv[0][2] == '\0') {
1217 if (argc < 2) return usage();
1218 hostname = argv[1];
1219 argc--;
1220 argv++;
1221 } else {
1222 hostname = argv[0] + 2;
1223 }
1224 adb_set_tcp_name(hostname);
1225
Riley Andrews98f58e82014-12-05 17:37:24 -08001226 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001227 if (argv[0][2] == '\0') {
1228 if (argc < 2) return usage();
1229 server_port_str = argv[1];
1230 argc--;
1231 argv++;
1232 } else {
1233 server_port_str = argv[0] + 2;
1234 }
1235 if (strlen(server_port_str) > 0) {
1236 server_port = (int) strtol(server_port_str, NULL, 0);
1237 if (server_port <= 0 || server_port > 65535) {
1238 fprintf(stderr,
1239 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1240 server_port_str);
1241 return usage();
1242 }
1243 } else {
1244 fprintf(stderr,
1245 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1246 return usage();
1247 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001248 } else {
1249 /* out of recognized modifiers and flags */
1250 break;
1251 }
1252 argc--;
1253 argv++;
1254 }
1255
1256 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001257 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001259 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001260 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001261 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001262 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001263 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001264 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001265 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001266 fprintf(stderr,"* could not start server *\n");
1267 }
1268 return r;
1269 }
1270
Riley Andrews98f58e82014-12-05 17:37:24 -08001271 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001272 return usage();
1273 }
1274
Riley Andrewsc8514c82014-12-05 17:32:46 -08001275 /* handle wait-for-* prefix */
1276 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1277 char* service = argv[0];
1278 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1279 if (ttype == kTransportUsb) {
1280 service = "wait-for-usb";
1281 } else if (ttype == kTransportLocal) {
1282 service = "wait-for-local";
1283 } else {
1284 service = "wait-for-any";
1285 }
1286 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001287
Riley Andrewsc8514c82014-12-05 17:32:46 -08001288 format_host_command(buf, sizeof buf, service, ttype, serial);
1289
1290 if (adb_command(buf)) {
1291 D("failure: %s *\n",adb_error());
1292 fprintf(stderr,"error: %s\n", adb_error());
1293 return 1;
1294 }
1295
1296 /* Allow a command to be run after wait-for-device,
1297 * e.g. 'adb wait-for-device shell'.
1298 */
1299 if (argc == 1) {
1300 return 0;
1301 }
1302
1303 /* Fall through */
1304 argc--;
1305 argv++;
1306 }
1307
1308 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001309 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001310 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001311 char *listopt;
1312 if (argc < 2)
1313 listopt = "";
1314 else if (argc == 2 && !strcmp(argv[1], "-l"))
1315 listopt = argv[1];
1316 else {
1317 fprintf(stderr, "Usage: adb devices [-l]\n");
1318 return 1;
1319 }
1320 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001321 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001322 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001323 printf("List of devices attached \n");
1324 printf("%s\n", tmp);
1325 return 0;
1326 } else {
1327 return 1;
1328 }
1329 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001330 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001331 char *tmp;
1332 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001333 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001334 return 1;
1335 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001336 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1337 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001338 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001339 printf("%s\n", tmp);
1340 return 0;
1341 } else {
1342 return 1;
1343 }
1344 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001345 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001346 char *tmp;
1347 if (argc > 2) {
1348 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1349 return 1;
1350 }
1351 if (argc == 2) {
1352 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1353 } else {
1354 snprintf(buf, sizeof buf, "host:disconnect:");
1355 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001356 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001357 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001358 printf("%s\n", tmp);
1359 return 0;
1360 } else {
1361 return 1;
1362 }
1363 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001364 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001365 return adb_send_emulator_command(argc, argv);
1366 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001367 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001368 int r;
1369 int fd;
1370
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001371 char h = (argv[0][0] == 'h');
1372
1373 if (h) {
1374 printf("\x1b[41;33m");
1375 fflush(stdout);
1376 }
1377
Riley Andrews98f58e82014-12-05 17:37:24 -08001378 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001379 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001380 r = interactive_shell();
1381 if (h) {
1382 printf("\x1b[0m");
1383 fflush(stdout);
1384 }
1385 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001386 }
1387
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001388 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001389 argc -= 2;
1390 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001391 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001392 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001393 strncat(buf, " ", sizeof(buf) - 1);
1394 strncat(buf, quoted, sizeof(buf) - 1);
1395 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 }
1397
1398 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001399 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001400 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001401 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001402 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001404 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001405 adb_close(fd);
1406 r = 0;
1407 } else {
1408 fprintf(stderr,"error: %s\n", adb_error());
1409 r = -1;
1410 }
1411
Riley Andrews98f58e82014-12-05 17:37:24 -08001412 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001413 fprintf(stderr,"\n- waiting for device -\n");
1414 adb_sleep_ms(1000);
1415 do_cmd(ttype, serial, "wait-for-device", 0);
1416 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001417 if (h) {
1418 printf("\x1b[0m");
1419 fflush(stdout);
1420 }
JP Abgrall408fa572011-03-16 15:57:42 -07001421 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001422 return r;
1423 }
1424 }
1425 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001426 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001427 int exec_in = !strcmp(argv[0], "exec-in");
1428 int fd;
1429
1430 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1431 argc -= 2;
1432 argv += 2;
1433 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001434 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001435 strncat(buf, " ", sizeof(buf) - 1);
1436 strncat(buf, quoted, sizeof(buf) - 1);
1437 free(quoted);
1438 }
1439
1440 fd = adb_connect(buf);
1441 if (fd < 0) {
1442 fprintf(stderr, "error: %s\n", adb_error());
1443 return -1;
1444 }
1445
1446 if (exec_in) {
1447 copy_to_file(STDIN_FILENO, fd);
1448 } else {
1449 copy_to_file(fd, STDOUT_FILENO);
1450 }
1451
1452 adb_close(fd);
1453 return 0;
1454 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001455 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001456 int fd;
1457 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001458 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001459 fprintf(stderr,"* server not running *\n");
1460 return 1;
1461 }
1462 return 0;
1463 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001464 else if (!strcmp(argv[0], "sideload")) {
1465 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001466 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001467 return 1;
1468 } else {
1469 return 0;
1470 }
1471 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001472 else if (!strcmp(argv[0], "remount") ||
1473 !strcmp(argv[0], "reboot") ||
1474 !strcmp(argv[0], "reboot-bootloader") ||
1475 !strcmp(argv[0], "tcpip") ||
1476 !strcmp(argv[0], "usb") ||
1477 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001478 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001479 !strcmp(argv[0], "disable-verity") ||
1480 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001481 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001482 if (!strcmp(argv[0], "reboot-bootloader"))
1483 snprintf(command, sizeof(command), "reboot:bootloader");
1484 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001485 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001486 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001487 snprintf(command, sizeof(command), "%s:", argv[0]);
1488 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001489 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001490 read_and_dump(fd);
1491 adb_close(fd);
1492 return 0;
1493 }
1494 fprintf(stderr,"error: %s\n", adb_error());
1495 return 1;
1496 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001497 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001498 if (argc != 1) return usage();
1499 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001500 return 0;
1501 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001502 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001503 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001504 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001505 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001506 char remove = 0;
1507 char remove_all = 0;
1508 char list = 0;
1509 char no_rebind = 0;
1510
1511 // Parse options here.
1512 while (argc > 1 && argv[1][0] == '-') {
1513 if (!strcmp(argv[1], "--list"))
1514 list = 1;
1515 else if (!strcmp(argv[1], "--remove"))
1516 remove = 1;
1517 else if (!strcmp(argv[1], "--remove-all"))
1518 remove_all = 1;
1519 else if (!strcmp(argv[1], "--no-rebind"))
1520 no_rebind = 1;
1521 else {
1522 return usage();
1523 }
1524 argc--;
1525 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001526 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001527
1528 // Ensure we can only use one option at a time.
1529 if (list + remove + remove_all + no_rebind > 1) {
1530 return usage();
1531 }
1532
1533 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001534 if (reverse) {
1535 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001536 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001537 if (serial) {
1538 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1539 serial);
1540 } else if (ttype == kTransportUsb) {
1541 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1542 } else if (ttype == kTransportLocal) {
1543 snprintf(host_prefix, sizeof host_prefix, "host-local");
1544 } else {
1545 snprintf(host_prefix, sizeof host_prefix, "host");
1546 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001547 }
1548
1549 // Implement forward --list
1550 if (list) {
1551 if (argc != 1)
1552 return usage();
1553 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1554 char* forwards = adb_query(buf);
1555 if (forwards == NULL) {
1556 fprintf(stderr, "error: %s\n", adb_error());
1557 return 1;
1558 }
1559 printf("%s", forwards);
1560 free(forwards);
1561 return 0;
1562 }
1563
1564 // Implement forward --remove-all
1565 else if (remove_all) {
1566 if (argc != 1)
1567 return usage();
1568 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1569 }
1570
1571 // Implement forward --remove <local>
1572 else if (remove) {
1573 if (argc != 2)
1574 return usage();
1575 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1576 }
1577 // Or implement one of:
1578 // forward <local> <remote>
1579 // forward --no-rebind <local> <remote>
1580 else
1581 {
1582 if (argc != 3)
1583 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001584 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001585 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1586 }
1587
Riley Andrews98f58e82014-12-05 17:37:24 -08001588 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001589 fprintf(stderr,"error: %s\n", adb_error());
1590 return 1;
1591 }
1592 return 0;
1593 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001594 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001595 else if (!strcmp(argv[0], "ls")) {
1596 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001597 return do_sync_ls(argv[1]);
1598 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001599 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001600 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001601 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001602 const char* lpath = NULL, *rpath = NULL;
1603
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001604 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001605
1606 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001607 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001608 }
1609
1610 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001611 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001612 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001613 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001614 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001615 const char* rpath = NULL, *lpath = ".";
1616
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001617 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001618
1619 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001620 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001621 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001622
1623 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001625 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001626 if (argc < 2) return usage();
1627 return install_app(ttype, serial, argc, argv);
1628 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001629 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001630 if (argc < 2) return usage();
1631 return install_multiple_app(ttype, serial, argc, argv);
1632 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001633 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001634 if (argc < 2) return usage();
1635 return uninstall_app(ttype, serial, argc, argv);
1636 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001637 else if (!strcmp(argv[0], "sync")) {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001638 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001639 int listonly = 0;
1640
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001641 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001642 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001643 /* No local path was specified. */
1644 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001645 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1646 listonly = 1;
1647 if (argc == 3) {
1648 srcarg = argv[2];
1649 } else {
1650 srcarg = NULL;
1651 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001652 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001653 /* A local path or "android"/"data" arg was specified. */
1654 srcarg = argv[1];
1655 } else {
1656 return usage();
1657 }
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001658 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001659 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001660
Riley Andrews98f58e82014-12-05 17:37:24 -08001661 if (android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001662 ret = do_sync_sync(android_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001663 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001664 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001665 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001666 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001667
1668 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001669 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001670 free(data_srcpath);
1671 return ret;
1672 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001673 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001674 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001675 !strcmp(argv[0],"get-serialno") ||
1676 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001677 {
1678 char *tmp;
1679
1680 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1681 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001682 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001683 printf("%s\n", tmp);
1684 return 0;
1685 } else {
1686 return 1;
1687 }
1688 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001689 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001690 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001691 status_window(ttype, serial);
1692 return 0;
1693 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001694 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001695 return logcat(ttype, serial, argc, argv);
1696 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001697 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001698 return ppp(argc, argv);
1699 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001700 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001701 return adb_connect("host:start-server");
1702 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001703 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001704 return backup(argc, argv);
1705 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001706 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001707 return restore(argc, argv);
1708 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001709 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001710 if (argc < 2) return usage();
1711 return adb_auth_keygen(argv[1]);
1712 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001713 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001714 int fd = adb_connect("jdwp");
1715 if (fd >= 0) {
1716 read_and_dump(fd);
1717 adb_close(fd);
1718 return 0;
1719 } else {
1720 fprintf(stderr, "error: %s\n", adb_error());
1721 return -1;
1722 }
1723 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001724 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001725 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001726 help();
1727 return 0;
1728 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001729 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001730 version(stdout);
1731 return 0;
1732 }
1733
1734 usage();
1735 return 1;
1736}
1737
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001738#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001739static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1740{
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001741 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001742 int argc;
1743 va_list ap;
1744
1745 va_start(ap, cmd);
1746 argc = 0;
1747
1748 if (serial) {
1749 argv[argc++] = "-s";
1750 argv[argc++] = serial;
1751 } else if (ttype == kTransportUsb) {
1752 argv[argc++] = "-d";
1753 } else if (ttype == kTransportLocal) {
1754 argv[argc++] = "-e";
1755 }
1756
1757 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001758 while(argc < MAX_ARGV_LENGTH &&
1759 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1760 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001761 va_end(ap);
1762
1763#if 0
1764 int n;
1765 fprintf(stderr,"argc = %d\n",argc);
1766 for(n = 0; n < argc; n++) {
1767 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1768 }
1769#endif
1770
1771 return adb_commandline(argc, argv);
1772}
1773
1774int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001775 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001776{
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001777 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1778 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001779
1780 if(srcarg == NULL) {
1781 android_srcdir = product_file("system");
1782 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001783 vendor_srcdir = product_file("vendor");
1784 /* Check if vendor partition exists */
1785 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1786 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001787 } else {
1788 /* srcarg may be "data", "system" or NULL.
1789 * if srcarg is NULL, then both data and system are synced
1790 */
1791 if(strcmp(srcarg, "system") == 0) {
1792 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001793 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001794 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001795 } else if(strcmp(srcarg, "vendor") == 0) {
1796 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001797 } else {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001798 /* It's not "system", "vendor", or "data".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001799 */
1800 return 1;
1801 }
1802 }
1803
1804 if(android_srcdir_out != NULL)
1805 *android_srcdir_out = android_srcdir;
1806 else
1807 free(android_srcdir);
1808
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001809 if(vendor_srcdir_out != NULL)
1810 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001811 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001812 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001813
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001814 if(data_srcdir_out != NULL)
1815 *data_srcdir_out = data_srcdir;
1816 else
1817 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001818 return 0;
1819}
1820
1821static int pm_command(transport_type transport, char* serial,
1822 int argc, char** argv)
1823{
1824 char buf[4096];
1825
1826 snprintf(buf, sizeof(buf), "shell:pm");
1827
1828 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001829 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001830 strncat(buf, " ", sizeof(buf) - 1);
1831 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001832 free(quoted);
1833 }
1834
1835 send_shellcommand(transport, serial, buf);
1836 return 0;
1837}
1838
1839int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1840{
1841 /* if the user choose the -k option, we refuse to do it until devices are
1842 out with the option to uninstall the remaining data somehow (adb/ui) */
1843 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1844 {
1845 printf(
1846 "The -k option uninstalls the application while retaining the data/cache.\n"
1847 "At the moment, there is no way to remove the remaining data.\n"
1848 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1849 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1850 return -1;
1851 }
1852
1853 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1854 return pm_command(transport, serial, argc, argv);
1855}
1856
1857static int delete_file(transport_type transport, char* serial, char* filename)
1858{
1859 char buf[4096];
1860 char* quoted;
1861
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001862 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001863 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001864 strncat(buf, quoted, sizeof(buf)-1);
1865 free(quoted);
1866
1867 send_shellcommand(transport, serial, buf);
1868 return 0;
1869}
1870
Kenny Root597ea5b2011-08-05 11:19:45 -07001871static const char* get_basename(const char* filename)
1872{
1873 const char* basename = adb_dirstop(filename);
1874 if (basename) {
1875 basename++;
1876 return basename;
1877 } else {
1878 return filename;
1879 }
1880}
1881
Kenny Root597ea5b2011-08-05 11:19:45 -07001882int install_app(transport_type transport, char* serial, int argc, char** argv)
1883{
1884 static const char *const DATA_DEST = "/data/local/tmp/%s";
1885 static const char *const SD_DEST = "/sdcard/tmp/%s";
1886 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001887 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001888 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001889
1890 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001891 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001892 where = SD_DEST;
1893 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001894 }
1895
Jeff Sharkey960df972014-06-09 17:30:57 -07001896 // Find last APK argument.
1897 // All other arguments passed through verbatim.
1898 int last_apk = -1;
1899 for (i = argc - 1; i >= 0; i--) {
1900 char* file = argv[i];
1901 char* dot = strrchr(file, '.');
1902 if (dot && !strcasecmp(dot, ".apk")) {
1903 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1904 fprintf(stderr, "Invalid APK file: %s\n", file);
1905 return -1;
1906 }
1907
1908 last_apk = i;
1909 break;
1910 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001911 }
1912
Jeff Sharkey960df972014-06-09 17:30:57 -07001913 if (last_apk == -1) {
1914 fprintf(stderr, "Missing APK file\n");
1915 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001916 }
1917
Jeff Sharkey960df972014-06-09 17:30:57 -07001918 char* apk_file = argv[last_apk];
1919 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001920 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001921 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001922 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001923 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001924 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001925 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001926 }
1927
1928 pm_command(transport, serial, argc, argv);
1929
Kenny Root60733e92012-03-26 16:14:02 -07001930cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001931 delete_file(transport, serial, apk_dest);
1932 return err;
1933}
1934
1935int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1936{
1937 char buf[1024];
1938 int i;
1939 struct stat sb;
1940 unsigned long long total_size = 0;
1941
1942 // Find all APK arguments starting at end.
1943 // All other arguments passed through verbatim.
1944 int first_apk = -1;
1945 for (i = argc - 1; i >= 0; i--) {
1946 char* file = argv[i];
1947 char* dot = strrchr(file, '.');
1948 if (dot && !strcasecmp(dot, ".apk")) {
1949 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1950 fprintf(stderr, "Invalid APK file: %s\n", file);
1951 return -1;
1952 }
1953
1954 total_size += sb.st_size;
1955 first_apk = i;
1956 } else {
1957 break;
1958 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001959 }
1960
Jeff Sharkey960df972014-06-09 17:30:57 -07001961 if (first_apk == -1) {
1962 fprintf(stderr, "Missing APK file\n");
1963 return 1;
1964 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001965
Jeff Sharkey960df972014-06-09 17:30:57 -07001966 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1967 for (i = 1; i < first_apk; i++) {
1968 char *quoted = escape_arg(argv[i]);
1969 strncat(buf, " ", sizeof(buf) - 1);
1970 strncat(buf, quoted, sizeof(buf) - 1);
1971 free(quoted);
1972 }
1973
1974 // Create install session
1975 int fd = adb_connect(buf);
1976 if (fd < 0) {
1977 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1978 return -1;
1979 }
1980 read_status_line(fd, buf, sizeof(buf));
1981 adb_close(fd);
1982
1983 int session_id = -1;
1984 if (!strncmp("Success", buf, 7)) {
1985 char* start = strrchr(buf, '[');
1986 char* end = strrchr(buf, ']');
1987 if (start && end) {
1988 *end = '\0';
1989 session_id = strtol(start + 1, NULL, 10);
1990 }
1991 }
1992 if (session_id < 0) {
1993 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001994 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001995 return -1;
1996 }
1997
1998 // Valid session, now stream the APKs
1999 int success = 1;
2000 for (i = first_apk; i < argc; i++) {
2001 char* file = argv[i];
2002 if (stat(file, &sb) == -1) {
2003 fprintf(stderr, "Failed to stat %s\n", file);
2004 success = 0;
2005 goto finalize_session;
2006 }
2007
2008 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002009 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002010
2011 int localFd = adb_open(file, O_RDONLY);
2012 if (localFd < 0) {
2013 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2014 success = 0;
2015 goto finalize_session;
2016 }
2017
2018 int remoteFd = adb_connect(buf);
2019 if (remoteFd < 0) {
2020 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2021 adb_close(localFd);
2022 success = 0;
2023 goto finalize_session;
2024 }
2025
2026 copy_to_file(localFd, remoteFd);
2027 read_status_line(remoteFd, buf, sizeof(buf));
2028
2029 adb_close(localFd);
2030 adb_close(remoteFd);
2031
2032 if (strncmp("Success", buf, 7)) {
2033 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002034 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002035 success = 0;
2036 goto finalize_session;
2037 }
2038 }
2039
2040finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002041 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002042 if (success) {
2043 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2044 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002045 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002046 }
2047
2048 fd = adb_connect(buf);
2049 if (fd < 0) {
2050 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2051 return -1;
2052 }
2053 read_status_line(fd, buf, sizeof(buf));
2054 adb_close(fd);
2055
2056 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002057 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002058 return 0;
2059 } else {
2060 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002061 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002062 return -1;
2063 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002064}