blob: e59a96a8feaa2a56c6d799fb6227d6179988171c [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 Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
19#include "sysdeps.h"
20
Dan Albert76649012015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
Elliott Hughes2940ccf2015-04-17 14:07:52 -070024#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <limits.h>
26#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <stdint.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080032#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033
Elliott Hughes2baae3a2015-04-17 10:59:34 -070034#include <string>
35
36#include <base/stringprintf.h>
37
Yabin Cuid325e862014-11-17 14:48:25 -080038#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080040#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#endif
42
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080044#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080045#include "adb_client.h"
46#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070047#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048#include "file_sync_service.h"
49
Dan Albertbac34742015-02-25 17:51:28 -080050static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080051
Elliott Hughes58305772015-04-17 13:57:15 -070052static int install_app(transport_type transport, const char* serial, int argc,
53 const char** argv);
54static int install_multiple_app(transport_type transport, const char* serial, int argc,
55 const char** argv);
56static int uninstall_app(transport_type transport, const char* serial, int argc,
Dan Albertbac34742015-02-25 17:51:28 -080057 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Elliott Hughes58305772015-04-17 13:57:15 -070059static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080060extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080061
Elliott Hughes58305772015-04-17 13:57:15 -070062static std::string product_file(const char *extra) {
63 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080064 fprintf(stderr, "adb: Product directory not specified; "
65 "use -p or define ANDROID_PRODUCT_OUT\n");
66 exit(1);
67 }
68
Elliott Hughes58305772015-04-17 13:57:15 -070069 return android::base::StringPrintf("%s%s%s",
70 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
72
Elliott Hughes58305772015-04-17 13:57:15 -070073static void version(FILE* out) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
Elliott Hughes58305772015-04-17 13:57:15 -070075 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080076}
77
Elliott Hughes58305772015-04-17 13:57:15 -070078static void help() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 version(stderr);
80
81 fprintf(stderr,
82 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080083 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080084 " -d - directs command to the only connected USB device\n"
85 " returns an error if more than one USB device is present.\n"
86 " -e - directs command to the only running emulator.\n"
87 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070088 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070089 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070090 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080091 " -p <product name or path> - simple product name like 'sooner', or\n"
92 " a relative/absolute path to a product\n"
93 " out directory like 'out/target/product/sooner'.\n"
94 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
95 " environment variable is used, which must\n"
96 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080097 " -H - Name of adb server host (default: localhost)\n"
98 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070099 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700100 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400101 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
102 " Port 5555 is used by default if no port number is specified.\n"
103 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
104 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200105 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400106 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107 "\n"
108 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700109 " adb push [-p] <local> <remote>\n"
110 " - copy file/dir to device\n"
111 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700112 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700113 " - copy file/dir from device\n"
114 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700115 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800116 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600117 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 " (see 'adb help all')\n"
119 " adb shell - run remote shell interactively\n"
120 " adb shell <command> - run remote shell command\n"
121 " adb emu <command> - run emulator console command\n"
122 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100123 " adb forward --list - list all forward socket connections.\n"
124 " the format is a list of lines with the following format:\n"
125 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 " adb forward <local> <remote> - forward socket connections\n"
127 " forward specs are one of: \n"
128 " tcp:<port>\n"
129 " localabstract:<unix domain socket name>\n"
130 " localreserved:<unix domain socket name>\n"
131 " localfilesystem:<unix domain socket name>\n"
132 " dev:<character device name>\n"
133 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100134 " adb forward --no-rebind <local> <remote>\n"
135 " - same as 'adb forward <local> <remote>' but fails\n"
136 " if <local> is already forwarded\n"
137 " adb forward --remove <local> - remove a specific forward socket connection\n"
138 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100139 " adb reverse --list - list all reverse socket connections from device\n"
140 " adb reverse <remote> <local> - reverse socket connections\n"
141 " reverse specs are one of:\n"
142 " tcp:<port>\n"
143 " localabstract:<unix domain socket name>\n"
144 " localreserved:<unix domain socket name>\n"
145 " localfilesystem:<unix domain socket name>\n"
146 " adb reverse --norebind <remote> <local>\n"
147 " - same as 'adb reverse <remote> <local>' but fails\n"
148 " if <remote> is already reversed.\n"
149 " adb reverse --remove <remote>\n"
150 " - remove a specific reversed socket connection\n"
151 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800152 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700153 " adb install [-lrtsd] <file>\n"
154 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700155 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700156 " (-l: forward lock application)\n"
157 " (-r: replace existing application)\n"
158 " (-t: allow test packages)\n"
159 " (-s: install application on sdcard)\n"
160 " (-d: allow version code downgrade)\n"
161 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 " adb uninstall [-k] <package> - remove this app package from the device\n"
163 " ('-k' means keep the data and cache directories)\n"
164 " adb bugreport - return all information from the device\n"
165 " that should be included in a bug report.\n"
166 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800167 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700168 " - write an archive of the device's data to <file>.\n"
169 " If no -f option is supplied then the data is written\n"
170 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700171 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700172 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800173 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
174 " (aka .obb) files associated with each application; the default\n"
175 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (-shared|-noshared enable/disable backup of the device's\n"
177 " shared storage / SD card contents; the default is noshared.)\n"
178 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700179 " (-system|-nosystem toggles whether -all automatically includes\n"
180 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (<packages...> is the list of applications to be backed up. If\n"
182 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700183 " list is optional. Applications explicitly given on the\n"
184 " command line will be included even if -nosystem would\n"
185 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700187 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700188 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800189 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
190 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800191 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
192 " and the public key is stored in <file>.pub. Any existing files\n"
193 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800194 " adb help - show this help message\n"
195 " adb version - show version num\n"
196 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 "scripting:\n"
198 " adb wait-for-device - block until device is online\n"
199 " adb start-server - ensure that there is a server running\n"
200 " adb kill-server - kill the server if it is running\n"
201 " adb get-state - prints: offline | bootloader | device\n"
202 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700203 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000205 " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
Tao Bao175b7bb2015-03-29 11:22:34 -0700206 " adb reboot [bootloader|recovery]\n"
207 " - reboots the device, optionally into the bootloader or recovery program.\n"
208 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
209 " adb reboot sideload-auto-reboot\n"
210 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800211 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700212 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500213 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800214 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000215 " 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 -0800216 "networking:\n"
217 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500218 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800219 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
220 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
221 "\n"
222 "adb sync notes: adb sync [ <directory> ]\n"
223 " <localdir> can be interpreted in several ways:\n"
224 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000225 " - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000227 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000229 "\n"
230 "environmental variables:\n"
231 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
232 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
233 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
234 " 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 -0800235 );
236}
237
Elliott Hughes58305772015-04-17 13:57:15 -0700238static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 help();
240 return 1;
241}
242
Yabin Cuid325e862014-11-17 14:48:25 -0800243#if defined(_WIN32)
244
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700245// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800246void stdin_raw_init(int fd);
247void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800248
249#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100250static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100252static void stdin_raw_init(int fd) {
253 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800254
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100255 termios tio;
256 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100258 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261 tio.c_cc[VTIME] = 0;
262 tio.c_cc[VMIN] = 1;
263
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100264 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265}
266
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100267static void stdin_raw_restore(int fd) {
268 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269}
270#endif
271
272static void read_and_dump(int fd)
273{
274 char buf[4096];
275 int len;
276
277 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700278 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800279 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700280 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 if(len == 0) {
282 break;
283 }
284
285 if(len < 0) {
286 if(errno == EINTR) continue;
287 break;
288 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400289 fwrite(buf, 1, len, stdout);
290 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 }
292}
293
Jeff Sharkey960df972014-06-09 17:30:57 -0700294static void read_status_line(int fd, char* buf, size_t count)
295{
296 count--;
297 while (count > 0) {
298 int len = adb_read(fd, buf, count);
299 if (len == 0) {
300 break;
301 } else if (len < 0) {
302 if (errno == EINTR) continue;
303 break;
304 }
305
306 buf += len;
307 count -= len;
308 }
309 *buf = '\0';
310}
311
Christopher Tated2f54152011-04-21 12:53:28 -0700312static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700313 const size_t BUFSIZE = 32 * 1024;
314 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700315 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700316 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700317 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700318
319 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800320
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700321 if (inFd == STDIN_FILENO) {
322 stdin_raw_init(STDIN_FILENO);
323 }
Yabin Cuid325e862014-11-17 14:48:25 -0800324
Elliott Hughesa7090b92015-04-17 17:03:59 -0700325 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700326 if (inFd == STDIN_FILENO) {
327 len = unix_read(inFd, buf, BUFSIZE);
328 } else {
329 len = adb_read(inFd, buf, BUFSIZE);
330 }
Christopher Tated2f54152011-04-21 12:53:28 -0700331 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700332 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700333 break;
334 }
335 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700336 if (errno == EINTR) {
337 D("copy_to_file() : EINTR, retrying\n");
338 continue;
339 }
Christopher Tated2f54152011-04-21 12:53:28 -0700340 D("copy_to_file() : error %d\n", errno);
341 break;
342 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700343 if (outFd == STDOUT_FILENO) {
344 fwrite(buf, 1, len, stdout);
345 fflush(stdout);
346 } else {
347 adb_write(outFd, buf, len);
348 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700349 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700350 }
Yabin Cuid325e862014-11-17 14:48:25 -0800351
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700352 if (inFd == STDIN_FILENO) {
353 stdin_raw_restore(STDIN_FILENO);
354 }
Yabin Cuid325e862014-11-17 14:48:25 -0800355
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700356 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700357 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700358}
359
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800360static void *stdin_read_thread(void *x)
361{
362 int fd, fdi;
363 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800364 int r, n;
365 int state = 0;
366
367 int *fds = (int*) x;
368 fd = fds[0];
369 fdi = fds[1];
370 free(fds);
371
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 for(;;) {
373 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700374 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700376 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800377 if(r == 0) break;
378 if(r < 0) {
379 if(errno == EINTR) continue;
380 break;
381 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400382 for(n = 0; n < r; n++){
383 switch(buf[n]) {
384 case '\n':
385 state = 1;
386 break;
387 case '\r':
388 state = 1;
389 break;
390 case '~':
391 if(state == 1) state++;
392 break;
393 case '.':
394 if(state == 2) {
395 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400396 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400397 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800398 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400399 default:
400 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800403 r = adb_write(fd, buf, r);
404 if(r <= 0) {
405 break;
406 }
407 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 return 0;
409}
410
Elliott Hughes58305772015-04-17 13:57:15 -0700411static int interactive_shell() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 adb_thread_t thr;
413 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414
415 fd = adb_connect("shell:");
416 if(fd < 0) {
417 fprintf(stderr,"error: %s\n", adb_error());
418 return 1;
419 }
420 fdi = 0; //dup(0);
421
Dan Albertbac34742015-02-25 17:51:28 -0800422 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700423 if (fds == nullptr) {
424 fprintf(stderr, "couldn't allocate fds array: %s\n", strerror(errno));
425 return 1;
426 }
427
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 fds[0] = fd;
429 fds[1] = fdi;
430
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800432 adb_thread_create(&thr, stdin_read_thread, fds);
433 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800435 return 0;
436}
437
438
439static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
440{
441 if (serial) {
442 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
443 } else {
444 const char* prefix = "host";
445 if (ttype == kTransportUsb)
446 prefix = "host-usb";
447 else if (ttype == kTransportLocal)
448 prefix = "host-local";
449
450 snprintf(buffer, buflen, "%s:%s", prefix, command);
451 }
452}
453
Elliott Hughes58305772015-04-17 13:57:15 -0700454static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
455 unsigned progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800456{
457 char buf[4096];
458 unsigned total;
459 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800460
461 sprintf(buf,"%s:%d", service, sz);
462 fd = adb_connect(buf);
463 if(fd < 0) {
464 fprintf(stderr,"error: %s\n", adb_error());
465 return -1;
466 }
467
468 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800469 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800470
471 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800472 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800473
474 if(progress) {
475 char *x = strrchr(service, ':');
476 if(x) service = x + 1;
477 }
478
479 while(sz > 0) {
480 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800481 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800482 adb_status(fd);
483 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
484 return -1;
485 }
486 sz -= xfer;
487 ptr += xfer;
488 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100489 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800490 fflush(stdout);
491 }
492 }
493 if(progress) {
494 printf("\n");
495 }
496
Dan Albertcc731cc2015-02-24 21:26:58 -0800497 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800498 fprintf(stderr,"* error reading response *\n");
499 adb_close(fd);
500 return -1;
501 }
502 if(memcmp(buf, "OKAY", 4)) {
503 buf[4] = 0;
504 fprintf(stderr,"* error response '%s' *\n", buf);
505 adb_close(fd);
506 return -1;
507 }
508
509 adb_close(fd);
510 return 0;
511}
512
Doug Zongker71fe5842014-06-26 15:35:36 -0700513#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
514
515/*
516 * The sideload-host protocol serves the data in a file (given on the
517 * command line) to the client, using a simple protocol:
518 *
519 * - The connect message includes the total number of bytes in the
520 * file and a block size chosen by us.
521 *
522 * - The other side sends the desired block number as eight decimal
523 * digits (eg "00000023" for block 23). Blocks are numbered from
524 * zero.
525 *
526 * - We send back the data of the requested block. The last block is
527 * likely to be partial; when the last block is requested we only
528 * send the part of the block that exists, it's not padded up to the
529 * block size.
530 *
531 * - When the other side sends "DONEDONE" instead of a block number,
532 * we hang up.
533 */
Elliott Hughes58305772015-04-17 13:57:15 -0700534static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700535 unsigned sz;
536 size_t xfer = 0;
537 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800538 int last_percent = -1;
539 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700540
541 printf("loading: '%s'", fn);
542 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800543 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700544 if (data == 0) {
545 printf("\n");
546 fprintf(stderr, "* cannot read '%s' *\n", fn);
547 return -1;
548 }
549
550 char buf[100];
551 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
552 int fd = adb_connect(buf);
553 if (fd < 0) {
554 // Try falling back to the older sideload method. Maybe this
555 // is an older device that doesn't support sideload-host.
556 printf("\n");
557 status = adb_download_buffer("sideload", fn, data, sz, 1);
558 goto done;
559 }
560
Spencer Lowf055c192015-01-25 14:40:16 -0800561 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700562
Elliott Hughesa7090b92015-04-17 17:03:59 -0700563 while (true) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800564 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700565 fprintf(stderr, "* failed to read command: %s\n", adb_error());
566 status = -1;
567 goto done;
568 }
569
570 if (strncmp("DONEDONE", buf, 8) == 0) {
571 status = 0;
572 break;
573 }
574
575 buf[8] = '\0';
576 int block = strtol(buf, NULL, 10);
577
578 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
579 if (offset >= sz) {
580 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
581 status = -1;
582 goto done;
583 }
584 uint8_t* start = data + offset;
585 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
586 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
587 if (offset_end > sz) {
588 to_write = sz - offset;
589 }
590
Dan Albertcc731cc2015-02-24 21:26:58 -0800591 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700592 adb_status(fd);
593 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
594 status = -1;
595 goto done;
596 }
597 xfer += to_write;
598
599 // For normal OTA packages, we expect to transfer every byte
600 // twice, plus a bit of overhead (one read during
601 // verification, one read of each byte for installation, plus
602 // extra access to things like the zip central directory).
603 // This estimate of the completion becomes 100% when we've
604 // transferred ~2.13 (=100/47) times the package size.
605 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
606 if (percent != last_percent) {
607 printf("\rserving: '%s' (~%d%%) ", fn, percent);
608 fflush(stdout);
609 last_percent = percent;
610 }
611 }
612
Colin Cross6d6a8982014-07-07 14:12:41 -0700613 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700614
615 done:
616 if (fd >= 0) adb_close(fd);
617 free(data);
618 return status;
619}
620
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800621static void status_window(transport_type ttype, const char* serial)
622{
623 char command[4096];
624 char *state = 0;
625 char *laststate = 0;
626
627 /* silence stderr */
628#ifdef _WIN32
629 /* XXX: TODO */
630#else
631 int fd;
632 fd = unix_open("/dev/null", O_WRONLY);
633 dup2(fd, 2);
634 adb_close(fd);
635#endif
636
637 format_host_command(command, sizeof command, "get-state", ttype, serial);
638
639 for(;;) {
640 adb_sleep_ms(250);
641
642 if(state) {
643 free(state);
644 state = 0;
645 }
646
647 state = adb_query(command);
648
649 if(state) {
650 if(laststate && !strcmp(state,laststate)){
651 continue;
652 } else {
653 if(laststate) free(laststate);
654 laststate = strdup(state);
655 }
656 }
657
658 printf("%c[2J%c[2H", 27, 27);
659 printf("Android Debug Bridge\n");
660 printf("State: %s\n", state ? state : "offline");
661 fflush(stdout);
662 }
663}
664
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800665/**
666 * Run ppp in "notty" mode against a resource listed as the first parameter
667 * eg:
668 *
669 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
670 *
671 */
Elliott Hughes58305772015-04-17 13:57:15 -0700672static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800673#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800674 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
675 return -1;
676#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800677 pid_t pid;
678 int fd;
679
680 if (argc < 2) {
681 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
682 argv[0]);
683
684 return 1;
685 }
686
Dan Albertbac34742015-02-25 17:51:28 -0800687 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800688 fd = adb_connect(adb_service_name);
689
690 if(fd < 0) {
691 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
692 adb_service_name, adb_error());
693 return 1;
694 }
695
696 pid = fork();
697
698 if (pid < 0) {
699 perror("from fork()");
700 return 1;
701 } else if (pid == 0) {
702 int err;
703 int i;
704 const char **ppp_args;
705
706 // copy args
707 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
708 ppp_args[0] = "pppd";
709 for (i = 2 ; i < argc ; i++) {
710 //argv[2] and beyond become ppp_args[1] and beyond
711 ppp_args[i - 1] = argv[i];
712 }
713 ppp_args[i-1] = NULL;
714
715 // child side
716
717 dup2(fd, STDIN_FILENO);
718 dup2(fd, STDOUT_FILENO);
719 adb_close(STDERR_FILENO);
720 adb_close(fd);
721
722 err = execvp("pppd", (char * const *)ppp_args);
723
724 if (err < 0) {
725 perror("execing pppd");
726 }
727 exit(-1);
728 } else {
729 // parent side
730
731 adb_close(fd);
732 return 0;
733 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800734#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800735}
736
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700737static int send_shell_command(transport_type transport, const char* serial,
738 const std::string& command) {
739 int fd;
740 while (true) {
741 fd = adb_connect(command.c_str());
742 if (fd >= 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800743 break;
744 fprintf(stderr,"- waiting for device -\n");
745 adb_sleep_ms(1000);
746 do_cmd(transport, serial, "wait-for-device", 0);
747 }
748
749 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700750 int rc = adb_close(fd);
751 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800752 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700753 }
754 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800755}
756
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700757static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
758 char* log_tags = getenv("ANDROID_LOG_TAGS");
759 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800760
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700761 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800762
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700763 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700764 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800765 }
766
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700767 --argc;
768 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700769 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700770 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800771 }
772
Elliott Hughes15551472015-04-21 17:58:55 -0700773 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800774}
775
Mark Salyzyn60299df2014-04-30 09:10:31 -0700776static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800777{
778 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700779 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800780
781 for(;;) {
782 x = adb_dirstart(x);
783 if(x == 0) return 0;
784 *x = 0;
785 ret = adb_mkdir(path, 0775);
786 *x = OS_PATH_SEPARATOR;
787 if((ret < 0) && (errno != EEXIST)) {
788 return ret;
789 }
790 x++;
791 }
792 return 0;
793}
794
Dan Albertbac34742015-02-25 17:51:28 -0800795static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700796 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700797
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700798 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700799 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700800 if (!strcmp("-f", argv[i])) {
801 if (i == argc-1) {
802 fprintf(stderr, "adb: -f passed with no filename\n");
803 return usage();
804 }
805 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700806 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700807 argv[i++] = argv[j++];
808 }
809 argc -= 2;
810 argv[argc] = NULL;
811 }
Christopher Tated2f54152011-04-21 12:53:28 -0700812 }
813
Christopher Tatebb86bc52011-08-22 17:12:08 -0700814 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
815 if (argc < 2) return usage();
816
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800817 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700818 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700819 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700820 if (outFd < 0) {
821 fprintf(stderr, "adb: unable to open file %s\n", filename);
822 return -1;
823 }
824
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700825 std::string cmd = "backup:";
826 --argc;
827 ++argv;
828 while (argc-- > 0) {
829 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700830 }
831
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700832 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
833 int fd = adb_connect(cmd.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700834 if (fd < 0) {
835 fprintf(stderr, "adb: unable to connect for backup\n");
836 adb_close(outFd);
837 return -1;
838 }
839
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800840 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700841 copy_to_file(fd, outFd);
842
843 adb_close(fd);
844 adb_close(outFd);
845 return 0;
846}
847
Dan Albertbac34742015-02-25 17:51:28 -0800848static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700849 const char* filename;
850 int fd, tarFd;
851
852 if (argc != 2) return usage();
853
854 filename = argv[1];
855 tarFd = adb_open(filename, O_RDONLY);
856 if (tarFd < 0) {
857 fprintf(stderr, "adb: unable to open file %s\n", filename);
858 return -1;
859 }
860
861 fd = adb_connect("restore:");
862 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700863 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700864 adb_close(tarFd);
865 return -1;
866 }
867
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800868 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700869 copy_to_file(tarFd, fd);
870
871 adb_close(fd);
872 adb_close(tarFd);
873 return 0;
874}
875
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800876/* <hint> may be:
877 * - A simple product name
878 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800879 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
880 * e.g., "out/target/product/sooner"
881 * - An absolute path to the PRODUCT_OUT dir
882 * e.g., "/src/device/out/target/product/sooner"
883 *
884 * Given <hint>, try to construct an absolute path to the
885 * ANDROID_PRODUCT_OUT dir.
886 */
Elliott Hughes58305772015-04-17 13:57:15 -0700887static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800888 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700889 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800890 }
891
Elliott Hughes58305772015-04-17 13:57:15 -0700892 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800893 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700894 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800895 }
896
Elliott Hughes58305772015-04-17 13:57:15 -0700897 // If there are any slashes in it, assume it's a relative path;
898 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700899 if (adb_dirstart(hint) != nullptr) {
900 std::string cwd;
901 if (!getcwd(&cwd)) {
902 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700903 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800904 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700905 return android::base::StringPrintf("%s%s%s", cwd.c_str(), OS_PATH_SEPARATOR_STR, hint);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800906 }
907
Elliott Hughes58305772015-04-17 13:57:15 -0700908 // It's a string without any slashes. Try to do something with it.
909 //
910 // Try to find the root of the build tree, and build a PRODUCT_OUT
911 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700912 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700913 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700914 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700915 return "";
916 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700917
918 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700919 path += OS_PATH_SEPARATOR_STR;
920 path += "out";
921 path += OS_PATH_SEPARATOR_STR;
922 path += "target";
923 path += OS_PATH_SEPARATOR_STR;
924 path += "product";
925 path += OS_PATH_SEPARATOR_STR;
926 path += hint;
927 if (!directory_exists(path)) {
928 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
929 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700930 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800931 }
Elliott Hughes58305772015-04-17 13:57:15 -0700932 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800933}
934
Dan Albertbac34742015-02-25 17:51:28 -0800935static void parse_push_pull_args(const char **arg, int narg, char const **path1,
936 char const **path2, int *show_progress,
937 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700938 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700939 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700940
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700941 while (narg > 0) {
942 if (!strcmp(*arg, "-p")) {
943 *show_progress = 1;
944 } else if (!strcmp(*arg, "-a")) {
945 *copy_attrs = 1;
946 } else {
947 break;
948 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700949 ++arg;
950 --narg;
951 }
952
953 if (narg > 0) {
954 *path1 = *arg;
955 ++arg;
956 --narg;
957 }
958
959 if (narg > 0) {
960 *path2 = *arg;
961 }
962}
963
Tao Bao175b7bb2015-03-29 11:22:34 -0700964static int adb_connect_command(const char* command) {
965 int fd = adb_connect(command);
966 if (fd != -1) {
967 read_and_dump(fd);
968 adb_close(fd);
969 return 0;
970 }
971 fprintf(stderr, "Error: %s\n", adb_error());
972 return 1;
973}
974
Dan Albertbac34742015-02-25 17:51:28 -0800975int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800976{
977 char buf[4096];
978 int no_daemon = 0;
979 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100980 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800981 int persist = 0;
982 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800983 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -0800984 const char* serial = NULL;
985 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800986
Elliott Hughes58305772015-04-17 13:57:15 -0700987 // If defined, this should be an absolute path to
988 // the directory containing all of the various system images
989 // for a particular product. If not defined, and the adb
990 // command requires this information, then the user must
991 // specify the path using "-p".
992 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
993 if (ANDROID_PRODUCT_OUT != nullptr) {
994 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800995 }
996 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
997
Nick Pellydb449262009-05-07 12:48:03 -0700998 serial = getenv("ANDROID_SERIAL");
999
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001000 /* Validate and assign the server port */
1001 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1002 int server_port = DEFAULT_ADB_PORT;
1003 if (server_port_str && strlen(server_port_str) > 0) {
1004 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001005 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001006 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001007 "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 +01001008 server_port_str);
1009 return usage();
1010 }
1011 }
1012
1013 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001014 while (argc > 0) {
1015 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001016 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001017 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 no_daemon = 1;
1019 } else if (!strcmp(argv[0], "fork-server")) {
1020 /* this is a special flag used only when the ADB client launches the ADB Server */
1021 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001022 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001024 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001025 const char *product = NULL;
1026 if (argv[0][2] == '\0') {
1027 if (argc < 2) return usage();
1028 product = argv[1];
1029 argc--;
1030 argv++;
1031 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001032 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001033 }
1034 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001035 if (gProductOutPath.empty()) {
1036 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001037 return usage();
1038 }
1039 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1040 if (isdigit(argv[0][2])) {
1041 serial = argv[0] + 2;
1042 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001043 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001044 serial = argv[1];
1045 argc--;
1046 argv++;
1047 }
1048 } else if (!strcmp(argv[0],"-d")) {
1049 ttype = kTransportUsb;
1050 } else if (!strcmp(argv[0],"-e")) {
1051 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001052 } else if (!strcmp(argv[0],"-a")) {
1053 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001054 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001055 const char *hostname = NULL;
1056 if (argv[0][2] == '\0') {
1057 if (argc < 2) return usage();
1058 hostname = argv[1];
1059 argc--;
1060 argv++;
1061 } else {
1062 hostname = argv[0] + 2;
1063 }
1064 adb_set_tcp_name(hostname);
1065
Riley Andrews98f58e82014-12-05 17:37:24 -08001066 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001067 if (argv[0][2] == '\0') {
1068 if (argc < 2) return usage();
1069 server_port_str = argv[1];
1070 argc--;
1071 argv++;
1072 } else {
1073 server_port_str = argv[0] + 2;
1074 }
1075 if (strlen(server_port_str) > 0) {
1076 server_port = (int) strtol(server_port_str, NULL, 0);
1077 if (server_port <= 0 || server_port > 65535) {
1078 fprintf(stderr,
1079 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1080 server_port_str);
1081 return usage();
1082 }
1083 } else {
1084 fprintf(stderr,
1085 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1086 return usage();
1087 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001088 } else {
1089 /* out of recognized modifiers and flags */
1090 break;
1091 }
1092 argc--;
1093 argv++;
1094 }
1095
1096 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001097 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001098
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001099 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001100 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001101 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001102 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001103 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001105 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001106 fprintf(stderr,"* could not start server *\n");
1107 }
1108 return r;
1109 }
1110
Riley Andrews98f58e82014-12-05 17:37:24 -08001111 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001112 return usage();
1113 }
1114
Riley Andrewsc8514c82014-12-05 17:32:46 -08001115 /* handle wait-for-* prefix */
1116 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001117 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001118 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1119 if (ttype == kTransportUsb) {
1120 service = "wait-for-usb";
1121 } else if (ttype == kTransportLocal) {
1122 service = "wait-for-local";
1123 } else {
1124 service = "wait-for-any";
1125 }
1126 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001127
Riley Andrewsc8514c82014-12-05 17:32:46 -08001128 format_host_command(buf, sizeof buf, service, ttype, serial);
1129
1130 if (adb_command(buf)) {
1131 D("failure: %s *\n",adb_error());
1132 fprintf(stderr,"error: %s\n", adb_error());
1133 return 1;
1134 }
1135
1136 /* Allow a command to be run after wait-for-device,
1137 * e.g. 'adb wait-for-device shell'.
1138 */
1139 if (argc == 1) {
1140 return 0;
1141 }
1142
1143 /* Fall through */
1144 argc--;
1145 argv++;
1146 }
1147
1148 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001149 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001150 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001151 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001152 if (argc < 2)
1153 listopt = "";
1154 else if (argc == 2 && !strcmp(argv[1], "-l"))
1155 listopt = argv[1];
1156 else {
1157 fprintf(stderr, "Usage: adb devices [-l]\n");
1158 return 1;
1159 }
1160 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001161 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001162 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 printf("List of devices attached \n");
1164 printf("%s\n", tmp);
1165 return 0;
1166 } else {
1167 return 1;
1168 }
1169 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001170 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001171 char *tmp;
1172 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001173 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001174 return 1;
1175 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001176 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1177 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001178 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001179 printf("%s\n", tmp);
1180 return 0;
1181 } else {
1182 return 1;
1183 }
1184 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001185 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001186 char *tmp;
1187 if (argc > 2) {
1188 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1189 return 1;
1190 }
1191 if (argc == 2) {
1192 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1193 } else {
1194 snprintf(buf, sizeof buf, "host:disconnect:");
1195 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001196 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001197 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001198 printf("%s\n", tmp);
1199 return 0;
1200 } else {
1201 return 1;
1202 }
1203 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001204 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001205 return adb_send_emulator_command(argc, argv);
1206 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001207 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001208 char h = (argv[0][0] == 'h');
1209
1210 if (h) {
1211 printf("\x1b[41;33m");
1212 fflush(stdout);
1213 }
1214
Riley Andrews98f58e82014-12-05 17:37:24 -08001215 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001216 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001217 r = interactive_shell();
1218 if (h) {
1219 printf("\x1b[0m");
1220 fflush(stdout);
1221 }
1222 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001223 }
1224
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001225 std::string cmd = "shell:";
1226 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001227 argc -= 2;
1228 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001229 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001230 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001231 }
1232
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001233 while (true) {
1234 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1235 int fd = adb_connect(cmd.c_str());
1236 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001237 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001238 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001239 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001240 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001241 adb_close(fd);
1242 r = 0;
1243 } else {
1244 fprintf(stderr,"error: %s\n", adb_error());
1245 r = -1;
1246 }
1247
Riley Andrews98f58e82014-12-05 17:37:24 -08001248 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001249 fprintf(stderr,"\n- waiting for device -\n");
1250 adb_sleep_ms(1000);
1251 do_cmd(ttype, serial, "wait-for-device", 0);
1252 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001253 if (h) {
1254 printf("\x1b[0m");
1255 fflush(stdout);
1256 }
JP Abgrall408fa572011-03-16 15:57:42 -07001257 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258 return r;
1259 }
1260 }
1261 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001262 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001263 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001264
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001265 std::string cmd = "exec:";
1266 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001267 argc -= 2;
1268 argv += 2;
1269 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001270 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001271 }
1272
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001273 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001274 if (fd < 0) {
1275 fprintf(stderr, "error: %s\n", adb_error());
1276 return -1;
1277 }
1278
1279 if (exec_in) {
1280 copy_to_file(STDIN_FILENO, fd);
1281 } else {
1282 copy_to_file(fd, STDOUT_FILENO);
1283 }
1284
1285 adb_close(fd);
1286 return 0;
1287 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001288 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001289 int fd;
1290 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001291 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001292 fprintf(stderr,"* server not running *\n");
1293 return 1;
1294 }
1295 return 0;
1296 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001297 else if (!strcmp(argv[0], "sideload")) {
1298 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001299 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001300 return 1;
1301 } else {
1302 return 0;
1303 }
1304 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001305 else if (!strcmp(argv[0], "remount") ||
1306 !strcmp(argv[0], "reboot") ||
1307 !strcmp(argv[0], "reboot-bootloader") ||
1308 !strcmp(argv[0], "tcpip") ||
1309 !strcmp(argv[0], "usb") ||
1310 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001311 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001312 !strcmp(argv[0], "disable-verity") ||
1313 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001314 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001315 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001316 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001317 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001318 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001319 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001320 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001321 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001322 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001323 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001324 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001325 if (argc != 1) return usage();
1326 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001327 return 0;
1328 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001329 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001330 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001331 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001332 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001333 char remove = 0;
1334 char remove_all = 0;
1335 char list = 0;
1336 char no_rebind = 0;
1337
1338 // Parse options here.
1339 while (argc > 1 && argv[1][0] == '-') {
1340 if (!strcmp(argv[1], "--list"))
1341 list = 1;
1342 else if (!strcmp(argv[1], "--remove"))
1343 remove = 1;
1344 else if (!strcmp(argv[1], "--remove-all"))
1345 remove_all = 1;
1346 else if (!strcmp(argv[1], "--no-rebind"))
1347 no_rebind = 1;
1348 else {
1349 return usage();
1350 }
1351 argc--;
1352 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001353 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001354
1355 // Ensure we can only use one option at a time.
1356 if (list + remove + remove_all + no_rebind > 1) {
1357 return usage();
1358 }
1359
1360 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001361 if (reverse) {
1362 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001363 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001364 if (serial) {
1365 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1366 serial);
1367 } else if (ttype == kTransportUsb) {
1368 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1369 } else if (ttype == kTransportLocal) {
1370 snprintf(host_prefix, sizeof host_prefix, "host-local");
1371 } else {
1372 snprintf(host_prefix, sizeof host_prefix, "host");
1373 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001374 }
1375
1376 // Implement forward --list
1377 if (list) {
1378 if (argc != 1)
1379 return usage();
1380 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1381 char* forwards = adb_query(buf);
1382 if (forwards == NULL) {
1383 fprintf(stderr, "error: %s\n", adb_error());
1384 return 1;
1385 }
1386 printf("%s", forwards);
1387 free(forwards);
1388 return 0;
1389 }
1390
1391 // Implement forward --remove-all
1392 else if (remove_all) {
1393 if (argc != 1)
1394 return usage();
1395 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1396 }
1397
1398 // Implement forward --remove <local>
1399 else if (remove) {
1400 if (argc != 2)
1401 return usage();
1402 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1403 }
1404 // Or implement one of:
1405 // forward <local> <remote>
1406 // forward --no-rebind <local> <remote>
1407 else
1408 {
1409 if (argc != 3)
1410 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001411 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001412 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1413 }
1414
Riley Andrews98f58e82014-12-05 17:37:24 -08001415 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001416 fprintf(stderr,"error: %s\n", adb_error());
1417 return 1;
1418 }
1419 return 0;
1420 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001421 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001422 else if (!strcmp(argv[0], "ls")) {
1423 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001424 return do_sync_ls(argv[1]);
1425 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001426 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001427 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001428 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001429 const char* lpath = NULL, *rpath = NULL;
1430
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001431 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001432
1433 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001434 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001435 }
1436
1437 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001438 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001439 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001440 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001441 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001442 const char* rpath = NULL, *lpath = ".";
1443
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001444 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001445
1446 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001447 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001448 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001449
1450 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001451 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001452 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001453 if (argc < 2) return usage();
1454 return install_app(ttype, serial, argc, argv);
1455 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001456 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001457 if (argc < 2) return usage();
1458 return install_multiple_app(ttype, serial, argc, argv);
1459 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001460 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001461 if (argc < 2) return usage();
1462 return uninstall_app(ttype, serial, argc, argv);
1463 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001464 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001465 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001466 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001467 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001468 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001469 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001470 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001471 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001472 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001473 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001474 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001475 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001476 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001477 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001478 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001479 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001480 } else {
1481 return usage();
1482 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001483
Elliott Hughesd236d072015-04-21 10:17:07 -07001484 if (src != "" &&
1485 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001486 return usage();
1487 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001488
Elliott Hughes58305772015-04-17 13:57:15 -07001489 std::string system_src_path = product_file("system");
1490 std::string data_src_path = product_file("data");
1491 std::string vendor_src_path = product_file("vendor");
1492 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001493
1494 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001495 if (rc == 0 && (src.empty() || src == "system")) {
1496 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001497 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001498 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1499 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001500 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001501 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1502 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001503 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001504 if (rc == 0 && (src.empty() || src == "data")) {
1505 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001506 }
1507 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001508 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001509 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001510 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001511 !strcmp(argv[0],"get-serialno") ||
1512 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001513 {
1514 char *tmp;
1515
1516 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1517 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001518 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001519 printf("%s\n", tmp);
1520 return 0;
1521 } else {
1522 return 1;
1523 }
1524 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001526 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001527 status_window(ttype, serial);
1528 return 0;
1529 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001530 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 return logcat(ttype, serial, argc, argv);
1532 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001533 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001534 return ppp(argc, argv);
1535 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001536 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001537 return adb_connect("host:start-server");
1538 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001539 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001540 return backup(argc, argv);
1541 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001542 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001543 return restore(argc, argv);
1544 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001545 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001546 if (argc < 2) return usage();
1547 return adb_auth_keygen(argv[1]);
1548 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001549 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001550 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001551 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001552 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001553 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001554 help();
1555 return 0;
1556 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001557 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001558 version(stdout);
1559 return 0;
1560 }
1561
1562 usage();
1563 return 1;
1564}
1565
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001566#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001567static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001568{
Dan Albertbac34742015-02-25 17:51:28 -08001569 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001570 int argc;
1571 va_list ap;
1572
1573 va_start(ap, cmd);
1574 argc = 0;
1575
1576 if (serial) {
1577 argv[argc++] = "-s";
1578 argv[argc++] = serial;
1579 } else if (ttype == kTransportUsb) {
1580 argv[argc++] = "-d";
1581 } else if (ttype == kTransportLocal) {
1582 argv[argc++] = "-e";
1583 }
1584
1585 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001586 while(argc < MAX_ARGV_LENGTH &&
1587 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1588 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001589 va_end(ap);
1590
1591#if 0
1592 int n;
1593 fprintf(stderr,"argc = %d\n",argc);
1594 for(n = 0; n < argc; n++) {
1595 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1596 }
1597#endif
1598
1599 return adb_commandline(argc, argv);
1600}
1601
Dan Albertbac34742015-02-25 17:51:28 -08001602static int pm_command(transport_type transport, const char* serial,
1603 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001604{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001605 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001606
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001607 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001608 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001609 }
1610
Elliott Hughes15551472015-04-21 17:58:55 -07001611 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001612}
1613
Elliott Hughes58305772015-04-17 13:57:15 -07001614static int uninstall_app(transport_type transport, const char* serial, int argc,
1615 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001616{
1617 /* if the user choose the -k option, we refuse to do it until devices are
1618 out with the option to uninstall the remaining data somehow (adb/ui) */
1619 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1620 {
1621 printf(
1622 "The -k option uninstalls the application while retaining the data/cache.\n"
1623 "At the moment, there is no way to remove the remaining data.\n"
1624 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1625 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1626 return -1;
1627 }
1628
1629 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1630 return pm_command(transport, serial, argc, argv);
1631}
1632
Dan Albertbac34742015-02-25 17:51:28 -08001633static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001634{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001635 std::string cmd = "shell:rm -f " + escape_arg(filename);
Elliott Hughes15551472015-04-21 17:58:55 -07001636 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637}
1638
Kenny Root597ea5b2011-08-05 11:19:45 -07001639static const char* get_basename(const char* filename)
1640{
1641 const char* basename = adb_dirstop(filename);
1642 if (basename) {
1643 basename++;
1644 return basename;
1645 } else {
1646 return filename;
1647 }
1648}
1649
Elliott Hughes58305772015-04-17 13:57:15 -07001650static int install_app(transport_type transport, const char* serial, int argc,
1651 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001652{
1653 static const char *const DATA_DEST = "/data/local/tmp/%s";
1654 static const char *const SD_DEST = "/sdcard/tmp/%s";
1655 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001656 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001657 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001658
1659 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001660 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001661 where = SD_DEST;
1662 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001663 }
1664
Jeff Sharkey960df972014-06-09 17:30:57 -07001665 // Find last APK argument.
1666 // All other arguments passed through verbatim.
1667 int last_apk = -1;
1668 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001669 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001670 char* dot = strrchr(file, '.');
1671 if (dot && !strcasecmp(dot, ".apk")) {
1672 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1673 fprintf(stderr, "Invalid APK file: %s\n", file);
1674 return -1;
1675 }
1676
1677 last_apk = i;
1678 break;
1679 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001680 }
1681
Jeff Sharkey960df972014-06-09 17:30:57 -07001682 if (last_apk == -1) {
1683 fprintf(stderr, "Missing APK file\n");
1684 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001685 }
1686
Dan Albertbac34742015-02-25 17:51:28 -08001687 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001688 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001689 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001690 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001691 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001692 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001693 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001694 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001695 }
1696
Elliott Hughes15551472015-04-21 17:58:55 -07001697 err = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001698
Kenny Root60733e92012-03-26 16:14:02 -07001699cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001700 delete_file(transport, serial, apk_dest);
1701 return err;
1702}
1703
Elliott Hughes58305772015-04-17 13:57:15 -07001704static int install_multiple_app(transport_type transport, const char* serial, int argc,
1705 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001706{
Jeff Sharkey960df972014-06-09 17:30:57 -07001707 int i;
1708 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001709 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001710
1711 // Find all APK arguments starting at end.
1712 // All other arguments passed through verbatim.
1713 int first_apk = -1;
1714 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001715 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001716 char* dot = strrchr(file, '.');
1717 if (dot && !strcasecmp(dot, ".apk")) {
1718 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1719 fprintf(stderr, "Invalid APK file: %s\n", file);
1720 return -1;
1721 }
1722
1723 total_size += sb.st_size;
1724 first_apk = i;
1725 } else {
1726 break;
1727 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001728 }
1729
Jeff Sharkey960df972014-06-09 17:30:57 -07001730 if (first_apk == -1) {
1731 fprintf(stderr, "Missing APK file\n");
1732 return 1;
1733 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001734
Elliott Hughes53daee62015-04-19 13:17:01 -07001735#if defined(_WIN32) // Remove when we're using clang for Win32.
1736 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
1737#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001738 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Elliott Hughes53daee62015-04-19 13:17:01 -07001739#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001740 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001741 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001742 }
1743
1744 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001745 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001746 if (fd < 0) {
1747 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1748 return -1;
1749 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001750 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001751 read_status_line(fd, buf, sizeof(buf));
1752 adb_close(fd);
1753
1754 int session_id = -1;
1755 if (!strncmp("Success", buf, 7)) {
1756 char* start = strrchr(buf, '[');
1757 char* end = strrchr(buf, ']');
1758 if (start && end) {
1759 *end = '\0';
1760 session_id = strtol(start + 1, NULL, 10);
1761 }
1762 }
1763 if (session_id < 0) {
1764 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001765 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001766 return -1;
1767 }
1768
1769 // Valid session, now stream the APKs
1770 int success = 1;
1771 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001772 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001773 if (stat(file, &sb) == -1) {
1774 fprintf(stderr, "Failed to stat %s\n", file);
1775 success = 0;
1776 goto finalize_session;
1777 }
1778
Elliott Hughes53daee62015-04-19 13:17:01 -07001779#if defined(_WIN32) // Remove when we're using clang for Win32.
1780 std::string cmd = android::base::StringPrintf(
1781 "exec:pm install-write -S %u %d %d_%s -",
1782 (unsigned) sb.st_size, session_id, i, get_basename(file));
1783#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001784 std::string cmd = android::base::StringPrintf(
1785 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1786 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Elliott Hughes53daee62015-04-19 13:17:01 -07001787#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001788
1789 int localFd = adb_open(file, O_RDONLY);
1790 if (localFd < 0) {
1791 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1792 success = 0;
1793 goto finalize_session;
1794 }
1795
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001796 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001797 if (remoteFd < 0) {
1798 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1799 adb_close(localFd);
1800 success = 0;
1801 goto finalize_session;
1802 }
1803
1804 copy_to_file(localFd, remoteFd);
1805 read_status_line(remoteFd, buf, sizeof(buf));
1806
1807 adb_close(localFd);
1808 adb_close(remoteFd);
1809
1810 if (strncmp("Success", buf, 7)) {
1811 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001812 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001813 success = 0;
1814 goto finalize_session;
1815 }
1816 }
1817
1818finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001819 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07001820 if (success) {
1821 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
1822 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001823 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07001824 }
1825
1826 fd = adb_connect(buf);
1827 if (fd < 0) {
1828 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
1829 return -1;
1830 }
1831 read_status_line(fd, buf, sizeof(buf));
1832 adb_close(fd);
1833
1834 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001835 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001836 return 0;
1837 } else {
1838 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001839 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001840 return -1;
1841 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001842}