blob: 785fef3d9e5b5783cc97076c641e5b855127b106 [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
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG ADB
Dan Albert33134262015-03-19 15:21:08 -070018
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
David Pursell606835a2015-09-08 17:17:02 -070034#include <memory>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070035#include <string>
Josh Gao05786772015-10-30 16:57:19 -070036#include <vector>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070037
David Pursell606835a2015-09-08 17:17:02 -070038#include <base/logging.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070039#include <base/stringprintf.h>
David Pursell4e2fd362015-09-22 10:43:08 -070040#include <base/strings.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070041
Yabin Cuid325e862014-11-17 14:48:25 -080042#if !defined(_WIN32)
Josh Gao8dcdb572015-10-23 15:03:31 -070043#include <signal.h>
Elliott Hughes0fbf9612015-11-04 13:07:47 -080044#include <sys/ioctl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080046#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047#endif
48
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080050#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080051#include "adb_client.h"
52#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070053#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054#include "file_sync_service.h"
David Pursell70ef7b42015-09-30 13:35:42 -070055#include "services.h"
David Pursell606835a2015-09-08 17:17:02 -070056#include "shell_service.h"
57#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Elliott Hughes3bd73c12015-05-05 13:10:43 -070059static int install_app(TransportType t, const char* serial, int argc, const char** argv);
60static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
61static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080062
Elliott Hughes58305772015-04-17 13:57:15 -070063static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080064extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065
Elliott Hughes58305772015-04-17 13:57:15 -070066static std::string product_file(const char *extra) {
67 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080068 fprintf(stderr, "adb: Product directory not specified; "
69 "use -p or define ANDROID_PRODUCT_OUT\n");
70 exit(1);
71 }
72
Elliott Hughes58305772015-04-17 13:57:15 -070073 return android::base::StringPrintf("%s%s%s",
74 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075}
76
Elliott Hughes58305772015-04-17 13:57:15 -070077static void help() {
Elliott Hughes42ae2602015-08-12 08:32:10 -070078 fprintf(stderr, "%s\n", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -080080 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080081 " -d - directs command to the only connected USB device\n"
82 " returns an error if more than one USB device is present.\n"
83 " -e - directs command to the only running emulator.\n"
84 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070085 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070086 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070087 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080088 " -p <product name or path> - simple product name like 'sooner', or\n"
89 " a relative/absolute path to a product\n"
90 " out directory like 'out/target/product/sooner'.\n"
91 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
92 " environment variable is used, which must\n"
93 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080094 " -H - Name of adb server host (default: localhost)\n"
95 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070096 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070097 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040098 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
99 " Port 5555 is used by default if no port number is specified.\n"
100 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
101 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200102 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400103 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800104 "\n"
105 "device commands:\n"
Josh Gao05786772015-10-30 16:57:19 -0700106 " adb push <local>... <remote>\n"
107 " - copy files/dirs to device\n"
108 " adb pull [-a] <remote>... <local>\n"
109 " - copy files/dirs from device\n"
110 " (-a preserves file timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600112 " (-l means list but don't copy)\n"
David Pursell70ef7b42015-09-30 13:35:42 -0700113 " adb shell [-Ttx] - run remote shell interactively\n"
114 " adb shell [-Ttx] <command> - run remote shell command\n"
David Pursell4e2fd362015-09-22 10:43:08 -0700115 " (-T disables PTY allocation)\n"
116 " (-t forces PTY allocation)\n"
David Pursell70ef7b42015-09-30 13:35:42 -0700117 " (-x disables remote exit codes and stdout/stderr separation)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 " adb emu <command> - run emulator console command\n"
119 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100120 " adb forward --list - list all forward socket connections.\n"
121 " the format is a list of lines with the following format:\n"
122 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800123 " adb forward <local> <remote> - forward socket connections\n"
124 " forward specs are one of: \n"
125 " tcp:<port>\n"
126 " localabstract:<unix domain socket name>\n"
127 " localreserved:<unix domain socket name>\n"
128 " localfilesystem:<unix domain socket name>\n"
129 " dev:<character device name>\n"
130 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100131 " adb forward --no-rebind <local> <remote>\n"
132 " - same as 'adb forward <local> <remote>' but fails\n"
133 " if <local> is already forwarded\n"
134 " adb forward --remove <local> - remove a specific forward socket connection\n"
135 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100136 " adb reverse --list - list all reverse socket connections from device\n"
137 " adb reverse <remote> <local> - reverse socket connections\n"
138 " reverse specs are one of:\n"
139 " tcp:<port>\n"
140 " localabstract:<unix domain socket name>\n"
141 " localreserved:<unix domain socket name>\n"
142 " localfilesystem:<unix domain socket name>\n"
Spencer Low587ea202015-11-02 17:34:49 -0800143 " adb reverse --no-rebind <remote> <local>\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100144 " - same as 'adb reverse <remote> <local>' but fails\n"
145 " if <remote> is already reversed.\n"
146 " adb reverse --remove <remote>\n"
147 " - remove a specific reversed socket connection\n"
148 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800149 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900150 " adb install [-lrtsdg] <file>\n"
Svetoslav23d84072015-06-01 16:02:50 -0700151 " - push this package file to the device and install it\n"
152 " (-l: forward lock application)\n"
153 " (-r: replace existing application)\n"
154 " (-t: allow test packages)\n"
155 " (-s: install application on sdcard)\n"
156 " (-d: allow version code downgrade)\n"
157 " (-g: grant all runtime permissions)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900158 " adb install-multiple [-lrtsdpg] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700160 " (-l: forward lock application)\n"
161 " (-r: replace existing application)\n"
162 " (-t: allow test packages)\n"
163 " (-s: install application on sdcard)\n"
164 " (-d: allow version code downgrade)\n"
165 " (-p: partial application install)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900166 " (-g: grant all runtime permissions)\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"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000209 " 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 -0700210 " adb reboot [bootloader|recovery]\n"
211 " - reboots the device, optionally into the bootloader or recovery program.\n"
212 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
213 " adb reboot sideload-auto-reboot\n"
214 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700215 " adb sideload <file> - sideloads the given package\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700216 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500217 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800218 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000219 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700220 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 "networking:\n"
222 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500223 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800224 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
225 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
226 "\n"
227 "adb sync notes: adb sync [ <directory> ]\n"
228 " <localdir> can be interpreted in several ways:\n"
229 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000230 " - 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 -0800231 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000232 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000234 "\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700235 "environment variables:\n"
Timcd643152010-02-16 20:18:29 +0000236 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
237 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
238 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
239 " 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 -0800240 );
241}
242
Elliott Hughes58305772015-04-17 13:57:15 -0700243static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244 help();
245 return 1;
246}
247
Yabin Cuid325e862014-11-17 14:48:25 -0800248#if defined(_WIN32)
249
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700250// Implemented in sysdeps_win32.cpp.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800251void stdin_raw_init();
252void stdin_raw_restore();
Yabin Cuid325e862014-11-17 14:48:25 -0800253
254#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100255static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800257static void stdin_raw_init() {
258 if (tcgetattr(STDIN_FILENO, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 termios tio;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800261 if (tcgetattr(STDIN_FILENO, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100263 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800264
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100265 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266 tio.c_cc[VTIME] = 0;
267 tio.c_cc[VMIN] = 1;
268
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800269 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270}
271
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800272static void stdin_raw_restore() {
273 tcsetattr(STDIN_FILENO, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274}
275#endif
276
David Pursell606835a2015-09-08 17:17:02 -0700277// Reads from |fd| and prints received data. If |use_shell_protocol| is true
278// this expects that incoming data will use the shell protocol, in which case
279// stdout/stderr are routed independently and the remote exit code will be
280// returned.
281static int read_and_dump(int fd, bool use_shell_protocol=false) {
282 int exit_code = 0;
283 std::unique_ptr<ShellProtocol> protocol;
284 int length = 0;
285 FILE* outfile = stdout;
286
287 char raw_buffer[BUFSIZ];
288 char* buffer_ptr = raw_buffer;
289 if (use_shell_protocol) {
290 protocol.reset(new ShellProtocol(fd));
291 if (!protocol) {
292 LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
293 return 1;
294 }
295 buffer_ptr = protocol->data();
296 }
297
Elliott Hughes5677c232015-05-07 23:37:40 -0700298 while (fd >= 0) {
David Pursell606835a2015-09-08 17:17:02 -0700299 if (use_shell_protocol) {
300 if (!protocol->Read()) {
301 break;
302 }
303 switch (protocol->id()) {
304 case ShellProtocol::kIdStdout:
305 outfile = stdout;
306 break;
307 case ShellProtocol::kIdStderr:
308 outfile = stderr;
309 break;
310 case ShellProtocol::kIdExit:
311 exit_code = protocol->data()[0];
312 continue;
313 default:
314 continue;
315 }
316 length = protocol->data_length();
317 } else {
318 D("read_and_dump(): pre adb_read(fd=%d)", fd);
319 length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
320 D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
321 if (length <= 0) {
322 break;
323 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800324 }
325
David Pursell606835a2015-09-08 17:17:02 -0700326 fwrite(buffer_ptr, 1, length, outfile);
327 fflush(outfile);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800328 }
David Pursell606835a2015-09-08 17:17:02 -0700329
330 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800331}
332
Jeff Sharkey960df972014-06-09 17:30:57 -0700333static void read_status_line(int fd, char* buf, size_t count)
334{
335 count--;
336 while (count > 0) {
337 int len = adb_read(fd, buf, count);
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700338 if (len <= 0) {
Jeff Sharkey960df972014-06-09 17:30:57 -0700339 break;
340 }
341
342 buf += len;
343 count -= len;
344 }
345 *buf = '\0';
346}
347
Christopher Tated2f54152011-04-21 12:53:28 -0700348static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700349 const size_t BUFSIZE = 32 * 1024;
350 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700351 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700352 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700353 long total = 0;
Spencer Lowb7dfb792015-05-22 16:48:31 -0700354#ifdef _WIN32
355 int old_stdin_mode = -1;
356 int old_stdout_mode = -1;
357#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700358
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700359 D("copy_to_file(%d -> %d)", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800360
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700361 if (inFd == STDIN_FILENO) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800362 stdin_raw_init();
Spencer Lowb7dfb792015-05-22 16:48:31 -0700363#ifdef _WIN32
364 old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
365 if (old_stdin_mode == -1) {
366 fatal_errno("could not set stdin to binary");
367 }
368#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700369 }
Yabin Cuid325e862014-11-17 14:48:25 -0800370
Spencer Lowb7dfb792015-05-22 16:48:31 -0700371#ifdef _WIN32
372 if (outFd == STDOUT_FILENO) {
373 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
374 if (old_stdout_mode == -1) {
375 fatal_errno("could not set stdout to binary");
376 }
377 }
378#endif
379
Elliott Hughesa7090b92015-04-17 17:03:59 -0700380 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700381 if (inFd == STDIN_FILENO) {
382 len = unix_read(inFd, buf, BUFSIZE);
383 } else {
384 len = adb_read(inFd, buf, BUFSIZE);
385 }
Christopher Tated2f54152011-04-21 12:53:28 -0700386 if (len == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700387 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tated2f54152011-04-21 12:53:28 -0700388 break;
389 }
390 if (len < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700391 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tated2f54152011-04-21 12:53:28 -0700392 break;
393 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700394 if (outFd == STDOUT_FILENO) {
395 fwrite(buf, 1, len, stdout);
396 fflush(stdout);
397 } else {
398 adb_write(outFd, buf, len);
399 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700400 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700401 }
Yabin Cuid325e862014-11-17 14:48:25 -0800402
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700403 if (inFd == STDIN_FILENO) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800404 stdin_raw_restore();
Spencer Lowb7dfb792015-05-22 16:48:31 -0700405#ifdef _WIN32
406 if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
407 fatal_errno("could not restore stdin mode");
408 }
409#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700410 }
Yabin Cuid325e862014-11-17 14:48:25 -0800411
Spencer Lowb7dfb792015-05-22 16:48:31 -0700412#ifdef _WIN32
413 if (outFd == STDOUT_FILENO) {
414 if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
415 fatal_errno("could not restore stdout mode");
416 }
417 }
418#endif
419
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700420 D("copy_to_file() finished after %lu bytes", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700421 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700422}
423
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800424static std::string format_host_command(const char* command,
425 TransportType type, const char* serial) {
426 if (serial) {
427 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
428 }
429
430 const char* prefix = "host";
431 if (type == kTransportUsb) {
432 prefix = "host-usb";
433 } else if (type == kTransportLocal) {
434 prefix = "host-local";
435 }
436 return android::base::StringPrintf("%s:%s", prefix, command);
437}
438
439// Returns the FeatureSet for the indicated transport.
440static FeatureSet GetFeatureSet(TransportType transport_type, const char* serial) {
441 std::string result, error;
442 if (adb_query(format_host_command("features", transport_type, serial), &result, &error)) {
443 return StringToFeatureSet(result);
444 }
445 return FeatureSet();
446}
447
448static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) {
449#if !defined(_WIN32)
450 // Old devices can't handle window size changes.
451 if (shell == nullptr) return;
452
453 winsize ws;
454 if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return;
455
456 // Send the new window size as human-readable ASCII for debugging convenience.
457 size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d",
458 ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel);
459 shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1);
460#endif
461}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462
David Pursell606835a2015-09-08 17:17:02 -0700463// Used to pass multiple values to the stdin read thread.
464struct StdinReadArgs {
465 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700466 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700467 std::unique_ptr<ShellProtocol> protocol;
468};
469
David Pursell606835a2015-09-08 17:17:02 -0700470// Loops to read from stdin and push the data to the given FD.
471// The argument should be a pointer to a StdinReadArgs object. This function
472// will take ownership of the object and delete it when finished.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800473static void* stdin_read_thread_loop(void* x) {
David Pursell606835a2015-09-08 17:17:02 -0700474 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
475 int state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800476
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800477#if !defined(_WIN32)
478 // Mask SIGTTIN in case we're in a backgrounded process.
Josh Gao8dcdb572015-10-23 15:03:31 -0700479 sigset_t sigset;
480 sigemptyset(&sigset);
481 sigaddset(&sigset, SIGTTIN);
482 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
483#endif
484
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800485#if !defined(_WIN32)
486 // Unblock SIGWINCH for this thread, so our read(2) below will be
487 // interrupted if the window size changes.
488 sigset_t mask;
489 sigemptyset(&mask);
490 sigaddset(&mask, SIGWINCH);
491 pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
492#endif
493
494 // Set up the initial window size.
495 send_window_size_change(args->stdin_fd, args->protocol);
496
David Pursell606835a2015-09-08 17:17:02 -0700497 char raw_buffer[1024];
498 char* buffer_ptr = raw_buffer;
499 size_t buffer_size = sizeof(raw_buffer);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800500 if (args->protocol != nullptr) {
David Pursell606835a2015-09-08 17:17:02 -0700501 buffer_ptr = args->protocol->data();
502 buffer_size = args->protocol->data_capacity();
503 }
504
Elliott Hughesaa245492015-08-03 10:38:08 -0700505 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700506 // Use unix_read() rather than adb_read() for stdin.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800507 D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd);
508#if !defined(_WIN32)
509#undef read
510 int r = read(args->stdin_fd, buffer_ptr, buffer_size);
511 if (r == -1 && errno == EINTR) {
512 send_window_size_change(args->stdin_fd, args->protocol);
513 continue;
514 }
515#define read ___xxx_read
516#else
David Pursell606835a2015-09-08 17:17:02 -0700517 int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800518#endif
519 D("stdin_read_thread_loop(): post unix_read(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700520 if (r <= 0) {
521 // Only devices using the shell protocol know to close subprocess
522 // stdin. For older devices we want to just leave the connection
523 // open, otherwise an unpredictable amount of return data could
524 // be lost due to the FD closing before all data has been received.
525 if (args->protocol) {
526 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
527 }
528 break;
529 }
530 // If we made stdin raw, check input for the "~." escape sequence. In
531 // this situation signals like Ctrl+C are sent remotely rather than
532 // interpreted locally so this provides an emergency out if the remote
533 // process starts ignoring the signal. SSH also does this, see the
534 // "escape characters" section on the ssh man page for more info.
535 if (args->raw_stdin) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800536 for (int n = 0; n < r; n++) {
537 switch (buffer_ptr[n]) {
David Pursell1ed57f02015-10-06 15:30:03 -0700538 case '\n':
539 state = 1;
540 break;
541 case '\r':
542 state = 1;
543 break;
544 case '~':
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800545 if (state == 1) {
David Pursell08a27092015-10-20 14:19:36 -0700546 state++;
547 } else {
548 state = 0;
549 }
David Pursell1ed57f02015-10-06 15:30:03 -0700550 break;
551 case '.':
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800552 if (state == 2) {
553 fprintf(stderr,"\r\n* disconnect *\r\n");
554 stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700555 exit(0);
556 }
557 default:
558 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800559 }
560 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800561 }
David Pursell606835a2015-09-08 17:17:02 -0700562 if (args->protocol) {
563 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
564 break;
565 }
566 } else {
567 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
568 break;
569 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800570 }
571 }
David Pursell606835a2015-09-08 17:17:02 -0700572
573 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800574}
575
David Pursell1ed57f02015-10-06 15:30:03 -0700576// Returns a shell service string with the indicated arguments and command.
577static std::string ShellServiceString(bool use_shell_protocol,
578 const std::string& type_arg,
579 const std::string& command) {
580 std::vector<std::string> args;
581 if (use_shell_protocol) {
582 args.push_back(kShellServiceArgShellProtocol);
583 }
584 if (!type_arg.empty()) {
585 args.push_back(type_arg);
586 }
587
588 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
589 return android::base::StringPrintf("shell%s%s:%s",
590 args.empty() ? "" : ",",
591 android::base::Join(args, ',').c_str(),
592 command.c_str());
593}
594
595// Connects to a shell on the device and read/writes data.
596//
597// Note: currently this function doesn't properly clean up resources; the
598// FD connected to the adb server is never closed and the stdin read thread
599// may never exit.
600//
601// On success returns the remote exit code if |use_shell_protocol| is true,
602// 0 otherwise. On failure returns 1.
603static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
604 const std::string& command) {
605 std::string service_string = ShellServiceString(use_shell_protocol,
606 type_arg, command);
607
608 // Make local stdin raw if the device allocates a PTY, which happens if:
609 // 1. We are explicitly asking for a PTY shell, or
610 // 2. We don't specify shell type and are starting an interactive session.
611 bool raw_stdin = (type_arg == kShellServiceArgPty ||
612 (type_arg.empty() && command.empty()));
613
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700614 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700615 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700616 if (fd < 0) {
617 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800618 return 1;
619 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800620
David Pursell606835a2015-09-08 17:17:02 -0700621 StdinReadArgs* args = new StdinReadArgs;
622 if (!args) {
623 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700624 return 1;
625 }
David Pursell1ed57f02015-10-06 15:30:03 -0700626 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700627 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700628 args->raw_stdin = raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700629 if (use_shell_protocol) {
630 args->protocol.reset(new ShellProtocol(args->write_fd));
631 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700632
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800633 if (raw_stdin) stdin_raw_init();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800634
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800635#if !defined(_WIN32)
636 // Ensure our process is notified if the local window size changes.
637 // We use sigaction(2) to ensure that the SA_RESTART flag is not set,
638 // because the whole reason we're sending signals is to unblock the read(2)!
639 // That also means we don't need to do anything in the signal handler:
640 // the side effect of delivering the signal is all we need.
641 struct sigaction sa;
642 memset(&sa, 0, sizeof(sa));
643 sa.sa_handler = [](int) {};
644 sa.sa_flags = 0;
645 sigaction(SIGWINCH, &sa, nullptr);
646
647 // Now block SIGWINCH in this thread (the main thread) and all threads spawned
648 // from it. The stdin read thread will unblock this signal to ensure that it's
649 // the thread that receives the signal.
650 sigset_t mask;
651 sigemptyset(&mask);
652 sigaddset(&mask, SIGWINCH);
653 pthread_sigmask(SIG_BLOCK, &mask, nullptr);
654#endif
655
656 // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
657 int exit_code = 1;
658 if (!adb_thread_create(stdin_read_thread_loop, args)) {
David Pursell606835a2015-09-08 17:17:02 -0700659 PLOG(ERROR) << "error starting stdin read thread";
David Pursell606835a2015-09-08 17:17:02 -0700660 delete args;
661 } else {
662 exit_code = read_and_dump(fd, use_shell_protocol);
663 }
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700664
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800665 // TODO: properly exit stdin_read_thread_loop and close |fd|.
David Pursell1ed57f02015-10-06 15:30:03 -0700666
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800667 // TODO: we should probably install signal handlers for this.
668 // TODO: can we use atexit? even on Windows?
669 if (raw_stdin) stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700670
David Pursell606835a2015-09-08 17:17:02 -0700671 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800672}
673
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800674static int adb_shell(int argc, const char** argv,
675 TransportType transport_type, const char* serial) {
676 FeatureSet features = GetFeatureSet(transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800677
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800678 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2);
679 if (!use_shell_protocol) {
680 D("shell protocol not supported, using raw data transfer");
681 } else {
682 D("using shell protocol");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800683 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700684
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800685 // Parse shell-specific command-line options.
686 // argv[0] is always "shell".
687 --argc;
688 ++argv;
689 int t_arg_count = 0;
690 while (argc) {
691 if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
692 if (!CanUseFeature(features, kFeatureShell2)) {
693 fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
694 return 1;
695 }
696 // Like ssh, -t arguments are cumulative so that multiple -t's
697 // are needed to force a PTY.
698 if (argv[0][1] == 't') {
699 ++t_arg_count;
700 } else {
701 t_arg_count = -1;
702 }
703 --argc;
704 ++argv;
705 } else if (!strcmp(argv[0], "-x")) {
706 use_shell_protocol = false;
707 --argc;
708 ++argv;
709 } else {
710 break;
711 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700712 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800714 std::string shell_type_arg;
715 if (CanUseFeature(features, kFeatureShell2)) {
716 if (t_arg_count < 0) {
717 shell_type_arg = kShellServiceArgRaw;
718 } else if (t_arg_count == 0) {
719 // If stdin isn't a TTY, default to a raw shell; this lets
720 // things like `adb shell < my_script.sh` work as expected.
721 // Otherwise leave |shell_type_arg| blank which uses PTY for
722 // interactive shells and raw for non-interactive.
723 if (!unix_isatty(STDIN_FILENO)) {
724 shell_type_arg = kShellServiceArgRaw;
725 }
726 } else if (t_arg_count == 1) {
727 // A single -t arg isn't enough to override implicit -T.
728 if (!unix_isatty(STDIN_FILENO)) {
729 fprintf(stderr,
730 "Remote PTY will not be allocated because stdin is not a terminal.\n"
731 "Use multiple -t options to force remote PTY allocation.\n");
732 shell_type_arg = kShellServiceArgRaw;
733 } else {
734 shell_type_arg = kShellServiceArgPty;
735 }
736 } else {
737 shell_type_arg = kShellServiceArgPty;
738 }
David Pursell71c83122015-09-14 15:33:50 -0700739 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800740
741 std::string command;
742 if (argc) {
743 // We don't escape here, just like ssh(1). http://b/20564385.
744 command = android::base::Join(std::vector<const char*>(argv, argv + argc), ' ');
745 }
746
747 return RemoteShell(use_shell_protocol, shell_type_arg, command);
David Pursell71c83122015-09-14 15:33:50 -0700748}
749
Elliott Hughes6452a892015-04-29 12:28:13 -0700750static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700751 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800752{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700753 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700754 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700755 if (fd < 0) {
756 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800757 return -1;
758 }
759
760 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800761 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800762
Elliott Hughes6452a892015-04-29 12:28:13 -0700763 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800764 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800765
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700766 if (show_progress) {
Elliott Hughes3e7048c2015-07-27 21:21:39 -0700767 const char* x = strrchr(service, ':');
768 if (x) service = x + 1;
Doug Zongker447f0612012-01-09 14:54:53 -0800769 }
770
Elliott Hughes6452a892015-04-29 12:28:13 -0700771 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800772 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700773 if (!WriteFdExactly(fd, ptr, xfer)) {
774 std::string error;
775 adb_status(fd, &error);
776 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700777 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800778 return -1;
779 }
780 sz -= xfer;
781 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700782 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100783 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800784 fflush(stdout);
785 }
786 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700787 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800788 printf("\n");
789 }
790
Elliott Hughese67f1f82015-04-30 17:32:03 -0700791 if (!adb_status(fd, &error)) {
792 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700793 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800794 return -1;
795 }
796
797 adb_close(fd);
798 return 0;
799}
800
Doug Zongker71fe5842014-06-26 15:35:36 -0700801#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
802
803/*
804 * The sideload-host protocol serves the data in a file (given on the
805 * command line) to the client, using a simple protocol:
806 *
807 * - The connect message includes the total number of bytes in the
808 * file and a block size chosen by us.
809 *
810 * - The other side sends the desired block number as eight decimal
811 * digits (eg "00000023" for block 23). Blocks are numbered from
812 * zero.
813 *
814 * - We send back the data of the requested block. The last block is
815 * likely to be partial; when the last block is requested we only
816 * send the part of the block that exists, it's not padded up to the
817 * block size.
818 *
819 * - When the other side sends "DONEDONE" instead of a block number,
820 * we hang up.
821 */
Elliott Hughes58305772015-04-17 13:57:15 -0700822static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700823 unsigned sz;
824 size_t xfer = 0;
825 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800826 int last_percent = -1;
827 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700828
829 printf("loading: '%s'", fn);
830 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800831 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700832 if (data == 0) {
833 printf("\n");
834 fprintf(stderr, "* cannot read '%s' *\n", fn);
835 return -1;
836 }
837
Elliott Hughes6452a892015-04-29 12:28:13 -0700838 std::string service =
839 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700840 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700841 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700842 if (fd < 0) {
843 // Try falling back to the older sideload method. Maybe this
844 // is an older device that doesn't support sideload-host.
845 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700846 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700847 goto done;
848 }
849
Spencer Lowf055c192015-01-25 14:40:16 -0800850 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700851
Elliott Hughesa7090b92015-04-17 17:03:59 -0700852 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700853 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800854 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700855 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700856 status = -1;
857 goto done;
858 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700859 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700860
Elliott Hughes6452a892015-04-29 12:28:13 -0700861 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700862 status = 0;
863 break;
864 }
865
Doug Zongker71fe5842014-06-26 15:35:36 -0700866 int block = strtol(buf, NULL, 10);
867
868 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
869 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700870 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700871 status = -1;
872 goto done;
873 }
874 uint8_t* start = data + offset;
875 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
876 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
877 if (offset_end > sz) {
878 to_write = sz - offset;
879 }
880
Dan Albertcc731cc2015-02-24 21:26:58 -0800881 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700882 adb_status(fd, &error);
883 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700884 status = -1;
885 goto done;
886 }
887 xfer += to_write;
888
889 // For normal OTA packages, we expect to transfer every byte
890 // twice, plus a bit of overhead (one read during
891 // verification, one read of each byte for installation, plus
892 // extra access to things like the zip central directory).
893 // This estimate of the completion becomes 100% when we've
894 // transferred ~2.13 (=100/47) times the package size.
895 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
896 if (percent != last_percent) {
897 printf("\rserving: '%s' (~%d%%) ", fn, percent);
898 fflush(stdout);
899 last_percent = percent;
900 }
901 }
902
Colin Cross6d6a8982014-07-07 14:12:41 -0700903 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700904
905 done:
906 if (fd >= 0) adb_close(fd);
907 free(data);
908 return status;
909}
910
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800911/**
912 * Run ppp in "notty" mode against a resource listed as the first parameter
913 * eg:
914 *
915 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
916 *
917 */
Elliott Hughes58305772015-04-17 13:57:15 -0700918static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800919#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800920 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
921 return -1;
922#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800923 if (argc < 2) {
924 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
925 argv[0]);
926
927 return 1;
928 }
929
Dan Albertbac34742015-02-25 17:51:28 -0800930 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700931 std::string error;
932 int fd = adb_connect(adb_service_name, &error);
933 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800934 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700935 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800936 return 1;
937 }
938
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700939 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800940
941 if (pid < 0) {
942 perror("from fork()");
943 return 1;
944 } else if (pid == 0) {
945 int err;
946 int i;
947 const char **ppp_args;
948
949 // copy args
950 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
951 ppp_args[0] = "pppd";
952 for (i = 2 ; i < argc ; i++) {
953 //argv[2] and beyond become ppp_args[1] and beyond
954 ppp_args[i - 1] = argv[i];
955 }
956 ppp_args[i-1] = NULL;
957
958 // child side
959
960 dup2(fd, STDIN_FILENO);
961 dup2(fd, STDOUT_FILENO);
962 adb_close(STDERR_FILENO);
963 adb_close(fd);
964
965 err = execvp("pppd", (char * const *)ppp_args);
966
967 if (err < 0) {
968 perror("execing pppd");
969 }
970 exit(-1);
971 } else {
972 // parent side
973
974 adb_close(fd);
975 return 0;
976 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800977#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800978}
979
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700980static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700981 // Was the caller vague about what they'd like us to wait for?
982 // If so, check they weren't more specific in their choice of transport type.
983 if (strcmp(service, "wait-for-device") == 0) {
984 if (t == kTransportUsb) {
985 service = "wait-for-usb";
986 } else if (t == kTransportLocal) {
987 service = "wait-for-local";
988 } else {
989 service = "wait-for-any";
990 }
991 }
992
993 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700994 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700995}
996
David Pursell70ef7b42015-09-30 13:35:42 -0700997// Connects to the device "shell" service with |command| and prints the
998// resulting output.
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700999static int send_shell_command(TransportType transport_type, const char* serial,
David Pursell70ef7b42015-09-30 13:35:42 -07001000 const std::string& command,
1001 bool disable_shell_protocol) {
1002 // Only use shell protocol if it's supported and the caller doesn't want
1003 // to explicitly disable it.
1004 bool use_shell_protocol = false;
1005 if (!disable_shell_protocol) {
1006 FeatureSet features = GetFeatureSet(transport_type, serial);
1007 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
1008 }
1009
1010 std::string service_string = ShellServiceString(use_shell_protocol, "",
1011 command);
1012
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001013 int fd;
1014 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001015 std::string error;
David Pursell70ef7b42015-09-30 13:35:42 -07001016 fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001017 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001019 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001020 fprintf(stderr,"- waiting for device -\n");
1021 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -07001022 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 }
1024
David Pursell70ef7b42015-09-30 13:35:42 -07001025 int exit_code = read_and_dump(fd, use_shell_protocol);
David Pursell71c83122015-09-14 15:33:50 -07001026
1027 if (adb_close(fd) < 0) {
1028 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001029 }
David Pursell71c83122015-09-14 15:33:50 -07001030
1031 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001032}
1033
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001034static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001035 char* log_tags = getenv("ANDROID_LOG_TAGS");
1036 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001037
David Pursell70ef7b42015-09-30 13:35:42 -07001038 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001039
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001040 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001041 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -08001042 }
1043
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001044 --argc;
1045 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001046 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001047 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001048 }
1049
David Pursell70ef7b42015-09-30 13:35:42 -07001050 // No need for shell protocol with logcat, always disable for simplicity.
1051 return send_shell_command(transport, serial, cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001052}
1053
Dan Albertbac34742015-02-25 17:51:28 -08001054static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -07001055 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -07001056
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001057 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001058 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001059 if (!strcmp("-f", argv[i])) {
1060 if (i == argc-1) {
1061 fprintf(stderr, "adb: -f passed with no filename\n");
1062 return usage();
1063 }
1064 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001065 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001066 argv[i++] = argv[j++];
1067 }
1068 argc -= 2;
1069 argv[argc] = NULL;
1070 }
Christopher Tated2f54152011-04-21 12:53:28 -07001071 }
1072
Christopher Tatebb86bc52011-08-22 17:12:08 -07001073 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
1074 if (argc < 2) return usage();
1075
Christopher Tateb1dfffe2011-12-08 19:04:34 -08001076 adb_unlink(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001077 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -07001078 if (outFd < 0) {
1079 fprintf(stderr, "adb: unable to open file %s\n", filename);
1080 return -1;
1081 }
1082
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001083 std::string cmd = "backup:";
1084 --argc;
1085 ++argv;
1086 while (argc-- > 0) {
1087 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -07001088 }
1089
Yabin Cui7a3f8d62015-09-02 17:44:28 -07001090 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001091 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001092 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -07001093 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001094 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -07001095 adb_close(outFd);
1096 return -1;
1097 }
1098
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001099 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -07001100 copy_to_file(fd, outFd);
1101
1102 adb_close(fd);
1103 adb_close(outFd);
1104 return 0;
1105}
1106
Dan Albertbac34742015-02-25 17:51:28 -08001107static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -07001108 if (argc != 2) return usage();
1109
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001110 const char* filename = argv[1];
1111 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -07001112 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001113 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -07001114 return -1;
1115 }
1116
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001117 std::string error;
1118 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -07001119 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001120 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -07001121 adb_close(tarFd);
1122 return -1;
1123 }
1124
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001125 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -07001126 copy_to_file(tarFd, fd);
1127
1128 adb_close(fd);
1129 adb_close(tarFd);
1130 return 0;
1131}
1132
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133/* <hint> may be:
1134 * - A simple product name
1135 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001136 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1137 * e.g., "out/target/product/sooner"
1138 * - An absolute path to the PRODUCT_OUT dir
1139 * e.g., "/src/device/out/target/product/sooner"
1140 *
1141 * Given <hint>, try to construct an absolute path to the
1142 * ANDROID_PRODUCT_OUT dir.
1143 */
Elliott Hughes5c742702015-07-30 17:42:01 -07001144static std::string find_product_out_path(const std::string& hint) {
1145 if (hint.empty()) {
Elliott Hughes58305772015-04-17 13:57:15 -07001146 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001147 }
1148
Elliott Hughes58305772015-04-17 13:57:15 -07001149 // If it's already absolute, don't bother doing any work.
Elliott Hughes5c742702015-07-30 17:42:01 -07001150 if (adb_is_absolute_host_path(hint.c_str())) {
Elliott Hughes58305772015-04-17 13:57:15 -07001151 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001152 }
1153
Elliott Hughes58305772015-04-17 13:57:15 -07001154 // If there are any slashes in it, assume it's a relative path;
1155 // make it absolute.
Elliott Hughes5c742702015-07-30 17:42:01 -07001156 if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001157 std::string cwd;
1158 if (!getcwd(&cwd)) {
1159 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -07001160 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001161 }
Elliott Hughes5c742702015-07-30 17:42:01 -07001162 return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 }
1164
Elliott Hughes58305772015-04-17 13:57:15 -07001165 // It's a string without any slashes. Try to do something with it.
1166 //
1167 // Try to find the root of the build tree, and build a PRODUCT_OUT
1168 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -07001169 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -07001170 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001171 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -07001172 return "";
1173 }
Elliott Hughesa7090b92015-04-17 17:03:59 -07001174
1175 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -07001176 path += OS_PATH_SEPARATOR_STR;
1177 path += "out";
1178 path += OS_PATH_SEPARATOR_STR;
1179 path += "target";
1180 path += OS_PATH_SEPARATOR_STR;
1181 path += "product";
1182 path += OS_PATH_SEPARATOR_STR;
1183 path += hint;
1184 if (!directory_exists(path)) {
1185 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
Elliott Hughes5c742702015-07-30 17:42:01 -07001186 "\"%s\" doesn't exist\n", hint.c_str(), path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -07001187 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001188 }
Elliott Hughes58305772015-04-17 13:57:15 -07001189 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001190}
1191
Josh Gao05786772015-10-30 16:57:19 -07001192static void parse_push_pull_args(const char** arg, int narg,
1193 std::vector<const char*>* srcs,
1194 const char** dst, bool* copy_attrs) {
1195 *copy_attrs = false;
Mark Lindner76f2a932014-03-11 17:55:59 -07001196
Josh Gao05786772015-10-30 16:57:19 -07001197 srcs->clear();
1198 bool ignore_flags = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001199 while (narg > 0) {
Josh Gao05786772015-10-30 16:57:19 -07001200 if (ignore_flags || *arg[0] != '-') {
1201 srcs->push_back(*arg);
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001202 } else {
Josh Gao05786772015-10-30 16:57:19 -07001203 if (!strcmp(*arg, "-p")) {
1204 // Silently ignore for backwards compatibility.
1205 } else if (!strcmp(*arg, "-a")) {
1206 *copy_attrs = true;
1207 } else if (!strcmp(*arg, "--")) {
1208 ignore_flags = true;
1209 } else {
1210 fprintf(stderr, "adb: unrecognized option '%s'\n", *arg);
1211 exit(1);
1212 }
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001213 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001214 ++arg;
1215 --narg;
1216 }
1217
Josh Gao05786772015-10-30 16:57:19 -07001218 if (srcs->size() > 1) {
1219 *dst = srcs->back();
1220 srcs->pop_back();
Mark Lindner76f2a932014-03-11 17:55:59 -07001221 }
1222}
1223
Elliott Hughes6452a892015-04-29 12:28:13 -07001224static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001225 std::string error;
1226 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001227 if (fd < 0) {
1228 fprintf(stderr, "error: %s\n", error.c_str());
1229 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001230 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001231 read_and_dump(fd);
1232 adb_close(fd);
1233 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001234}
1235
Elliott Hughes6452a892015-04-29 12:28:13 -07001236static int adb_query_command(const std::string& command) {
1237 std::string result;
1238 std::string error;
1239 if (!adb_query(command, &result, &error)) {
1240 fprintf(stderr, "error: %s\n", error.c_str());
1241 return 1;
1242 }
1243 printf("%s\n", result.c_str());
1244 return 0;
1245}
1246
Spencer Lowa13df302015-09-07 16:20:13 -07001247// Disallow stdin, stdout, and stderr.
1248static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1249#ifdef _WIN32
1250 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1251 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1252 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1253 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1254#else
1255 return ack_reply_fd > 2;
1256#endif
1257}
1258
Elliott Hughesab52c182015-05-01 17:04:38 -07001259int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001260 int no_daemon = 0;
1261 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001262 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001264 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001265 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001266
Elliott Hughes58305772015-04-17 13:57:15 -07001267 // If defined, this should be an absolute path to
1268 // the directory containing all of the various system images
1269 // for a particular product. If not defined, and the adb
1270 // command requires this information, then the user must
1271 // specify the path using "-p".
1272 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1273 if (ANDROID_PRODUCT_OUT != nullptr) {
1274 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001275 }
1276 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1277
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001278 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001279 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001280 int server_port = DEFAULT_ADB_PORT;
1281 if (server_port_str && strlen(server_port_str) > 0) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001282 server_port = strtol(server_port_str, nullptr, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001283 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001284 fprintf(stderr,
Spencer Lowf18fc082015-08-11 17:05:02 -07001285 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65536. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001286 server_port_str);
1287 return usage();
1288 }
1289 }
1290
Elliott Hughes8d28e192015-10-07 14:55:10 -07001291 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1292 const char* serial = nullptr;
1293
Riley Andrews98f58e82014-12-05 17:37:24 -08001294 while (argc > 0) {
1295 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001296 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001297 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001298 no_daemon = 1;
1299 } else if (!strcmp(argv[0], "fork-server")) {
1300 /* this is a special flag used only when the ADB client launches the ADB Server */
1301 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001302 } else if (!strcmp(argv[0], "--reply-fd")) {
1303 if (argc < 2) return usage();
1304 const char* reply_fd_str = argv[1];
1305 argc--;
1306 argv++;
1307 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001308 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001309 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
1310 return usage();
1311 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001312 } else if (!strncmp(argv[0], "-p", 2)) {
Elliott Hughes048b27c2015-07-31 13:18:22 -07001313 const char* product = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001314 if (argv[0][2] == '\0') {
1315 if (argc < 2) return usage();
1316 product = argv[1];
1317 argc--;
1318 argv++;
1319 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001320 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001321 }
Elliott Hughes048b27c2015-07-31 13:18:22 -07001322 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001323 if (gProductOutPath.empty()) {
1324 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001325 return usage();
1326 }
1327 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1328 if (isdigit(argv[0][2])) {
1329 serial = argv[0] + 2;
1330 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001331 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001332 serial = argv[1];
1333 argc--;
1334 argv++;
1335 }
1336 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001337 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001338 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001339 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001340 } else if (!strcmp(argv[0],"-a")) {
1341 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001342 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001343 const char *hostname = NULL;
1344 if (argv[0][2] == '\0') {
1345 if (argc < 2) return usage();
1346 hostname = argv[1];
1347 argc--;
1348 argv++;
1349 } else {
1350 hostname = argv[0] + 2;
1351 }
1352 adb_set_tcp_name(hostname);
1353
Riley Andrews98f58e82014-12-05 17:37:24 -08001354 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001355 if (argv[0][2] == '\0') {
1356 if (argc < 2) return usage();
1357 server_port_str = argv[1];
1358 argc--;
1359 argv++;
1360 } else {
1361 server_port_str = argv[0] + 2;
1362 }
1363 if (strlen(server_port_str) > 0) {
1364 server_port = (int) strtol(server_port_str, NULL, 0);
1365 if (server_port <= 0 || server_port > 65535) {
1366 fprintf(stderr,
1367 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1368 server_port_str);
1369 return usage();
1370 }
1371 } else {
1372 fprintf(stderr,
1373 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1374 return usage();
1375 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001376 } else {
1377 /* out of recognized modifiers and flags */
1378 break;
1379 }
1380 argc--;
1381 argv++;
1382 }
1383
Elliott Hughes8d28e192015-10-07 14:55:10 -07001384 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1385 if (transport_type == kTransportAny && serial == nullptr) {
1386 serial = getenv("ANDROID_SERIAL");
1387 }
1388
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001389 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001390 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001391
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001392 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001393 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001394 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001395 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
1396 return usage();
1397 }
1398 r = adb_main(is_daemon, server_port, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001399 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001400 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001401 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001402 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 fprintf(stderr,"* could not start server *\n");
1404 }
1405 return r;
1406 }
1407
Riley Andrews98f58e82014-12-05 17:37:24 -08001408 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001409 return usage();
1410 }
1411
Riley Andrewsc8514c82014-12-05 17:32:46 -08001412 /* handle wait-for-* prefix */
1413 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001414 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001415
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001416 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001417 return 1;
1418 }
1419
Elliott Hughes2b101112015-05-04 19:29:32 -07001420 // Allow a command to be run after wait-for-device,
1421 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001422 if (argc == 1) {
1423 return 0;
1424 }
1425
1426 /* Fall through */
1427 argc--;
1428 argv++;
1429 }
1430
1431 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001432 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001433 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001434 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001435 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001436 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001437 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001438 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001439 fprintf(stderr, "Usage: adb devices [-l]\n");
1440 return 1;
1441 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001442
1443 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1444 printf("List of devices attached\n");
1445 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001446 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001447 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001448 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001449 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001450 return 1;
1451 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001452
1453 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1454 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001455 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001456 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001457 if (argc > 2) {
1458 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1459 return 1;
1460 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001461
1462 std::string query = android::base::StringPrintf("host:disconnect:%s",
1463 (argc == 2) ? argv[1] : "");
1464 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001465 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001466 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001467 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001468 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -08001469 else if (!strcmp(argv[0], "shell")) {
1470 return adb_shell(argc, argv, transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001471 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001472 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001473 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001474
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001475 std::string cmd = "exec:";
1476 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001477 argc -= 2;
1478 argv += 2;
1479 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001480 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001481 }
1482
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001483 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001484 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001485 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001486 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001487 return -1;
1488 }
1489
1490 if (exec_in) {
1491 copy_to_file(STDIN_FILENO, fd);
1492 } else {
1493 copy_to_file(fd, STDOUT_FILENO);
1494 }
1495
1496 adb_close(fd);
1497 return 0;
1498 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001499 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001500 std::string error;
1501 int fd = _adb_connect("host:kill", &error);
Spencer Lowf18fc082015-08-11 17:05:02 -07001502 if (fd == -2) {
1503 // Failed to make network connection to server. Don't output the
1504 // network error since that is expected.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001505 fprintf(stderr,"* server not running *\n");
Spencer Lowf18fc082015-08-11 17:05:02 -07001506 // Successful exit code because the server is already "killed".
1507 return 0;
1508 } else if (fd == -1) {
1509 // Some other error.
1510 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001511 return 1;
Spencer Lowf18fc082015-08-11 17:05:02 -07001512 } else {
1513 // Successfully connected, kill command sent, okay status came back.
1514 // Server should exit() in a moment, if not already.
Spencer Low351ecd12015-10-14 17:32:44 -07001515 ReadOrderlyShutdown(fd);
Spencer Lowf18fc082015-08-11 17:05:02 -07001516 adb_close(fd);
1517 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001518 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001519 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001520 else if (!strcmp(argv[0], "sideload")) {
1521 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001522 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001523 return 1;
1524 } else {
1525 return 0;
1526 }
1527 }
Elliott Hughes19d80b82015-07-21 16:13:40 -07001528 else if (!strcmp(argv[0], "tcpip") && argc > 1) {
1529 return adb_connect_command(android::base::StringPrintf("tcpip:%s", argv[1]));
1530 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001531 else if (!strcmp(argv[0], "remount") ||
1532 !strcmp(argv[0], "reboot") ||
1533 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001534 !strcmp(argv[0], "usb") ||
1535 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001536 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001537 !strcmp(argv[0], "disable-verity") ||
1538 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001539 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001540 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001541 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001542 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001543 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001544 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001545 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001546 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001547 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001548 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001549 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001550 if (argc != 1) return usage();
David Pursell70ef7b42015-09-30 13:35:42 -07001551 // No need for shell protocol with bugreport, always disable for
1552 // simplicity.
1553 return send_shell_command(transport_type, serial, "bugreport", true);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001554 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001555 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001556 bool reverse = !strcmp(argv[0], "reverse");
1557 ++argv;
1558 --argc;
1559 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001560
1561 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001562 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001563 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001564 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001565 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001566 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001567 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001568 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001569 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001570 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001571 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001572 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001573 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001574 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001575 }
1576
Elliott Hughes424af022015-05-29 17:55:19 -07001577 std::string cmd;
1578 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001579 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001580 return adb_query_command(host_prefix + ":list-forward");
1581 } else if (strcmp(argv[0], "--remove-all") == 0) {
1582 if (argc != 1) return usage();
1583 cmd = host_prefix + ":killforward-all";
1584 } else if (strcmp(argv[0], "--remove") == 0) {
1585 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001586 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001587 cmd = host_prefix + ":killforward:" + argv[1];
1588 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1589 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001590 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001591 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1592 } else {
1593 // forward <local> <remote>
1594 if (argc != 2) return usage();
1595 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001596 }
1597
Elliott Hughes424af022015-05-29 17:55:19 -07001598 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001599 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001600 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001601 else if (!strcmp(argv[0], "ls")) {
1602 if (argc != 2) return usage();
Elliott Hughesaa245492015-08-03 10:38:08 -07001603 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001604 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001605 else if (!strcmp(argv[0], "push")) {
Josh Gao05786772015-10-30 16:57:19 -07001606 bool copy_attrs = false;
1607 std::vector<const char*> srcs;
1608 const char* dst = nullptr;
Mark Lindner76f2a932014-03-11 17:55:59 -07001609
Josh Gao05786772015-10-30 16:57:19 -07001610 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1611 if (srcs.empty() || !dst) return usage();
1612 return do_sync_push(srcs, dst) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001613 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001614 else if (!strcmp(argv[0], "pull")) {
Josh Gao05786772015-10-30 16:57:19 -07001615 bool copy_attrs = false;
1616 std::vector<const char*> srcs;
1617 const char* dst = ".";
Mark Lindner76f2a932014-03-11 17:55:59 -07001618
Josh Gao05786772015-10-30 16:57:19 -07001619 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1620 if (srcs.empty()) return usage();
1621 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001622 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001623 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624 if (argc < 2) return usage();
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001625 return install_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001626 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001627 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001628 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001629 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001630 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001631 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001632 if (argc < 2) return usage();
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001633 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001634 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001635 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001636 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001637 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001638 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001639 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001640 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001641 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001642 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001643 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001644 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001645 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001646 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001647 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001648 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001649 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001650 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001651 } else {
1652 return usage();
1653 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001654
Elliott Hughesd236d072015-04-21 10:17:07 -07001655 if (src != "" &&
1656 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001657 return usage();
1658 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001659
Elliott Hughes58305772015-04-17 13:57:15 -07001660 std::string system_src_path = product_file("system");
1661 std::string data_src_path = product_file("data");
1662 std::string vendor_src_path = product_file("vendor");
1663 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001664
Elliott Hughesaa245492015-08-03 10:38:08 -07001665 bool okay = true;
1666 if (okay && (src.empty() || src == "system")) {
1667 okay = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001668 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001669 if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1670 okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001671 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001672 if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1673 okay = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001674 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001675 if (okay && (src.empty() || src == "data")) {
1676 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001677 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001678 return okay ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001679 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001681 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001682 !strcmp(argv[0],"get-serialno") ||
1683 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001684 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001685 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001686 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001688 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001689 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001691 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001692 return ppp(argc, argv);
1693 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001694 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001695 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001696 const int result = adb_connect("host:start-server", &error);
1697 if (result < 0) {
1698 fprintf(stderr, "error: %s\n", error.c_str());
1699 }
1700 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001701 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001703 return backup(argc, argv);
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001706 return restore(argc, argv);
1707 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001709 if (argc < 2) return usage();
Yabin Cuiaed3c612015-09-22 15:52:57 -07001710 // Always print key generation information for keygen command.
1711 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001712 return adb_auth_keygen(argv[1]);
1713 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001714 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001715 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001716 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001717 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001718 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001719 help();
1720 return 0;
1721 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001722 else if (!strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001723 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001724 return 0;
1725 }
Dan Albert90d4b732015-05-20 18:58:41 -07001726 else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001727 // Only list the features common to both the adb client and the device.
1728 FeatureSet features = GetFeatureSet(transport_type, serial);
1729 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001730 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001731 printf("%s\n", name.c_str());
1732 }
1733 }
1734 return 0;
Dan Albert90d4b732015-05-20 18:58:41 -07001735 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001736
1737 usage();
1738 return 1;
1739}
1740
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001741static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
1742 std::string cmd = "pm";
1743
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001744 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001745 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001746 }
1747
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001748 // TODO(dpursell): add command-line arguments to install/uninstall to
1749 // manually disable shell protocol if needed.
1750 return send_shell_command(transport, serial, cmd, false);
1751}
1752
1753static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
1754 /* if the user choose the -k option, we refuse to do it until devices are
1755 out with the option to uninstall the remaining data somehow (adb/ui) */
1756 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1757 {
1758 printf(
1759 "The -k option uninstalls the application while retaining the data/cache.\n"
1760 "At the moment, there is no way to remove the remaining data.\n"
1761 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1762 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1763 return -1;
1764 }
1765
1766 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1767 return pm_command(transport, serial, argc, argv);
1768}
1769
1770static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
1771 std::string cmd = "rm -f " + escape_arg(filename);
David Pursell70ef7b42015-09-30 13:35:42 -07001772 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001773}
1774
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001775static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001776 static const char *const DATA_DEST = "/data/local/tmp/%s";
1777 static const char *const SD_DEST = "/sdcard/tmp/%s";
1778 const char* where = DATA_DEST;
1779 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001780 struct stat sb;
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001781
1782 for (i = 1; i < argc; i++) {
1783 if (!strcmp(argv[i], "-s")) {
1784 where = SD_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001785 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001786 }
1787
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001788 // Find last APK argument.
1789 // All other arguments passed through verbatim.
1790 int last_apk = -1;
1791 for (i = argc - 1; i >= 0; i--) {
1792 const char* file = argv[i];
1793 const char* dot = strrchr(file, '.');
1794 if (dot && !strcasecmp(dot, ".apk")) {
1795 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1796 fprintf(stderr, "Invalid APK file: %s\n", file);
1797 return -1;
1798 }
1799
1800 last_apk = i;
1801 break;
1802 }
1803 }
1804
1805 if (last_apk == -1) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001806 fprintf(stderr, "Missing APK file\n");
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001807 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001808 }
1809
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001810 int result = -1;
1811 std::vector<const char*> apk_file = {argv[last_apk]};
1812 std::string apk_dest = android::base::StringPrintf(
1813 where, adb_basename(argv[last_apk]).c_str());
1814 if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
1815 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
1816 result = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001817
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001818cleanup_apk:
1819 delete_file(transport, serial, apk_dest);
1820 return result;
Jeff Sharkey960df972014-06-09 17:30:57 -07001821}
1822
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001823static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001824 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001825{
Jeff Sharkey960df972014-06-09 17:30:57 -07001826 int i;
1827 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001828 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001829
1830 // Find all APK arguments starting at end.
1831 // All other arguments passed through verbatim.
1832 int first_apk = -1;
1833 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001834 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001835 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001836 if (dot && !strcasecmp(dot, ".apk")) {
1837 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1838 fprintf(stderr, "Invalid APK file: %s\n", file);
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001839 return -1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001840 }
1841
1842 total_size += sb.st_size;
1843 first_apk = i;
1844 } else {
1845 break;
1846 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001847 }
1848
Jeff Sharkey960df972014-06-09 17:30:57 -07001849 if (first_apk == -1) {
1850 fprintf(stderr, "Missing APK file\n");
1851 return 1;
1852 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001853
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001854 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001855 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001856 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001857 }
1858
1859 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001860 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001861 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001862 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001863 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001864 return -1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001865 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001866 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001867 read_status_line(fd, buf, sizeof(buf));
1868 adb_close(fd);
1869
1870 int session_id = -1;
1871 if (!strncmp("Success", buf, 7)) {
1872 char* start = strrchr(buf, '[');
1873 char* end = strrchr(buf, ']');
1874 if (start && end) {
1875 *end = '\0';
1876 session_id = strtol(start + 1, NULL, 10);
1877 }
1878 }
1879 if (session_id < 0) {
1880 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001881 fputs(buf, stderr);
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001882 return -1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001883 }
1884
1885 // Valid session, now stream the APKs
1886 int success = 1;
1887 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001888 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001889 if (stat(file, &sb) == -1) {
1890 fprintf(stderr, "Failed to stat %s\n", file);
1891 success = 0;
1892 goto finalize_session;
1893 }
1894
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001895 std::string cmd = android::base::StringPrintf(
1896 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
Elliott Hughes5c742702015-07-30 17:42:01 -07001897 static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001898
1899 int localFd = adb_open(file, O_RDONLY);
1900 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001901 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001902 success = 0;
1903 goto finalize_session;
1904 }
1905
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001906 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001907 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001908 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001909 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001910 adb_close(localFd);
1911 success = 0;
1912 goto finalize_session;
1913 }
1914
1915 copy_to_file(localFd, remoteFd);
1916 read_status_line(remoteFd, buf, sizeof(buf));
1917
1918 adb_close(localFd);
1919 adb_close(remoteFd);
1920
1921 if (strncmp("Success", buf, 7)) {
1922 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001923 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001924 success = 0;
1925 goto finalize_session;
1926 }
1927 }
1928
1929finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001930 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001931 std::string service =
1932 android::base::StringPrintf("exec:pm install-%s %d",
1933 success ? "commit" : "abandon", session_id);
1934 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001935 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001936 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001937 return -1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001938 }
1939 read_status_line(fd, buf, sizeof(buf));
1940 adb_close(fd);
1941
1942 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001943 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001944 return 0;
1945 } else {
1946 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001947 fputs(buf, stderr);
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +00001948 return -1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001949 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001950}