blob: 6981ff25c17b7c6a0063aa5f072d3f4f6c2fb32e [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>
Elliott Hughesdbe91ee2016-11-15 12:37:32 -080036#include <thread>
Josh Gao05786772015-10-30 16:57:19 -070037#include <vector>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070038
Elliott Hughese8b663f2016-05-26 22:43:19 -070039#include <android-base/file.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080040#include <android-base/logging.h>
Tao Wu135f4ab2016-09-16 13:01:24 -070041#include <android-base/parseint.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080042#include <android-base/stringprintf.h>
43#include <android-base/strings.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070044
Yabin Cuid325e862014-11-17 14:48:25 -080045#if !defined(_WIN32)
Josh Gao8dcdb572015-10-23 15:03:31 -070046#include <signal.h>
Elliott Hughes0fbf9612015-11-04 13:07:47 -080047#include <sys/ioctl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080049#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050#endif
51
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080052#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080053#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080054#include "adb_client.h"
55#include "adb_io.h"
Josh Gao924d35a2016-08-30 15:39:25 -070056#include "adb_unique_fd.h"
Elliott Hughes58305772015-04-17 13:57:15 -070057#include "adb_utils.h"
Felipe Leme698e0652016-07-19 17:07:22 -070058#include "bugreport.h"
59#include "commandline.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060#include "file_sync_service.h"
David Pursell70ef7b42015-09-30 13:35:42 -070061#include "services.h"
David Pursell606835a2015-09-08 17:17:02 -070062#include "shell_service.h"
Josh Gao4602adb2016-11-15 18:55:47 -080063#include "sysdeps/chrono.h"
Josh Gao28589bb2018-03-07 16:51:08 -080064#include "sysdeps/memory.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065
Josh Gaob122b172017-08-16 16:57:01 -070066static int install_app(int argc, const char** argv);
67static int install_multiple_app(int argc, const char** argv);
68static int uninstall_app(int argc, const char** argv);
69static int install_app_legacy(int argc, const char** argv);
70static int uninstall_app_legacy(int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071
Matt Gumbeld7b33082012-11-14 10:16:17 -080072extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080073
Felipe Leme0d4f0502016-07-26 12:14:39 -070074DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
75
Elliott Hughes792581f2018-04-03 10:54:39 -070076static std::string product_file(const std::string& file) {
Elliott Hughes0754cb92017-05-01 11:04:31 -070077 const char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
78 if (ANDROID_PRODUCT_OUT == nullptr) {
79 fprintf(stderr, "adb: product directory not specified; set $ANDROID_PRODUCT_OUT\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080080 exit(1);
81 }
Elliott Hughes792581f2018-04-03 10:54:39 -070082 return std::string{ANDROID_PRODUCT_OUT} + OS_PATH_SEPARATOR_STR + file;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080083}
84
Elliott Hughes58305772015-04-17 13:57:15 -070085static void help() {
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070086 fprintf(stdout, "%s\n", adb_version().c_str());
Felipe Lemeb3239722016-07-29 17:57:00 -070087 // clang-format off
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070088 fprintf(stdout,
89 "global options:\n"
90 " -a listen on all network interfaces, not just localhost\n"
91 " -d use USB device (error if multiple devices connected)\n"
Elliott Hughes83ab5c22017-01-13 16:58:25 -080092 " -e use TCP/IP device (error if multiple TCP/IP devices available)\n"
Elliott Hughes0754cb92017-05-01 11:04:31 -070093 " -s SERIAL use device with given serial (overrides $ANDROID_SERIAL)\n"
Josh Gaob122b172017-08-16 16:57:01 -070094 " -t ID use device with given transport id\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070095 " -H name of adb server host [default=localhost]\n"
96 " -P port of adb server [default=5037]\n"
97 " -L SOCKET listen on given socket for adb server [default=tcp:localhost:5037]\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080098 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070099 "general commands:\n"
100 " devices [-l] list connected devices (-l for long output)\n"
101 " help show this help message\n"
102 " version show version num\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700103 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800104 "networking:\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700105 " connect HOST[:PORT] connect to a device via TCP/IP [default port=5555]\n"
106 " disconnect [HOST[:PORT]]\n"
107 " disconnect from given TCP/IP device [default port=5555], or all\n"
108 " forward --list list all forward socket connections\n"
109 " forward [--no-rebind] LOCAL REMOTE\n"
110 " forward socket connection using:\n"
111 " tcp:<port> (<local> may be \"tcp:0\" to pick any open port)\n"
112 " localabstract:<unix domain socket name>\n"
113 " localreserved:<unix domain socket name>\n"
114 " localfilesystem:<unix domain socket name>\n"
115 " dev:<character device name>\n"
116 " jdwp:<process pid> (remote only)\n"
117 " forward --remove LOCAL remove specific forward socket connection\n"
118 " forward --remove-all remove all forward socket connections\n"
119 " ppp TTY [PARAMETER...] run PPP over USB\n"
120 " reverse --list list all reverse socket connections from device\n"
121 " reverse [--no-rebind] REMOTE LOCAL\n"
122 " reverse socket connection using:\n"
123 " tcp:<port> (<remote> may be \"tcp:0\" to pick any open port)\n"
124 " localabstract:<unix domain socket name>\n"
125 " localreserved:<unix domain socket name>\n"
126 " localfilesystem:<unix domain socket name>\n"
127 " reverse --remove REMOTE remove specific reverse socket connection\n"
128 " reverse --remove-all remove all reverse socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700130 "file transfer:\n"
Dan Albert06b0d6b2017-05-18 22:56:48 -0700131 " push [--sync] LOCAL... REMOTE\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700132 " copy local files/directories to device\n"
Dan Albert06b0d6b2017-05-18 22:56:48 -0700133 " --sync: only push files that are newer on the host than the device\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700134 " pull [-a] REMOTE... LOCAL\n"
135 " copy files/dirs from device\n"
136 " -a: preserve file timestamp and mode\n"
Elliott Hughes792581f2018-04-03 10:54:39 -0700137 " sync [all|data|odm|oem|product|system|vendor]\n"
Elliott Hughes0754cb92017-05-01 11:04:31 -0700138 " sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700139 " -l: list but don't copy\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800140 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700141 "shell:\n"
142 " shell [-e ESCAPE] [-n] [-Tt] [-x] [COMMAND...]\n"
143 " run remote shell command (interactive shell if no command given)\n"
144 " -e: choose escape character, or \"none\"; default '~'\n"
145 " -n: don't read from stdin\n"
146 " -T: disable PTY allocation\n"
147 " -t: force PTY allocation\n"
148 " -x: disable remote exit codes and stdout/stderr separation\n"
149 " emu COMMAND run emulator console command\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700151 "app installation:\n"
Felipe Leme95c5b7f2018-05-08 18:40:18 -0700152 " install [-lrtsdg] [--instant] PACKAGE\n"
153 " install-multiple [-lrtsdpg] [--instant] PACKAGE...\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700154 " push package(s) to the device and install them\n"
155 " -l: forward lock application\n"
156 " -r: replace existing application\n"
157 " -t: allow test packages\n"
158 " -s: install application on sdcard\n"
159 " -d: allow version code downgrade (debuggable packages only)\n"
160 " -p: partial application install (install-multiple only)\n"
161 " -g: grant all runtime permissions\n"
Felipe Leme95c5b7f2018-05-08 18:40:18 -0700162 " --instant: cause the app to be installed as an ephemeral install app\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700163 " uninstall [-k] PACKAGE\n"
164 " remove this app package from the device\n"
165 " '-k': keep the data and cache directories\n"
166 "\n"
167 "backup/restore:\n"
Johan Toras Halsetheca1b3b2017-04-11 19:15:17 +0100168 " to show usage run \"adb shell bu help\"\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700169 "\n"
170 "debugging:\n"
171 " bugreport [PATH]\n"
172 " write bugreport to given PATH [default=bugreport.zip];\n"
173 " if PATH is a directory, the bug report is saved in that directory.\n"
174 " devices that don't support zipped bug reports output to stdout.\n"
175 " jdwp list pids of processes hosting a JDWP transport\n"
176 " logcat show device log (logcat --help for more)\n"
177 "\n"
178 "security:\n"
179 " disable-verity disable dm-verity checking on userdebug builds\n"
180 " enable-verity re-enable dm-verity checking on userdebug builds\n"
181 " keygen FILE\n"
182 " generate adb public/private key; private key stored in FILE,\n"
183 " public key stored in FILE.pub (existing files overwritten)\n"
184 "\n"
185 "scripting:\n"
186 " wait-for[-TRANSPORT]-STATE\n"
187 " wait for device to be in the given state\n"
188 " State: device, recovery, sideload, or bootloader\n"
189 " Transport: usb, local, or any [default=any]\n"
190 " get-state print offline | bootloader | device\n"
191 " get-serialno print <serial-number>\n"
192 " get-devpath print <device-path>\n"
Elliott Hughes792581f2018-04-03 10:54:39 -0700193 " remount remount partitions read-write\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700194 " reboot [bootloader|recovery|sideload|sideload-auto-reboot]\n"
195 " reboot the device; defaults to booting system image but\n"
196 " supports bootloader and recovery too. sideload reboots\n"
197 " into recovery and automatically starts sideload mode,\n"
198 " sideload-auto-reboot is the same but reboots after sideloading.\n"
199 " sideload OTAPACKAGE sideload the given full OTA package\n"
200 " root restart adbd with root permissions\n"
201 " unroot restart adbd without root permissions\n"
202 " usb restart adb server listening on USB\n"
203 " tcpip PORT restart adb server listening on TCP on PORT\n"
Timcd643152010-02-16 20:18:29 +0000204 "\n"
Yabin Cui1f4ec192016-04-05 13:50:44 -0700205 "internal debugging:\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700206 " start-server ensure that there is a server running\n"
207 " kill-server kill the server if it is running\n"
208 " reconnect kick connection from host side to force reconnect\n"
209 " reconnect device kick connection from device side to force reconnect\n"
Yabin Cuib5e11412017-03-10 16:01:01 -0800210 " reconnect offline reset offline/unauthorized devices to force reconnect\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700211 "\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700212 "environment variables:\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700213 " $ADB_TRACE\n"
214 " comma-separated list of debug info to log:\n"
215 " all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp\n"
216 " $ADB_VENDOR_KEYS colon-separated list of keys (files or directories)\n"
217 " $ANDROID_SERIAL serial number to connect to (see -s)\n"
218 " $ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)\n");
Felipe Lemeb3239722016-07-29 17:57:00 -0700219 // clang-format on
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800220}
221
Yabin Cuid325e862014-11-17 14:48:25 -0800222#if defined(_WIN32)
223
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700224// Implemented in sysdeps_win32.cpp.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800225void stdin_raw_init();
226void stdin_raw_restore();
Yabin Cuid325e862014-11-17 14:48:25 -0800227
228#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100229static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800231static void stdin_raw_init() {
232 if (tcgetattr(STDIN_FILENO, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100234 termios tio;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800235 if (tcgetattr(STDIN_FILENO, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800236
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100237 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100239 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800240 tio.c_cc[VTIME] = 0;
241 tio.c_cc[VMIN] = 1;
242
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800243 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244}
245
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800246static void stdin_raw_restore() {
247 tcsetattr(STDIN_FILENO, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248}
249#endif
250
David Pursell606835a2015-09-08 17:17:02 -0700251// Reads from |fd| and prints received data. If |use_shell_protocol| is true
252// this expects that incoming data will use the shell protocol, in which case
253// stdout/stderr are routed independently and the remote exit code will be
254// returned.
Felipe Leme0d4f0502016-07-26 12:14:39 -0700255// if |callback| is non-null, stdout/stderr output will be handled by it.
256int read_and_dump(int fd, bool use_shell_protocol = false,
257 StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK) {
David Pursell606835a2015-09-08 17:17:02 -0700258 int exit_code = 0;
Felipe Lemed1dd1252016-06-06 16:05:36 -0700259 if (fd < 0) return exit_code;
260
David Pursell606835a2015-09-08 17:17:02 -0700261 std::unique_ptr<ShellProtocol> protocol;
262 int length = 0;
David Pursell606835a2015-09-08 17:17:02 -0700263
264 char raw_buffer[BUFSIZ];
265 char* buffer_ptr = raw_buffer;
266 if (use_shell_protocol) {
Josh Gao28589bb2018-03-07 16:51:08 -0800267 protocol = std::make_unique<ShellProtocol>(fd);
David Pursell606835a2015-09-08 17:17:02 -0700268 if (!protocol) {
269 LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
270 return 1;
271 }
272 buffer_ptr = protocol->data();
273 }
274
Felipe Lemed1dd1252016-06-06 16:05:36 -0700275 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700276 if (use_shell_protocol) {
277 if (!protocol->Read()) {
278 break;
279 }
Felipe Leme0d4f0502016-07-26 12:14:39 -0700280 length = protocol->data_length();
David Pursell606835a2015-09-08 17:17:02 -0700281 switch (protocol->id()) {
282 case ShellProtocol::kIdStdout:
Felipe Leme0d4f0502016-07-26 12:14:39 -0700283 callback->OnStdout(buffer_ptr, length);
David Pursell606835a2015-09-08 17:17:02 -0700284 break;
285 case ShellProtocol::kIdStderr:
Felipe Leme0d4f0502016-07-26 12:14:39 -0700286 callback->OnStderr(buffer_ptr, length);
David Pursell606835a2015-09-08 17:17:02 -0700287 break;
288 case ShellProtocol::kIdExit:
289 exit_code = protocol->data()[0];
290 continue;
291 default:
292 continue;
293 }
294 length = protocol->data_length();
295 } else {
296 D("read_and_dump(): pre adb_read(fd=%d)", fd);
297 length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
298 D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
299 if (length <= 0) {
300 break;
301 }
Felipe Leme0d4f0502016-07-26 12:14:39 -0700302 callback->OnStdout(buffer_ptr, length);
Felipe Leme44a42672016-04-01 17:43:27 -0700303 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800304 }
David Pursell606835a2015-09-08 17:17:02 -0700305
Felipe Leme0d4f0502016-07-26 12:14:39 -0700306 return callback->Done(exit_code);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307}
308
Jeff Sharkey960df972014-06-09 17:30:57 -0700309static void read_status_line(int fd, char* buf, size_t count)
310{
311 count--;
312 while (count > 0) {
313 int len = adb_read(fd, buf, count);
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700314 if (len <= 0) {
Jeff Sharkey960df972014-06-09 17:30:57 -0700315 break;
316 }
317
318 buf += len;
319 count -= len;
320 }
321 *buf = '\0';
322}
323
Christopher Tatec42f1bb2016-07-06 13:22:22 -0700324static void stdinout_raw_prologue(int inFd, int outFd, int& old_stdin_mode, int& old_stdout_mode) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700325 if (inFd == STDIN_FILENO) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800326 stdin_raw_init();
Spencer Lowb7dfb792015-05-22 16:48:31 -0700327#ifdef _WIN32
328 old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
329 if (old_stdin_mode == -1) {
330 fatal_errno("could not set stdin to binary");
331 }
332#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700333 }
Yabin Cuid325e862014-11-17 14:48:25 -0800334
Spencer Lowb7dfb792015-05-22 16:48:31 -0700335#ifdef _WIN32
336 if (outFd == STDOUT_FILENO) {
337 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
338 if (old_stdout_mode == -1) {
339 fatal_errno("could not set stdout to binary");
340 }
341 }
342#endif
Christopher Tatec42f1bb2016-07-06 13:22:22 -0700343}
344
345static void stdinout_raw_epilogue(int inFd, int outFd, int old_stdin_mode, int old_stdout_mode) {
346 if (inFd == STDIN_FILENO) {
347 stdin_raw_restore();
348#ifdef _WIN32
349 if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
350 fatal_errno("could not restore stdin mode");
351 }
352#endif
353 }
354
355#ifdef _WIN32
356 if (outFd == STDOUT_FILENO) {
357 if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
358 fatal_errno("could not restore stdout mode");
359 }
360 }
361#endif
362}
363
364static void copy_to_file(int inFd, int outFd) {
365 const size_t BUFSIZE = 32 * 1024;
366 char* buf = (char*) malloc(BUFSIZE);
367 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
368 int len;
369 long total = 0;
370 int old_stdin_mode = -1;
371 int old_stdout_mode = -1;
372
373 D("copy_to_file(%d -> %d)", inFd, outFd);
374
375 stdinout_raw_prologue(inFd, outFd, old_stdin_mode, old_stdout_mode);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700376
Elliott Hughesa7090b92015-04-17 17:03:59 -0700377 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700378 if (inFd == STDIN_FILENO) {
379 len = unix_read(inFd, buf, BUFSIZE);
380 } else {
381 len = adb_read(inFd, buf, BUFSIZE);
382 }
Christopher Tated2f54152011-04-21 12:53:28 -0700383 if (len == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700384 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tated2f54152011-04-21 12:53:28 -0700385 break;
386 }
387 if (len < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700388 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tated2f54152011-04-21 12:53:28 -0700389 break;
390 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700391 if (outFd == STDOUT_FILENO) {
392 fwrite(buf, 1, len, stdout);
393 fflush(stdout);
394 } else {
395 adb_write(outFd, buf, len);
396 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700397 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700398 }
Yabin Cuid325e862014-11-17 14:48:25 -0800399
Christopher Tatec42f1bb2016-07-06 13:22:22 -0700400 stdinout_raw_epilogue(inFd, outFd, old_stdin_mode, old_stdout_mode);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700401
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700402 D("copy_to_file() finished after %lu bytes", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700403 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700404}
405
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800406static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800407 // Old devices can't handle window size changes.
408 if (shell == nullptr) return;
409
Spencer Low2e02dc62015-11-07 17:34:39 -0800410#if defined(_WIN32)
411 struct winsize {
412 unsigned short ws_row;
413 unsigned short ws_col;
414 unsigned short ws_xpixel;
415 unsigned short ws_ypixel;
416 };
417#endif
418
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800419 winsize ws;
Spencer Low2e02dc62015-11-07 17:34:39 -0800420
421#if defined(_WIN32)
422 // If stdout is redirected to a non-console, we won't be able to get the
423 // console size, but that makes sense.
424 const intptr_t intptr_handle = _get_osfhandle(STDOUT_FILENO);
425 if (intptr_handle == -1) return;
426
427 const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle);
428
429 CONSOLE_SCREEN_BUFFER_INFO info;
430 memset(&info, 0, sizeof(info));
431 if (!GetConsoleScreenBufferInfo(handle, &info)) return;
432
433 memset(&ws, 0, sizeof(ws));
434 // The number of visible rows, excluding offscreen scroll-back rows which are in info.dwSize.Y.
435 ws.ws_row = info.srWindow.Bottom - info.srWindow.Top + 1;
436 // If the user has disabled "Wrap text output on resize", they can make the screen buffer wider
437 // than the window, in which case we should use the width of the buffer.
438 ws.ws_col = info.dwSize.X;
439#else
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800440 if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return;
Spencer Low2e02dc62015-11-07 17:34:39 -0800441#endif
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800442
443 // Send the new window size as human-readable ASCII for debugging convenience.
444 size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d",
445 ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel);
446 shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800447}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800448
David Pursell606835a2015-09-08 17:17:02 -0700449// Used to pass multiple values to the stdin read thread.
450struct StdinReadArgs {
451 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700452 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700453 std::unique_ptr<ShellProtocol> protocol;
Elliott Hughes28416d62015-11-04 13:36:32 -0800454 char escape_char;
David Pursell606835a2015-09-08 17:17:02 -0700455};
456
David Pursell606835a2015-09-08 17:17:02 -0700457// Loops to read from stdin and push the data to the given FD.
458// The argument should be a pointer to a StdinReadArgs object. This function
459// will take ownership of the object and delete it when finished.
Josh Gaod9db09c2016-02-12 14:31:15 -0800460static void stdin_read_thread_loop(void* x) {
David Pursell606835a2015-09-08 17:17:02 -0700461 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800463#if !defined(_WIN32)
464 // Mask SIGTTIN in case we're in a backgrounded process.
Josh Gao8dcdb572015-10-23 15:03:31 -0700465 sigset_t sigset;
466 sigemptyset(&sigset);
467 sigaddset(&sigset, SIGTTIN);
468 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
469#endif
470
Spencer Low2e02dc62015-11-07 17:34:39 -0800471#if defined(_WIN32)
472 // _get_interesting_input_record_uncached() causes unix_read_interruptible()
473 // to return -1 with errno == EINTR if the window size changes.
474#else
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800475 // Unblock SIGWINCH for this thread, so our read(2) below will be
476 // interrupted if the window size changes.
477 sigset_t mask;
478 sigemptyset(&mask);
479 sigaddset(&mask, SIGWINCH);
480 pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
481#endif
482
483 // Set up the initial window size.
484 send_window_size_change(args->stdin_fd, args->protocol);
485
Elliott Hughes28416d62015-11-04 13:36:32 -0800486 char raw_buffer[BUFSIZ];
David Pursell606835a2015-09-08 17:17:02 -0700487 char* buffer_ptr = raw_buffer;
488 size_t buffer_size = sizeof(raw_buffer);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800489 if (args->protocol != nullptr) {
David Pursell606835a2015-09-08 17:17:02 -0700490 buffer_ptr = args->protocol->data();
491 buffer_size = args->protocol->data_capacity();
492 }
493
Elliott Hughes28416d62015-11-04 13:36:32 -0800494 // If we need to parse escape sequences, make life easy.
495 if (args->raw_stdin && args->escape_char != '\0') {
496 buffer_size = 1;
497 }
498
499 enum EscapeState { kMidFlow, kStartOfLine, kInEscape };
500 EscapeState state = kStartOfLine;
501
Elliott Hughesaa245492015-08-03 10:38:08 -0700502 while (true) {
Spencer Low2e02dc62015-11-07 17:34:39 -0800503 // Use unix_read_interruptible() rather than adb_read() for stdin.
504 D("stdin_read_thread_loop(): pre unix_read_interruptible(fdi=%d,...)", args->stdin_fd);
505 int r = unix_read_interruptible(args->stdin_fd, buffer_ptr,
506 buffer_size);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800507 if (r == -1 && errno == EINTR) {
508 send_window_size_change(args->stdin_fd, args->protocol);
509 continue;
510 }
Spencer Low2e02dc62015-11-07 17:34:39 -0800511 D("stdin_read_thread_loop(): post unix_read_interruptible(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700512 if (r <= 0) {
513 // Only devices using the shell protocol know to close subprocess
514 // stdin. For older devices we want to just leave the connection
515 // open, otherwise an unpredictable amount of return data could
516 // be lost due to the FD closing before all data has been received.
517 if (args->protocol) {
518 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
519 }
520 break;
521 }
Elliott Hughes28416d62015-11-04 13:36:32 -0800522 // If we made stdin raw, check input for escape sequences. In
David Pursell1ed57f02015-10-06 15:30:03 -0700523 // this situation signals like Ctrl+C are sent remotely rather than
524 // interpreted locally so this provides an emergency out if the remote
525 // process starts ignoring the signal. SSH also does this, see the
526 // "escape characters" section on the ssh man page for more info.
Elliott Hughes28416d62015-11-04 13:36:32 -0800527 if (args->raw_stdin && args->escape_char != '\0') {
528 char ch = buffer_ptr[0];
529 if (ch == args->escape_char) {
530 if (state == kStartOfLine) {
531 state = kInEscape;
532 // Swallow the escape character.
533 continue;
534 } else {
535 state = kMidFlow;
536 }
537 } else {
538 if (state == kInEscape) {
539 if (ch == '.') {
540 fprintf(stderr,"\r\n[ disconnected ]\r\n");
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800541 stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700542 exit(0);
Elliott Hughes28416d62015-11-04 13:36:32 -0800543 } else {
544 // We swallowed an escape character that wasn't part of
545 // a valid escape sequence; time to cough it up.
546 buffer_ptr[0] = args->escape_char;
547 buffer_ptr[1] = ch;
548 ++r;
David Pursell1ed57f02015-10-06 15:30:03 -0700549 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550 }
Elliott Hughes28416d62015-11-04 13:36:32 -0800551 state = (ch == '\n' || ch == '\r') ? kStartOfLine : kMidFlow;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800552 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800553 }
David Pursell606835a2015-09-08 17:17:02 -0700554 if (args->protocol) {
555 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
556 break;
557 }
558 } else {
559 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
560 break;
561 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800562 }
563 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800564}
565
David Pursell1ed57f02015-10-06 15:30:03 -0700566// Returns a shell service string with the indicated arguments and command.
567static std::string ShellServiceString(bool use_shell_protocol,
568 const std::string& type_arg,
569 const std::string& command) {
570 std::vector<std::string> args;
571 if (use_shell_protocol) {
572 args.push_back(kShellServiceArgShellProtocol);
Elliott Hughesc2252df2015-11-18 12:45:48 -0800573
574 const char* terminal_type = getenv("TERM");
575 if (terminal_type != nullptr) {
576 args.push_back(std::string("TERM=") + terminal_type);
577 }
David Pursell1ed57f02015-10-06 15:30:03 -0700578 }
579 if (!type_arg.empty()) {
580 args.push_back(type_arg);
581 }
582
583 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
584 return android::base::StringPrintf("shell%s%s:%s",
585 args.empty() ? "" : ",",
586 android::base::Join(args, ',').c_str(),
587 command.c_str());
588}
589
590// Connects to a shell on the device and read/writes data.
591//
592// Note: currently this function doesn't properly clean up resources; the
593// FD connected to the adb server is never closed and the stdin read thread
594// may never exit.
595//
596// On success returns the remote exit code if |use_shell_protocol| is true,
597// 0 otherwise. On failure returns 1.
598static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
Elliott Hughes28416d62015-11-04 13:36:32 -0800599 char escape_char,
David Pursell1ed57f02015-10-06 15:30:03 -0700600 const std::string& command) {
601 std::string service_string = ShellServiceString(use_shell_protocol,
602 type_arg, command);
603
Josh Gaoa019f782017-06-16 15:34:34 -0700604 // Old devices can't handle a service string that's longer than MAX_PAYLOAD_V1.
605 // Use |use_shell_protocol| to determine whether to allow a command longer than that.
606 if (service_string.size() > MAX_PAYLOAD_V1 && !use_shell_protocol) {
607 fprintf(stderr, "error: shell command too long\n");
608 return 1;
609 }
610
David Pursell1ed57f02015-10-06 15:30:03 -0700611 // Make local stdin raw if the device allocates a PTY, which happens if:
612 // 1. We are explicitly asking for a PTY shell, or
613 // 2. We don't specify shell type and are starting an interactive session.
614 bool raw_stdin = (type_arg == kShellServiceArgPty ||
615 (type_arg.empty() && command.empty()));
616
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700617 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700618 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700619 if (fd < 0) {
620 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800621 return 1;
622 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800623
David Pursell606835a2015-09-08 17:17:02 -0700624 StdinReadArgs* args = new StdinReadArgs;
625 if (!args) {
626 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700627 return 1;
628 }
David Pursell1ed57f02015-10-06 15:30:03 -0700629 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700630 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700631 args->raw_stdin = raw_stdin;
Elliott Hughes28416d62015-11-04 13:36:32 -0800632 args->escape_char = escape_char;
David Pursell606835a2015-09-08 17:17:02 -0700633 if (use_shell_protocol) {
Josh Gao28589bb2018-03-07 16:51:08 -0800634 args->protocol = std::make_unique<ShellProtocol>(args->write_fd);
David Pursell606835a2015-09-08 17:17:02 -0700635 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700636
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800637 if (raw_stdin) stdin_raw_init();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800638
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800639#if !defined(_WIN32)
640 // Ensure our process is notified if the local window size changes.
641 // We use sigaction(2) to ensure that the SA_RESTART flag is not set,
642 // because the whole reason we're sending signals is to unblock the read(2)!
643 // That also means we don't need to do anything in the signal handler:
644 // the side effect of delivering the signal is all we need.
645 struct sigaction sa;
646 memset(&sa, 0, sizeof(sa));
647 sa.sa_handler = [](int) {};
648 sa.sa_flags = 0;
649 sigaction(SIGWINCH, &sa, nullptr);
650
651 // Now block SIGWINCH in this thread (the main thread) and all threads spawned
652 // from it. The stdin read thread will unblock this signal to ensure that it's
653 // the thread that receives the signal.
654 sigset_t mask;
655 sigemptyset(&mask);
656 sigaddset(&mask, SIGWINCH);
657 pthread_sigmask(SIG_BLOCK, &mask, nullptr);
658#endif
659
660 // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
Josh Gaoe1dacfc2017-04-12 17:00:49 -0700661 std::thread(stdin_read_thread_loop, args).detach();
662 int exit_code = read_and_dump(fd, use_shell_protocol);
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700663
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800664 // TODO: properly exit stdin_read_thread_loop and close |fd|.
David Pursell1ed57f02015-10-06 15:30:03 -0700665
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800666 // TODO: we should probably install signal handlers for this.
667 // TODO: can we use atexit? even on Windows?
668 if (raw_stdin) stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700669
David Pursell606835a2015-09-08 17:17:02 -0700670 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800671}
672
Josh Gaof3f6a1d2016-01-31 19:12:26 -0800673static int adb_shell(int argc, const char** argv) {
David Pursell0aacbbe2016-01-21 19:56:50 -0800674 FeatureSet features;
Josh Gaof3f6a1d2016-01-31 19:12:26 -0800675 std::string error;
Josh Gaof3f6a1d2016-01-31 19:12:26 -0800676 if (!adb_get_feature_set(&features, &error)) {
677 fprintf(stderr, "error: %s\n", error.c_str());
David Pursell0aacbbe2016-01-21 19:56:50 -0800678 return 1;
679 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800680
Elliott Hughescabfa112016-10-19 14:47:11 -0700681 enum PtyAllocationMode { kPtyAuto, kPtyNo, kPtyYes, kPtyDefinitely };
682
683 // Defaults.
684 char escape_char = '~'; // -e
685 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2); // -x
686 PtyAllocationMode tty = use_shell_protocol ? kPtyAuto : kPtyDefinitely; // -t/-T
Elliott Hughes6452a892015-04-29 12:28:13 -0700687
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800688 // Parse shell-specific command-line options.
Elliott Hughescabfa112016-10-19 14:47:11 -0700689 argv[0] = "adb shell"; // So getopt(3) error messages start "adb shell".
Huihong Luoaf398852017-08-17 15:23:08 -0700690#ifdef _WIN32
691 // fixes "adb shell -l" crash on Windows, b/37284906
692 __argv = const_cast<char**>(argv);
693#endif
Elliott Hughescabfa112016-10-19 14:47:11 -0700694 optind = 1; // argv[0] is always "shell", so set `optind` appropriately.
695 int opt;
696 while ((opt = getopt(argc, const_cast<char**>(argv), "+e:ntTx")) != -1) {
697 switch (opt) {
698 case 'e':
699 if (!(strlen(optarg) == 1 || strcmp(optarg, "none") == 0)) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700700 return syntax_error("-e requires a single-character argument or 'none'");
Elliott Hughescabfa112016-10-19 14:47:11 -0700701 }
702 escape_char = (strcmp(optarg, "none") == 0) ? 0 : optarg[0];
703 break;
704 case 'n':
705 close_stdin();
706 break;
707 case 'x':
708 // This option basically asks for historical behavior, so set options that
709 // correspond to the historical defaults. This is slightly weird in that -Tx
710 // is fine (because we'll undo the -T) but -xT isn't, but that does seem to
711 // be our least worst choice...
712 use_shell_protocol = false;
713 tty = kPtyDefinitely;
714 escape_char = '~';
715 break;
716 case 't':
717 // Like ssh, -t arguments are cumulative so that multiple -t's
718 // are needed to force a PTY.
719 tty = (tty >= kPtyYes) ? kPtyDefinitely : kPtyYes;
720 break;
721 case 'T':
722 tty = kPtyNo;
723 break;
724 default:
725 // getopt(3) already printed an error message for us.
Elliott Hughes28416d62015-11-04 13:36:32 -0800726 return 1;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800727 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700728 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800729
Elliott Hughescabfa112016-10-19 14:47:11 -0700730 bool is_interactive = (optind == argc);
David Pursell57dd5ae2016-01-27 16:07:52 -0800731
Elliott Hughescabfa112016-10-19 14:47:11 -0700732 std::string shell_type_arg = kShellServiceArgPty;
733 if (tty == kPtyNo) {
734 shell_type_arg = kShellServiceArgRaw;
735 } else if (tty == kPtyAuto) {
736 // If stdin isn't a TTY, default to a raw shell; this lets
737 // things like `adb shell < my_script.sh` work as expected.
738 // Non-interactive shells should also not have a pty.
739 if (!unix_isatty(STDIN_FILENO) || !is_interactive) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800740 shell_type_arg = kShellServiceArgRaw;
Elliott Hughescabfa112016-10-19 14:47:11 -0700741 }
742 } else if (tty == kPtyYes) {
743 // A single -t arg isn't enough to override implicit -T.
744 if (!unix_isatty(STDIN_FILENO)) {
745 fprintf(stderr,
746 "Remote PTY will not be allocated because stdin is not a terminal.\n"
747 "Use multiple -t options to force remote PTY allocation.\n");
748 shell_type_arg = kShellServiceArgRaw;
749 }
750 }
751
752 D("shell -e 0x%x t=%d use_shell_protocol=%s shell_type_arg=%s\n",
753 escape_char, tty,
754 use_shell_protocol ? "true" : "false",
755 (shell_type_arg == kShellServiceArgPty) ? "pty" : "raw");
756
757 // Raw mode is only supported when talking to a new device *and* using the shell protocol.
758 if (!use_shell_protocol) {
759 if (shell_type_arg != kShellServiceArgPty) {
760 fprintf(stderr, "error: %s only supports allocating a pty\n",
761 !CanUseFeature(features, kFeatureShell2) ? "device" : "-x");
762 return 1;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800763 } else {
Elliott Hughescabfa112016-10-19 14:47:11 -0700764 // If we're not using the shell protocol, the type argument must be empty.
765 shell_type_arg = "";
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800766 }
David Pursell71c83122015-09-14 15:33:50 -0700767 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800768
769 std::string command;
Elliott Hughescabfa112016-10-19 14:47:11 -0700770 if (optind < argc) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800771 // We don't escape here, just like ssh(1). http://b/20564385.
Elliott Hughescabfa112016-10-19 14:47:11 -0700772 command = android::base::Join(std::vector<const char*>(argv + optind, argv + argc), ' ');
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800773 }
774
Elliott Hughes28416d62015-11-04 13:36:32 -0800775 return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command);
David Pursell71c83122015-09-14 15:33:50 -0700776}
777
Elliott Hughes09e794c2017-05-02 14:31:59 -0700778static int adb_sideload_legacy(const char* filename, int in_fd, int size) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700779 std::string error;
Elliott Hughes09e794c2017-05-02 14:31:59 -0700780 int out_fd = adb_connect(android::base::StringPrintf("sideload:%d", size), &error);
781 if (out_fd < 0) {
782 fprintf(stderr, "adb: pre-KitKat sideload connection failed: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800783 return -1;
784 }
785
786 int opt = CHUNK_SIZE;
Elliott Hughes09e794c2017-05-02 14:31:59 -0700787 opt = adb_setsockopt(out_fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800788
Elliott Hughes09e794c2017-05-02 14:31:59 -0700789 char buf[CHUNK_SIZE];
790 int total = size;
791 while (size > 0) {
792 unsigned xfer = (size > CHUNK_SIZE) ? CHUNK_SIZE : size;
793 if (!ReadFdExactly(in_fd, buf, xfer)) {
794 fprintf(stderr, "adb: failed to read data from %s: %s\n", filename, strerror(errno));
795 adb_close(out_fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800796 return -1;
797 }
Elliott Hughes09e794c2017-05-02 14:31:59 -0700798 if (!WriteFdExactly(out_fd, buf, xfer)) {
799 std::string error;
800 adb_status(out_fd, &error);
801 fprintf(stderr, "adb: failed to write data: %s\n", error.c_str());
802 adb_close(out_fd);
803 return -1;
804 }
805 size -= xfer;
806 printf("sending: '%s' %4d%% \r", filename, (int)(100LL - ((100LL * size) / (total))));
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700807 fflush(stdout);
Doug Zongker447f0612012-01-09 14:54:53 -0800808 }
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700809 printf("\n");
Doug Zongker447f0612012-01-09 14:54:53 -0800810
Elliott Hughes09e794c2017-05-02 14:31:59 -0700811 if (!adb_status(out_fd, &error)) {
812 fprintf(stderr, "adb: error response: %s\n", error.c_str());
813 adb_close(out_fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800814 return -1;
815 }
816
Elliott Hughes09e794c2017-05-02 14:31:59 -0700817 adb_close(out_fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800818 return 0;
819}
820
Doug Zongker71fe5842014-06-26 15:35:36 -0700821#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
822
823/*
824 * The sideload-host protocol serves the data in a file (given on the
825 * command line) to the client, using a simple protocol:
826 *
827 * - The connect message includes the total number of bytes in the
828 * file and a block size chosen by us.
829 *
830 * - The other side sends the desired block number as eight decimal
831 * digits (eg "00000023" for block 23). Blocks are numbered from
832 * zero.
833 *
834 * - We send back the data of the requested block. The last block is
835 * likely to be partial; when the last block is requested we only
836 * send the part of the block that exists, it's not padded up to the
837 * block size.
838 *
839 * - When the other side sends "DONEDONE" instead of a block number,
840 * we hang up.
841 */
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700842static int adb_sideload_host(const char* filename) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700843 // TODO: use a LinePrinter instead...
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700844 struct stat sb;
845 if (stat(filename, &sb) == -1) {
Elliott Hughes09e794c2017-05-02 14:31:59 -0700846 fprintf(stderr, "adb: failed to stat file %s: %s\n", filename, strerror(errno));
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700847 return -1;
848 }
849 unique_fd package_fd(adb_open(filename, O_RDONLY));
850 if (package_fd == -1) {
Elliott Hughes09e794c2017-05-02 14:31:59 -0700851 fprintf(stderr, "adb: failed to open file %s: %s\n", filename, strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700852 return -1;
853 }
854
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700855 std::string service = android::base::StringPrintf(
856 "sideload-host:%d:%d", static_cast<int>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700857 std::string error;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700858 unique_fd device_fd(adb_connect(service, &error));
859 if (device_fd < 0) {
860 // Try falling back to the older (<= K) sideload method. Maybe this
Doug Zongker71fe5842014-06-26 15:35:36 -0700861 // is an older device that doesn't support sideload-host.
Elliott Hughes09e794c2017-05-02 14:31:59 -0700862 fprintf(stderr, "adb: sideload connection failed: %s\n", error.c_str());
863 fprintf(stderr, "adb: trying pre-KitKat sideload method...\n");
864 return adb_sideload_legacy(filename, package_fd, static_cast<int>(sb.st_size));
Doug Zongker71fe5842014-06-26 15:35:36 -0700865 }
866
Elliott Hughese8b663f2016-05-26 22:43:19 -0700867 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700868 adb_setsockopt(device_fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
869
870 char buf[SIDELOAD_HOST_BLOCK_SIZE];
Doug Zongker71fe5842014-06-26 15:35:36 -0700871
Elliott Hughese8b663f2016-05-26 22:43:19 -0700872 size_t xfer = 0;
873 int last_percent = -1;
Elliott Hughesa7090b92015-04-17 17:03:59 -0700874 while (true) {
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700875 if (!ReadFdExactly(device_fd, buf, 8)) {
Elliott Hughes09e794c2017-05-02 14:31:59 -0700876 fprintf(stderr, "adb: failed to read command: %s\n", strerror(errno));
Elliott Hughese8b663f2016-05-26 22:43:19 -0700877 return -1;
Doug Zongker71fe5842014-06-26 15:35:36 -0700878 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700879 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700880
Elliott Hughes6452a892015-04-29 12:28:13 -0700881 if (strcmp("DONEDONE", buf) == 0) {
Elliott Hughese8b663f2016-05-26 22:43:19 -0700882 printf("\rTotal xfer: %.2fx%*s\n",
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700883 static_cast<double>(xfer) / (sb.st_size ? sb.st_size : 1),
884 static_cast<int>(strlen(filename) + 10), "");
Elliott Hughese8b663f2016-05-26 22:43:19 -0700885 return 0;
Doug Zongker71fe5842014-06-26 15:35:36 -0700886 }
887
Doug Zongker71fe5842014-06-26 15:35:36 -0700888 int block = strtol(buf, NULL, 10);
889
890 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700891 if (offset >= static_cast<size_t>(sb.st_size)) {
Elliott Hughes09e794c2017-05-02 14:31:59 -0700892 fprintf(stderr, "adb: failed to read block %d past end\n", block);
Elliott Hughese8b663f2016-05-26 22:43:19 -0700893 return -1;
Doug Zongker71fe5842014-06-26 15:35:36 -0700894 }
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700895
Doug Zongker71fe5842014-06-26 15:35:36 -0700896 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700897 if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<size_t>(sb.st_size)) {
898 to_write = sb.st_size - offset;
Doug Zongker71fe5842014-06-26 15:35:36 -0700899 }
900
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700901 if (adb_lseek(package_fd, offset, SEEK_SET) != static_cast<int>(offset)) {
Elliott Hughes09e794c2017-05-02 14:31:59 -0700902 fprintf(stderr, "adb: failed to seek to package block: %s\n", strerror(errno));
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700903 return -1;
904 }
905 if (!ReadFdExactly(package_fd, buf, to_write)) {
Elliott Hughes09e794c2017-05-02 14:31:59 -0700906 fprintf(stderr, "adb: failed to read package block: %s\n", strerror(errno));
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700907 return -1;
908 }
909
910 if (!WriteFdExactly(device_fd, buf, to_write)) {
911 adb_status(device_fd, &error);
Elliott Hughes09e794c2017-05-02 14:31:59 -0700912 fprintf(stderr, "adb: failed to write data '%s' *\n", error.c_str());
Elliott Hughese8b663f2016-05-26 22:43:19 -0700913 return -1;
Doug Zongker71fe5842014-06-26 15:35:36 -0700914 }
915 xfer += to_write;
916
917 // For normal OTA packages, we expect to transfer every byte
918 // twice, plus a bit of overhead (one read during
919 // verification, one read of each byte for installation, plus
920 // extra access to things like the zip central directory).
921 // This estimate of the completion becomes 100% when we've
922 // transferred ~2.13 (=100/47) times the package size.
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700923 int percent = static_cast<int>(xfer * 47LL / (sb.st_size ? sb.st_size : 1));
Doug Zongker71fe5842014-06-26 15:35:36 -0700924 if (percent != last_percent) {
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700925 printf("\rserving: '%s' (~%d%%) ", filename, percent);
Doug Zongker71fe5842014-06-26 15:35:36 -0700926 fflush(stdout);
927 last_percent = percent;
928 }
929 }
Doug Zongker71fe5842014-06-26 15:35:36 -0700930}
931
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800932/**
933 * Run ppp in "notty" mode against a resource listed as the first parameter
934 * eg:
935 *
936 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
937 *
938 */
Elliott Hughes58305772015-04-17 13:57:15 -0700939static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800940#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800941 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
942 return -1;
943#else
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700944 if (argc < 2) return syntax_error("adb %s <adb service name> [ppp opts]", argv[0]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800945
Dan Albertbac34742015-02-25 17:51:28 -0800946 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700947 std::string error;
948 int fd = adb_connect(adb_service_name, &error);
949 if (fd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700950 fprintf(stderr, "adb: could not open adb service %s: %s\n", adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800951 return 1;
952 }
953
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700954 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800955
956 if (pid < 0) {
957 perror("from fork()");
958 return 1;
959 } else if (pid == 0) {
960 int err;
961 int i;
962 const char **ppp_args;
963
964 // copy args
965 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
966 ppp_args[0] = "pppd";
967 for (i = 2 ; i < argc ; i++) {
968 //argv[2] and beyond become ppp_args[1] and beyond
969 ppp_args[i - 1] = argv[i];
970 }
971 ppp_args[i-1] = NULL;
972
973 // child side
974
975 dup2(fd, STDIN_FILENO);
976 dup2(fd, STDOUT_FILENO);
977 adb_close(STDERR_FILENO);
978 adb_close(fd);
979
980 err = execvp("pppd", (char * const *)ppp_args);
981
982 if (err < 0) {
983 perror("execing pppd");
984 }
985 exit(-1);
986 } else {
987 // parent side
988
989 adb_close(fd);
990 return 0;
991 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800992#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800993}
994
Josh Gaob122b172017-08-16 16:57:01 -0700995static bool wait_for_device(const char* service) {
Josh Gao08881e72016-04-13 12:14:16 -0700996 std::vector<std::string> components = android::base::Split(service, "-");
997 if (components.size() < 3 || components.size() > 4) {
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100998 fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
999 return false;
1000 }
1001
Josh Gaob122b172017-08-16 16:57:01 -07001002 TransportType t;
1003 adb_get_transport(&t, nullptr, nullptr);
1004
Elliott Hughes2b101112015-05-04 19:29:32 -07001005 // Was the caller vague about what they'd like us to wait for?
1006 // If so, check they weren't more specific in their choice of transport type.
Josh Gao08881e72016-04-13 12:14:16 -07001007 if (components.size() == 3) {
1008 auto it = components.begin() + 2;
Elliott Hughes2b101112015-05-04 19:29:32 -07001009 if (t == kTransportUsb) {
Josh Gao08881e72016-04-13 12:14:16 -07001010 components.insert(it, "usb");
Elliott Hughes2b101112015-05-04 19:29:32 -07001011 } else if (t == kTransportLocal) {
Josh Gao08881e72016-04-13 12:14:16 -07001012 components.insert(it, "local");
Elliott Hughes2b101112015-05-04 19:29:32 -07001013 } else {
Josh Gao08881e72016-04-13 12:14:16 -07001014 components.insert(it, "any");
Elliott Hughes2b101112015-05-04 19:29:32 -07001015 }
Josh Gao08881e72016-04-13 12:14:16 -07001016 } else if (components[2] != "any" && components[2] != "local" && components[2] != "usb") {
1017 fprintf(stderr, "adb: unknown type %s; expected 'any', 'local', or 'usb'\n",
1018 components[2].c_str());
Leo Sartre1fbc9db2015-11-27 18:56:48 +01001019 return false;
1020 }
1021
Josh Gao86441c32016-04-13 12:18:58 -07001022 if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
1023 components[3] != "recovery" && components[3] != "sideload") {
Josh Gao08881e72016-04-13 12:14:16 -07001024 fprintf(stderr,
1025 "adb: unknown state %s; "
Josh Gao86441c32016-04-13 12:18:58 -07001026 "expected 'any', 'bootloader', 'device', 'recovery', or 'sideload'\n",
Josh Gao08881e72016-04-13 12:14:16 -07001027 components[3].c_str());
1028 return false;
1029 }
1030
Josh Gaob122b172017-08-16 16:57:01 -07001031 std::string cmd = format_host_command(android::base::Join(components, "-").c_str());
Elliott Hughes424af022015-05-29 17:55:19 -07001032 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -07001033}
1034
Josh Gao06c73ae2016-03-04 15:16:18 -08001035static bool adb_root(const char* command) {
1036 std::string error;
Josh Gao06c73ae2016-03-04 15:16:18 -08001037
Elliott Hughese8b663f2016-05-26 22:43:19 -07001038 unique_fd fd(adb_connect(android::base::StringPrintf("%s:", command), &error));
1039 if (fd < 0) {
Josh Gao06c73ae2016-03-04 15:16:18 -08001040 fprintf(stderr, "adb: unable to connect for %s: %s\n", command, error.c_str());
1041 return false;
1042 }
1043
1044 // Figure out whether we actually did anything.
1045 char buf[256];
1046 char* cur = buf;
1047 ssize_t bytes_left = sizeof(buf);
1048 while (bytes_left > 0) {
Elliott Hughese8b663f2016-05-26 22:43:19 -07001049 ssize_t bytes_read = adb_read(fd, cur, bytes_left);
Josh Gao06c73ae2016-03-04 15:16:18 -08001050 if (bytes_read == 0) {
1051 break;
1052 } else if (bytes_read < 0) {
1053 fprintf(stderr, "adb: error while reading for %s: %s\n", command, strerror(errno));
1054 return false;
1055 }
1056 cur += bytes_read;
1057 bytes_left -= bytes_read;
1058 }
1059
1060 if (bytes_left == 0) {
1061 fprintf(stderr, "adb: unexpected output length for %s\n", command);
1062 return false;
1063 }
1064
1065 fflush(stdout);
1066 WriteFdExactly(STDOUT_FILENO, buf, sizeof(buf) - bytes_left);
1067 if (cur != buf && strstr(buf, "restarting") == nullptr) {
1068 return true;
1069 }
1070
Josh Gao05824732016-06-16 14:00:09 -07001071 // Give adbd some time to kill itself and come back up.
1072 // We can't use wait-for-device because devices (e.g. adb over network) might not come back.
Josh Gao4602adb2016-11-15 18:55:47 -08001073 std::this_thread::sleep_for(3s);
Josh Gao05824732016-06-16 14:00:09 -07001074 return true;
Josh Gao06c73ae2016-03-04 15:16:18 -08001075}
1076
Josh Gaob122b172017-08-16 16:57:01 -07001077int send_shell_command(const std::string& command, bool disable_shell_protocol,
1078 StandardStreamsCallbackInterface* callback) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001079 int fd;
David Pursell0aacbbe2016-01-21 19:56:50 -08001080 bool use_shell_protocol = false;
1081
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001082 while (true) {
David Pursell0aacbbe2016-01-21 19:56:50 -08001083 bool attempt_connection = true;
1084
Felipe Leme0d4f0502016-07-26 12:14:39 -07001085 // Use shell protocol if it's supported and the caller doesn't explicitly
1086 // disable it.
David Pursell0aacbbe2016-01-21 19:56:50 -08001087 if (!disable_shell_protocol) {
1088 FeatureSet features;
Josh Gaof3f6a1d2016-01-31 19:12:26 -08001089 std::string error;
1090 if (adb_get_feature_set(&features, &error)) {
David Pursell0aacbbe2016-01-21 19:56:50 -08001091 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
1092 } else {
1093 // Device was unreachable.
1094 attempt_connection = false;
1095 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001096 }
David Pursell0aacbbe2016-01-21 19:56:50 -08001097
1098 if (attempt_connection) {
1099 std::string error;
1100 std::string service_string = ShellServiceString(use_shell_protocol, "", command);
1101
1102 fd = adb_connect(service_string, &error);
1103 if (fd >= 0) {
1104 break;
1105 }
1106 }
1107
Felipe Leme0d4f0502016-07-26 12:14:39 -07001108 fprintf(stderr, "- waiting for device -\n");
Josh Gaob122b172017-08-16 16:57:01 -07001109 if (!wait_for_device("wait-for-device")) {
Josh Gaob6117c42016-02-24 15:16:17 -08001110 return 1;
1111 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001112 }
1113
Felipe Leme0d4f0502016-07-26 12:14:39 -07001114 int exit_code = read_and_dump(fd, use_shell_protocol, callback);
David Pursell71c83122015-09-14 15:33:50 -07001115
1116 if (adb_close(fd) < 0) {
1117 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001118 }
David Pursell71c83122015-09-14 15:33:50 -07001119
1120 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001121}
1122
Josh Gaob122b172017-08-16 16:57:01 -07001123static int logcat(int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001124 char* log_tags = getenv("ANDROID_LOG_TAGS");
1125 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001126
David Pursell70ef7b42015-09-30 13:35:42 -07001127 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001128
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001129 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001130 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -08001131 }
1132
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001133 --argc;
1134 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001135 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001136 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137 }
1138
David Pursell70ef7b42015-09-30 13:35:42 -07001139 // No need for shell protocol with logcat, always disable for simplicity.
Josh Gaob122b172017-08-16 16:57:01 -07001140 return send_shell_command(cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141}
1142
Christopher Tatec42f1bb2016-07-06 13:22:22 -07001143static void write_zeros(int bytes, int fd) {
1144 int old_stdin_mode = -1;
1145 int old_stdout_mode = -1;
1146 char* buf = (char*) calloc(1, bytes);
1147 if (buf == nullptr) fatal("couldn't allocate buffer for write_zeros");
1148
1149 D("write_zeros(%d) -> %d", bytes, fd);
1150
1151 stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
1152
1153 if (fd == STDOUT_FILENO) {
1154 fwrite(buf, 1, bytes, stdout);
1155 fflush(stdout);
1156 } else {
1157 adb_write(fd, buf, bytes);
1158 }
1159
1160 stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
1161
1162 D("write_zeros() finished");
1163 free(buf);
1164}
1165
Dan Albertbac34742015-02-25 17:51:28 -08001166static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -07001167 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -07001168
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001169 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001170 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001171 if (!strcmp("-f", argv[i])) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001172 if (i == argc - 1) return syntax_error("backup -f passed with no filename");
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001173 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001174 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001175 argv[i++] = argv[j++];
1176 }
1177 argc -= 2;
1178 argv[argc] = NULL;
1179 }
Christopher Tated2f54152011-04-21 12:53:28 -07001180 }
1181
Elliott Hughes56e68132015-11-13 11:04:10 -08001182 // Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
1183 // a list of packages is required.
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001184 if (argc < 2) return syntax_error("backup either needs a list of packages or -all/-shared");
Christopher Tatebb86bc52011-08-22 17:12:08 -07001185
Christopher Tateb1dfffe2011-12-08 19:04:34 -08001186 adb_unlink(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001187 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -07001188 if (outFd < 0) {
Elliott Hughes56e68132015-11-13 11:04:10 -08001189 fprintf(stderr, "adb: backup unable to create file '%s': %s\n", filename, strerror(errno));
1190 return EXIT_FAILURE;
Christopher Tated2f54152011-04-21 12:53:28 -07001191 }
1192
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001193 std::string cmd = "backup:";
1194 --argc;
1195 ++argv;
1196 while (argc-- > 0) {
1197 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -07001198 }
1199
Yabin Cui7a3f8d62015-09-02 17:44:28 -07001200 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001201 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001202 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -07001203 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001204 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -07001205 adb_close(outFd);
Elliott Hughes56e68132015-11-13 11:04:10 -08001206 return EXIT_FAILURE;
Christopher Tated2f54152011-04-21 12:53:28 -07001207 }
1208
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001209 fprintf(stdout, "Now unlock your device and confirm the backup operation...\n");
Elliott Hughes56e68132015-11-13 11:04:10 -08001210 fflush(stdout);
1211
Christopher Tated2f54152011-04-21 12:53:28 -07001212 copy_to_file(fd, outFd);
1213
1214 adb_close(fd);
1215 adb_close(outFd);
Elliott Hughes56e68132015-11-13 11:04:10 -08001216 return EXIT_SUCCESS;
Christopher Tated2f54152011-04-21 12:53:28 -07001217}
1218
Dan Albertbac34742015-02-25 17:51:28 -08001219static int restore(int argc, const char** argv) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001220 if (argc != 2) return syntax_error("restore requires an argument");
Christopher Tate702967a2011-05-17 15:52:54 -07001221
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001222 const char* filename = argv[1];
1223 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -07001224 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001225 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -07001226 return -1;
1227 }
1228
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001229 std::string error;
1230 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -07001231 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001232 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -07001233 adb_close(tarFd);
1234 return -1;
1235 }
1236
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001237 fprintf(stdout, "Now unlock your device and confirm the restore operation.\n");
1238 fflush(stdout);
1239
Christopher Tate702967a2011-05-17 15:52:54 -07001240 copy_to_file(tarFd, fd);
1241
Christopher Tatec42f1bb2016-07-06 13:22:22 -07001242 // Provide an in-band EOD marker in case the archive file is malformed
1243 write_zeros(512*2, fd);
1244
Josh Gao5767d0d2016-03-04 15:51:03 -08001245 // Wait until the other side finishes, or it'll get sent SIGHUP.
1246 copy_to_file(fd, STDOUT_FILENO);
1247
Christopher Tate702967a2011-05-17 15:52:54 -07001248 adb_close(fd);
1249 adb_close(tarFd);
1250 return 0;
1251}
1252
Dan Albert06b0d6b2017-05-18 22:56:48 -07001253static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs,
1254 const char** dst, bool* copy_attrs, bool* sync) {
Josh Gao05786772015-10-30 16:57:19 -07001255 *copy_attrs = false;
Mark Lindner76f2a932014-03-11 17:55:59 -07001256
Josh Gao05786772015-10-30 16:57:19 -07001257 srcs->clear();
1258 bool ignore_flags = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001259 while (narg > 0) {
Josh Gao05786772015-10-30 16:57:19 -07001260 if (ignore_flags || *arg[0] != '-') {
1261 srcs->push_back(*arg);
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001262 } else {
Josh Gao05786772015-10-30 16:57:19 -07001263 if (!strcmp(*arg, "-p")) {
1264 // Silently ignore for backwards compatibility.
1265 } else if (!strcmp(*arg, "-a")) {
1266 *copy_attrs = true;
Dan Albert06b0d6b2017-05-18 22:56:48 -07001267 } else if (!strcmp(*arg, "--sync")) {
1268 if (sync != nullptr) {
1269 *sync = true;
1270 }
Josh Gao05786772015-10-30 16:57:19 -07001271 } else if (!strcmp(*arg, "--")) {
1272 ignore_flags = true;
1273 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001274 syntax_error("unrecognized option '%s'", *arg);
Josh Gao05786772015-10-30 16:57:19 -07001275 exit(1);
1276 }
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001277 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001278 ++arg;
1279 --narg;
1280 }
1281
Josh Gao05786772015-10-30 16:57:19 -07001282 if (srcs->size() > 1) {
1283 *dst = srcs->back();
1284 srcs->pop_back();
Mark Lindner76f2a932014-03-11 17:55:59 -07001285 }
1286}
1287
Elliott Hughes6452a892015-04-29 12:28:13 -07001288static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001289 std::string error;
1290 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001291 if (fd < 0) {
1292 fprintf(stderr, "error: %s\n", error.c_str());
1293 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001294 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001295 read_and_dump(fd);
1296 adb_close(fd);
1297 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001298}
1299
Elliott Hughes6452a892015-04-29 12:28:13 -07001300static int adb_query_command(const std::string& command) {
1301 std::string result;
1302 std::string error;
1303 if (!adb_query(command, &result, &error)) {
1304 fprintf(stderr, "error: %s\n", error.c_str());
1305 return 1;
1306 }
1307 printf("%s\n", result.c_str());
1308 return 0;
1309}
1310
Spencer Lowa13df302015-09-07 16:20:13 -07001311// Disallow stdin, stdout, and stderr.
1312static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1313#ifdef _WIN32
1314 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1315 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1316 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1317 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1318#else
1319 return ack_reply_fd > 2;
1320#endif
1321}
1322
Todd Kennedy248722e2016-07-20 16:22:37 -07001323static bool _use_legacy_install() {
1324 FeatureSet features;
1325 std::string error;
1326 if (!adb_get_feature_set(&features, &error)) {
1327 fprintf(stderr, "error: %s\n", error.c_str());
1328 return true;
1329 }
1330 return !CanUseFeature(features, kFeatureCmd);
1331}
1332
Elliott Hughescabfa112016-10-19 14:47:11 -07001333int adb_commandline(int argc, const char** argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001334 int no_daemon = 0;
1335 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001336 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001337 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001338 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001339 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001340
Elliott Hughes65433da2015-11-18 18:07:48 -08001341#if !defined(_WIN32)
1342 // We'd rather have EPIPE than SIGPIPE.
1343 signal(SIGPIPE, SIG_IGN);
1344#endif
1345
Josh Gao9c869b52016-08-25 16:00:22 -07001346 const char* server_host_str = nullptr;
1347 const char* server_port_str = nullptr;
1348 const char* server_socket_str = nullptr;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001349
Elliott Hughes8d28e192015-10-07 14:55:10 -07001350 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1351 const char* serial = nullptr;
Josh Gaob122b172017-08-16 16:57:01 -07001352 TransportId transport_id = 0;
Elliott Hughes8d28e192015-10-07 14:55:10 -07001353
Riley Andrews98f58e82014-12-05 17:37:24 -08001354 while (argc > 0) {
1355 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001356 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001357 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001358 no_daemon = 1;
1359 } else if (!strcmp(argv[0], "fork-server")) {
1360 /* this is a special flag used only when the ADB client launches the ADB Server */
1361 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001362 } else if (!strcmp(argv[0], "--reply-fd")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001363 if (argc < 2) return syntax_error("--reply-fd requires an argument");
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001364 const char* reply_fd_str = argv[1];
1365 argc--;
1366 argv++;
1367 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001368 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001369 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001370 return 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001371 }
Josh Gaob122b172017-08-16 16:57:01 -07001372 } else if (!strncmp(argv[0], "-s", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001373 if (isdigit(argv[0][2])) {
1374 serial = argv[0] + 2;
1375 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001376 if (argc < 2 || argv[0][2] != '\0') return syntax_error("-s requires an argument");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001377 serial = argv[1];
1378 argc--;
1379 argv++;
1380 }
Josh Gaob122b172017-08-16 16:57:01 -07001381 } else if (!strncmp(argv[0], "-t", 2)) {
1382 const char* id;
1383 if (isdigit(argv[0][2])) {
1384 id = argv[0] + 2;
1385 } else {
1386 id = argv[1];
1387 argc--;
1388 argv++;
1389 }
1390 transport_id = strtoll(id, const_cast<char**>(&id), 10);
1391 if (*id != '\0') {
1392 return syntax_error("invalid transport id");
1393 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001394 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001395 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001397 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001398 } else if (!strcmp(argv[0],"-a")) {
1399 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001400 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001401 if (argv[0][2] == '\0') {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001402 if (argc < 2) return syntax_error("-H requires an argument");
Josh Gao9c869b52016-08-25 16:00:22 -07001403 server_host_str = argv[1];
Matt Gumbeld7b33082012-11-14 10:16:17 -08001404 argc--;
1405 argv++;
1406 } else {
Josh Gao9c869b52016-08-25 16:00:22 -07001407 server_host_str = argv[0] + 2;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001408 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001409 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001410 if (argv[0][2] == '\0') {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001411 if (argc < 2) return syntax_error("-P requires an argument");
Matt Gumbeld7b33082012-11-14 10:16:17 -08001412 server_port_str = argv[1];
1413 argc--;
1414 argv++;
1415 } else {
1416 server_port_str = argv[0] + 2;
1417 }
Josh Gao9c869b52016-08-25 16:00:22 -07001418 } else if (!strcmp(argv[0], "-L")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001419 if (argc < 2) return syntax_error("-L requires an argument");
Josh Gao9c869b52016-08-25 16:00:22 -07001420 server_socket_str = argv[1];
1421 argc--;
1422 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423 } else {
Josh Gao9c869b52016-08-25 16:00:22 -07001424 /* out of recognized modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425 break;
1426 }
1427 argc--;
1428 argv++;
1429 }
1430
Josh Gao9c869b52016-08-25 16:00:22 -07001431 if ((server_host_str || server_port_str) && server_socket_str) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001432 return syntax_error("-L is incompatible with -H or -P");
Josh Gao9c869b52016-08-25 16:00:22 -07001433 }
1434
1435 // If -L, -H, or -P are specified, ignore environment variables.
1436 // Otherwise, prefer ADB_SERVER_SOCKET over ANDROID_ADB_SERVER_ADDRESS/PORT.
Tao Wu135f4ab2016-09-16 13:01:24 -07001437 if (!server_host_str && !server_port_str && !server_socket_str) {
1438 server_socket_str = getenv("ADB_SERVER_SOCKET");
Josh Gao9c869b52016-08-25 16:00:22 -07001439 }
1440
1441 if (!server_socket_str) {
1442 // tcp:1234 and tcp:localhost:1234 are different with -a, so don't default to localhost
1443 server_host_str = server_host_str ? server_host_str : getenv("ANDROID_ADB_SERVER_ADDRESS");
1444
Tao Wu135f4ab2016-09-16 13:01:24 -07001445 int server_port = DEFAULT_ADB_PORT;
Josh Gao9c869b52016-08-25 16:00:22 -07001446 server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
Tao Wu135f4ab2016-09-16 13:01:24 -07001447 if (server_port_str && strlen(server_port_str) > 0) {
1448 if (!android::base::ParseInt(server_port_str, &server_port, 1, 65535)) {
1449 fprintf(stderr,
1450 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive"
1451 " number less than 65535. Got \"%s\"\n",
1452 server_port_str);
1453 exit(1);
1454 }
1455 }
Josh Gao9c869b52016-08-25 16:00:22 -07001456
1457 int rc;
1458 char* temp;
1459 if (server_host_str) {
Tao Wu135f4ab2016-09-16 13:01:24 -07001460 rc = asprintf(&temp, "tcp:%s:%d", server_host_str, server_port);
Josh Gao9c869b52016-08-25 16:00:22 -07001461 } else {
Tao Wu135f4ab2016-09-16 13:01:24 -07001462 rc = asprintf(&temp, "tcp:%d", server_port);
Josh Gao9c869b52016-08-25 16:00:22 -07001463 }
1464 if (rc < 0) {
1465 fatal("failed to allocate server socket specification");
1466 }
1467 server_socket_str = temp;
1468 }
1469
1470 adb_set_socket_spec(server_socket_str);
1471
Elliott Hughes8d28e192015-10-07 14:55:10 -07001472 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1473 if (transport_type == kTransportAny && serial == nullptr) {
1474 serial = getenv("ANDROID_SERIAL");
1475 }
1476
Josh Gaob122b172017-08-16 16:57:01 -07001477 adb_set_transport(transport_type, serial, transport_id);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001478
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001479 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001480 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001481 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001482 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001483 return 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001484 }
Josh Gao9c869b52016-08-25 16:00:22 -07001485 r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001486 } else {
Josh Gao9c869b52016-08-25 16:00:22 -07001487 r = launch_server(server_socket_str);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001488 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001489 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001490 fprintf(stderr,"* could not start server *\n");
1491 }
1492 return r;
1493 }
1494
Riley Andrews98f58e82014-12-05 17:37:24 -08001495 if (argc == 0) {
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001496 help();
1497 return 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001498 }
1499
Riley Andrewsc8514c82014-12-05 17:32:46 -08001500 /* handle wait-for-* prefix */
1501 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001502 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503
Josh Gaob122b172017-08-16 16:57:01 -07001504 if (!wait_for_device(service)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001505 return 1;
1506 }
1507
Elliott Hughes2b101112015-05-04 19:29:32 -07001508 // Allow a command to be run after wait-for-device,
1509 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001510 if (argc == 1) {
1511 return 0;
1512 }
1513
1514 /* Fall through */
1515 argc--;
1516 argv++;
1517 }
1518
1519 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001520 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001521 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001522 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001523 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001524 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001525 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001526 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001527 return syntax_error("adb devices [-l]");
Scott Andersone109d262012-04-20 11:21:14 -07001528 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001529
1530 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1531 printf("List of devices attached\n");
1532 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001533 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001534 else if (!strcmp(argv[0], "connect")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001535 if (argc != 2) return syntax_error("adb connect <host>[:<port>]");
Elliott Hughes6452a892015-04-29 12:28:13 -07001536
1537 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1538 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001539 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001540 else if (!strcmp(argv[0], "disconnect")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001541 if (argc > 2) return syntax_error("adb disconnect [<host>[:<port>]]");
Elliott Hughes6452a892015-04-29 12:28:13 -07001542
1543 std::string query = android::base::StringPrintf("host:disconnect:%s",
1544 (argc == 2) ? argv[1] : "");
1545 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001546 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001547 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001548 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001549 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -08001550 else if (!strcmp(argv[0], "shell")) {
Josh Gaof3f6a1d2016-01-31 19:12:26 -08001551 return adb_shell(argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001552 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001553 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001554 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001555
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001556 if (argc < 2) return syntax_error("adb %s command", argv[0]);
Zach Riggleccafc792016-04-14 17:18:04 -04001557
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001558 std::string cmd = "exec:";
1559 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001560 argc -= 2;
1561 argv += 2;
1562 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001563 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001564 }
1565
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001566 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001567 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001568 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001569 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001570 return -1;
1571 }
1572
1573 if (exec_in) {
1574 copy_to_file(STDIN_FILENO, fd);
1575 } else {
1576 copy_to_file(fd, STDOUT_FILENO);
1577 }
1578
1579 adb_close(fd);
1580 return 0;
1581 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001582 else if (!strcmp(argv[0], "kill-server")) {
Josh Gaob3c14ec2017-05-08 18:37:17 -07001583 return adb_kill_server() ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001584 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001585 else if (!strcmp(argv[0], "sideload")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001586 if (argc != 2) return syntax_error("sideload requires an argument");
Doug Zongker71fe5842014-06-26 15:35:36 -07001587 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001588 return 1;
1589 } else {
1590 return 0;
1591 }
Elliott Hughese1632982017-08-23 15:42:28 -07001592 } else if (!strcmp(argv[0], "tcpip")) {
1593 if (argc != 2) return syntax_error("tcpip requires an argument");
1594 int port;
1595 if (!android::base::ParseInt(argv[1], &port, 1, 65535)) {
1596 return syntax_error("tcpip: invalid port: %s", argv[1]);
1597 }
1598 return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
Elliott Hughes19d80b82015-07-21 16:13:40 -07001599 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001600 else if (!strcmp(argv[0], "remount") ||
1601 !strcmp(argv[0], "reboot") ||
1602 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001603 !strcmp(argv[0], "usb") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001604 !strcmp(argv[0], "disable-verity") ||
1605 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001606 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001607 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001608 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001609 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001610 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001611 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001612 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001613 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001614 return adb_connect_command(command);
Josh Gao06c73ae2016-03-04 15:16:18 -08001615 } else if (!strcmp(argv[0], "root") || !strcmp(argv[0], "unroot")) {
1616 return adb_root(argv[0]) ? 0 : 1;
1617 } else if (!strcmp(argv[0], "bugreport")) {
Felipe Leme698e0652016-07-19 17:07:22 -07001618 Bugreport bugreport;
Josh Gaob122b172017-08-16 16:57:01 -07001619 return bugreport.DoIt(argc, argv);
Felipe Leme44a42672016-04-01 17:43:27 -07001620 } else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001621 bool reverse = !strcmp(argv[0], "reverse");
1622 ++argv;
1623 --argc;
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001624 if (argc < 1) return syntax_error("%s requires an argument", argv[0]);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001625
1626 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001627 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001628 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001629 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001630 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001631 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001632 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001633 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001634 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001635 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001636 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001637 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001638 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001639 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001640 }
1641
David Purselleaae97e2016-04-07 11:25:48 -07001642 std::string cmd, error;
Elliott Hughes424af022015-05-29 17:55:19 -07001643 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001644 if (argc != 1) return syntax_error("--list doesn't take any arguments");
Elliott Hughes424af022015-05-29 17:55:19 -07001645 return adb_query_command(host_prefix + ":list-forward");
1646 } else if (strcmp(argv[0], "--remove-all") == 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001647 if (argc != 1) return syntax_error("--remove-all doesn't take any arguments");
Elliott Hughes424af022015-05-29 17:55:19 -07001648 cmd = host_prefix + ":killforward-all";
1649 } else if (strcmp(argv[0], "--remove") == 0) {
1650 // forward --remove <local>
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001651 if (argc != 2) return syntax_error("--remove requires an argument");
Elliott Hughes424af022015-05-29 17:55:19 -07001652 cmd = host_prefix + ":killforward:" + argv[1];
1653 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1654 // forward --no-rebind <local> <remote>
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001655 if (argc != 3) return syntax_error("--no-rebind takes two arguments");
David Purselleaae97e2016-04-07 11:25:48 -07001656 if (forward_targets_are_valid(argv[1], argv[2], &error)) {
1657 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1658 }
Elliott Hughes424af022015-05-29 17:55:19 -07001659 } else {
1660 // forward <local> <remote>
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001661 if (argc != 2) return syntax_error("forward takes two arguments");
David Purselleaae97e2016-04-07 11:25:48 -07001662 if (forward_targets_are_valid(argv[0], argv[1], &error)) {
1663 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
1664 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001665 }
1666
David Purselleaae97e2016-04-07 11:25:48 -07001667 if (!error.empty()) {
1668 fprintf(stderr, "error: %s\n", error.c_str());
1669 return 1;
1670 }
1671
1672 int fd = adb_connect(cmd, &error);
1673 if (fd < 0 || !adb_status(fd, &error)) {
1674 adb_close(fd);
1675 fprintf(stderr, "error: %s\n", error.c_str());
1676 return 1;
1677 }
1678
1679 // Server or device may optionally return a resolved TCP port number.
1680 std::string resolved_port;
1681 if (ReadProtocolString(fd, &resolved_port, &error) && !resolved_port.empty()) {
1682 printf("%s\n", resolved_port.c_str());
1683 }
1684
1685 ReadOrderlyShutdown(fd);
1686 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001689 else if (!strcmp(argv[0], "ls")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001690 if (argc != 2) return syntax_error("ls requires an argument");
Elliott Hughesaa245492015-08-03 10:38:08 -07001691 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001692 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001693 else if (!strcmp(argv[0], "push")) {
Josh Gao05786772015-10-30 16:57:19 -07001694 bool copy_attrs = false;
Dan Albert06b0d6b2017-05-18 22:56:48 -07001695 bool sync = false;
Josh Gao05786772015-10-30 16:57:19 -07001696 std::vector<const char*> srcs;
1697 const char* dst = nullptr;
Mark Lindner76f2a932014-03-11 17:55:59 -07001698
Dan Albert06b0d6b2017-05-18 22:56:48 -07001699 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, &sync);
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001700 if (srcs.empty() || !dst) return syntax_error("push requires an argument");
Dan Albert06b0d6b2017-05-18 22:56:48 -07001701 return do_sync_push(srcs, dst, sync) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001702 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001703 else if (!strcmp(argv[0], "pull")) {
Josh Gao05786772015-10-30 16:57:19 -07001704 bool copy_attrs = false;
1705 std::vector<const char*> srcs;
1706 const char* dst = ".";
Mark Lindner76f2a932014-03-11 17:55:59 -07001707
Dan Albert06b0d6b2017-05-18 22:56:48 -07001708 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, nullptr);
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001709 if (srcs.empty()) return syntax_error("pull requires an argument");
Josh Gao05786772015-10-30 16:57:19 -07001710 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001711 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001712 else if (!strcmp(argv[0], "install")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001713 if (argc < 2) return syntax_error("install requires an argument");
Todd Kennedy248722e2016-07-20 16:22:37 -07001714 if (_use_legacy_install()) {
Josh Gaob122b172017-08-16 16:57:01 -07001715 return install_app_legacy(argc, argv);
David Pursell0aacbbe2016-01-21 19:56:50 -08001716 }
Josh Gaob122b172017-08-16 16:57:01 -07001717 return install_app(argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001718 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001719 else if (!strcmp(argv[0], "install-multiple")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001720 if (argc < 2) return syntax_error("install-multiple requires an argument");
Josh Gaob122b172017-08-16 16:57:01 -07001721 return install_multiple_app(argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001722 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001723 else if (!strcmp(argv[0], "uninstall")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001724 if (argc < 2) return syntax_error("uninstall requires an argument");
Todd Kennedy248722e2016-07-20 16:22:37 -07001725 if (_use_legacy_install()) {
Josh Gaob122b172017-08-16 16:57:01 -07001726 return uninstall_app_legacy(argc, argv);
David Pursell0aacbbe2016-01-21 19:56:50 -08001727 }
Josh Gaob122b172017-08-16 16:57:01 -07001728 return uninstall_app(argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001729 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001730 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001731 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001732 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001733 if (argc < 2) {
Elliott Hughes792581f2018-04-03 10:54:39 -07001734 // No partition specified: sync all of them.
Anthony Newnam705c9442010-02-22 08:36:49 -06001735 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001736 list_only = true;
Elliott Hughes792581f2018-04-03 10:54:39 -07001737 if (argc == 3) src = argv[2];
Riley Andrews98f58e82014-12-05 17:37:24 -08001738 } else if (argc == 2) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001739 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001740 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001741 return syntax_error("adb sync [-l] [PARTITION]");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001742 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001743
Elliott Hughes792581f2018-04-03 10:54:39 -07001744 if (src.empty()) src = "all";
1745 std::vector<std::string> partitions{"data", "odm", "oem", "product", "system", "vendor"};
1746 bool found = false;
1747 for (const auto& partition : partitions) {
1748 if (src == "all" || src == partition) {
1749 std::string src_dir{product_file(partition)};
1750 if (!directory_exists(src_dir)) continue;
1751 found = true;
1752 if (!do_sync_sync(src_dir, "/" + partition, list_only)) return 1;
1753 }
Elliott Hughes58305772015-04-17 13:57:15 -07001754 }
Elliott Hughes792581f2018-04-03 10:54:39 -07001755 return found ? 0 : syntax_error("don't know how to sync %s partition", src.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001756 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001757 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001758 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001759 !strcmp(argv[0],"get-serialno") ||
1760 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001761 {
Josh Gaob122b172017-08-16 16:57:01 -07001762 return adb_query_command(format_host_command(argv[0]));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001763 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001764 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001765 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Josh Gaob122b172017-08-16 16:57:01 -07001766 return logcat(argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001767 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001768 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001769 return ppp(argc, argv);
1770 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001771 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001772 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001773 const int result = adb_connect("host:start-server", &error);
1774 if (result < 0) {
1775 fprintf(stderr, "error: %s\n", error.c_str());
1776 }
1777 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001778 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001779 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001780 return backup(argc, argv);
1781 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001782 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001783 return restore(argc, argv);
1784 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001785 else if (!strcmp(argv[0], "keygen")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001786 if (argc != 2) return syntax_error("keygen requires an argument");
Yabin Cuiaed3c612015-09-22 15:52:57 -07001787 // Always print key generation information for keygen command.
1788 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001789 return adb_auth_keygen(argv[1]);
1790 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001791 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001792 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001793 }
Josh Gaob463baf2016-05-13 18:18:23 -07001794 else if (!strcmp(argv[0], "track-jdwp")) {
1795 return adb_connect_command("track-jdwp");
1796 }
1797 else if (!strcmp(argv[0], "track-devices")) {
1798 return adb_connect_command("host:track-devices");
1799 }
1800
1801
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 /* "adb /?" is a common idiom under Windows */
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001803 else if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001804 help();
1805 return 0;
1806 }
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001807 else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001808 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001809 return 0;
Josh Gao5d1756c2017-02-22 17:07:01 -08001810 } else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001811 // Only list the features common to both the adb client and the device.
David Pursell0aacbbe2016-01-21 19:56:50 -08001812 FeatureSet features;
Josh Gaof3f6a1d2016-01-31 19:12:26 -08001813 std::string error;
1814 if (!adb_get_feature_set(&features, &error)) {
1815 fprintf(stderr, "error: %s\n", error.c_str());
David Pursell0aacbbe2016-01-21 19:56:50 -08001816 return 1;
1817 }
1818
David Pursell4e2fd362015-09-22 10:43:08 -07001819 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001820 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001821 printf("%s\n", name.c_str());
1822 }
1823 }
1824 return 0;
Josh Gao5d1756c2017-02-22 17:07:01 -08001825 } else if (!strcmp(argv[0], "host-features")) {
1826 return adb_query_command("host:host-features");
Yabin Cui1f4ec192016-04-05 13:50:44 -07001827 } else if (!strcmp(argv[0], "reconnect")) {
1828 if (argc == 1) {
Josh Gaob122b172017-08-16 16:57:01 -07001829 return adb_query_command(format_host_command(argv[0]));
Josh Gao22d2b3e2016-10-27 14:01:08 -07001830 } else if (argc == 2) {
1831 if (!strcmp(argv[1], "device")) {
1832 std::string err;
1833 adb_connect("reconnect", &err);
1834 return 0;
1835 } else if (!strcmp(argv[1], "offline")) {
1836 std::string err;
1837 return adb_query_command("host:reconnect-offline");
1838 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001839 return syntax_error("adb reconnect [device|offline]");
Josh Gao22d2b3e2016-10-27 14:01:08 -07001840 }
Yabin Cui1f4ec192016-04-05 13:50:44 -07001841 }
Dan Albert90d4b732015-05-20 18:58:41 -07001842 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001843
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001844 syntax_error("unknown command %s", argv[0]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001845 return 1;
1846}
1847
Josh Gaob122b172017-08-16 16:57:01 -07001848static int uninstall_app(int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001849 // 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
1850 std::string cmd = "cmd package";
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001851 while (argc-- > 0) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001852 // deny the '-k' option until the remaining data/cache can be removed with adb/UI
1853 if (strcmp(*argv, "-k") == 0) {
1854 printf(
1855 "The -k option uninstalls the application while retaining the data/cache.\n"
1856 "At the moment, there is no way to remove the remaining data.\n"
1857 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1858 "If you truly wish to continue, execute 'adb shell cmd package uninstall -k'.\n");
1859 return EXIT_FAILURE;
1860 }
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001861 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001862 }
1863
Josh Gaob122b172017-08-16 16:57:01 -07001864 return send_shell_command(cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001865}
1866
Josh Gaob122b172017-08-16 16:57:01 -07001867static int install_app(int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001868 // The last argument must be the APK file
1869 const char* file = argv[argc - 1];
Elliott Hughes72884782016-10-24 18:29:21 -07001870 if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001871 return syntax_error("filename doesn't end .apk: %s", file);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001872 }
1873
Elliott Hughes72884782016-10-24 18:29:21 -07001874 struct stat sb;
1875 if (stat(file, &sb) == -1) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001876 fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
Elliott Hughes72884782016-10-24 18:29:21 -07001877 return 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001878 }
1879
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001880 int localFd = adb_open(file, O_RDONLY);
1881 if (localFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001882 fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001883 return 1;
1884 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001885
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001886 std::string error;
1887 std::string cmd = "exec:cmd package";
1888
1889 // don't copy the APK name, but, copy the rest of the arguments as-is
1890 while (argc-- > 1) {
1891 cmd += " " + escape_arg(std::string(*argv++));
1892 }
1893
1894 // add size parameter [required for streaming installs]
1895 // do last to override any user specified value
1896 cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
1897
1898 int remoteFd = adb_connect(cmd, &error);
1899 if (remoteFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001900 fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001901 adb_close(localFd);
1902 return 1;
1903 }
1904
1905 char buf[BUFSIZ];
1906 copy_to_file(localFd, remoteFd);
1907 read_status_line(remoteFd, buf, sizeof(buf));
1908
1909 adb_close(localFd);
1910 adb_close(remoteFd);
1911
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001912 if (!strncmp("Success", buf, 7)) {
1913 fputs(buf, stdout);
1914 return 0;
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001915 }
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001916 fprintf(stderr, "adb: failed to install %s: %s", file, buf);
1917 return 1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001918}
1919
Josh Gaob122b172017-08-16 16:57:01 -07001920static int install_multiple_app(int argc, const char** argv) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001921 // Find all APK arguments starting at end.
1922 // All other arguments passed through verbatim.
1923 int first_apk = -1;
Elliott Hughes72884782016-10-24 18:29:21 -07001924 uint64_t total_size = 0;
1925 for (int i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001926 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001927
Calin Juravleaa775382017-12-14 15:48:15 -08001928 if (android::base::EndsWithIgnoreCase(file, ".apk") ||
1929 android::base::EndsWithIgnoreCase(file, ".dm")) {
Elliott Hughes72884782016-10-24 18:29:21 -07001930 struct stat sb;
1931 if (stat(file, &sb) != -1) total_size += sb.st_size;
Jeff Sharkey960df972014-06-09 17:30:57 -07001932 first_apk = i;
1933 } else {
1934 break;
1935 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 }
1937
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001938 if (first_apk == -1) return syntax_error("need APK file on command line");
Kenny Root597ea5b2011-08-05 11:19:45 -07001939
Todd Kennedy248722e2016-07-20 16:22:37 -07001940 std::string install_cmd;
1941 if (_use_legacy_install()) {
1942 install_cmd = "exec:pm";
1943 } else {
1944 install_cmd = "exec:cmd package";
1945 }
1946
1947 std::string cmd = android::base::StringPrintf("%s install-create -S %" PRIu64, install_cmd.c_str(), total_size);
Elliott Hughes72884782016-10-24 18:29:21 -07001948 for (int i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001949 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001950 }
1951
1952 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001953 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001954 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001955 if (fd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001956 fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001957 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001958 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001959 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001960 read_status_line(fd, buf, sizeof(buf));
1961 adb_close(fd);
1962
1963 int session_id = -1;
1964 if (!strncmp("Success", buf, 7)) {
1965 char* start = strrchr(buf, '[');
1966 char* end = strrchr(buf, ']');
1967 if (start && end) {
1968 *end = '\0';
1969 session_id = strtol(start + 1, NULL, 10);
1970 }
1971 }
1972 if (session_id < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001973 fprintf(stderr, "adb: failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001974 fputs(buf, stderr);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001975 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001976 }
1977
1978 // Valid session, now stream the APKs
1979 int success = 1;
Elliott Hughes72884782016-10-24 18:29:21 -07001980 for (int i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001981 const char* file = argv[i];
Elliott Hughes72884782016-10-24 18:29:21 -07001982 struct stat sb;
Jeff Sharkey960df972014-06-09 17:30:57 -07001983 if (stat(file, &sb) == -1) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001984 fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001985 success = 0;
1986 goto finalize_session;
1987 }
1988
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001989 std::string cmd = android::base::StringPrintf(
Calin Juravleaa775382017-12-14 15:48:15 -08001990 "%s install-write -S %" PRIu64 " %d %s -", install_cmd.c_str(),
1991 static_cast<uint64_t>(sb.st_size), session_id, android::base::Basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001992
1993 int localFd = adb_open(file, O_RDONLY);
1994 if (localFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001995 fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001996 success = 0;
1997 goto finalize_session;
1998 }
1999
Elliott Hughes078f0fc2015-04-29 08:35:59 -07002000 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07002001 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07002002 if (remoteFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002003 fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07002004 adb_close(localFd);
2005 success = 0;
2006 goto finalize_session;
2007 }
2008
2009 copy_to_file(localFd, remoteFd);
2010 read_status_line(remoteFd, buf, sizeof(buf));
2011
2012 adb_close(localFd);
2013 adb_close(remoteFd);
2014
2015 if (strncmp("Success", buf, 7)) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002016 fprintf(stderr, "adb: failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002017 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002018 success = 0;
2019 goto finalize_session;
2020 }
2021 }
2022
2023finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002024 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07002025 std::string service =
Todd Kennedy248722e2016-07-20 16:22:37 -07002026 android::base::StringPrintf("%s install-%s %d",
2027 install_cmd.c_str(), success ? "commit" : "abandon", session_id);
Elliott Hughes6452a892015-04-29 12:28:13 -07002028 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07002029 if (fd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002030 fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002031 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07002032 }
2033 read_status_line(fd, buf, sizeof(buf));
2034 adb_close(fd);
2035
2036 if (!strncmp("Success", buf, 7)) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002037 fputs(buf, stdout);
Jeff Sharkey960df972014-06-09 17:30:57 -07002038 return 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07002039 }
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002040 fprintf(stderr, "adb: failed to finalize session\n");
2041 fputs(buf, stderr);
2042 return EXIT_FAILURE;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002043}
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002044
Josh Gaob122b172017-08-16 16:57:01 -07002045static int pm_command(int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002046 std::string cmd = "pm";
2047
2048 while (argc-- > 0) {
2049 cmd += " " + escape_arg(*argv++);
2050 }
2051
Josh Gaob122b172017-08-16 16:57:01 -07002052 return send_shell_command(cmd, false);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002053}
2054
Josh Gaob122b172017-08-16 16:57:01 -07002055static int uninstall_app_legacy(int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002056 /* if the user choose the -k option, we refuse to do it until devices are
2057 out with the option to uninstall the remaining data somehow (adb/ui) */
2058 int i;
2059 for (i = 1; i < argc; i++) {
2060 if (!strcmp(argv[i], "-k")) {
2061 printf(
2062 "The -k option uninstalls the application while retaining the data/cache.\n"
2063 "At the moment, there is no way to remove the remaining data.\n"
2064 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
2065 "If you truly wish to continue, execute 'adb shell pm uninstall -k'\n.");
2066 return EXIT_FAILURE;
2067 }
2068 }
2069
2070 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
Josh Gaob122b172017-08-16 16:57:01 -07002071 return pm_command(argc, argv);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002072}
2073
Josh Gaob122b172017-08-16 16:57:01 -07002074static int delete_file(const std::string& filename) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002075 std::string cmd = "rm -f " + escape_arg(filename);
Josh Gaob122b172017-08-16 16:57:01 -07002076 return send_shell_command(cmd, false);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002077}
2078
Josh Gaob122b172017-08-16 16:57:01 -07002079static int install_app_legacy(int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002080 static const char *const DATA_DEST = "/data/local/tmp/%s";
2081 static const char *const SD_DEST = "/sdcard/tmp/%s";
2082 const char* where = DATA_DEST;
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002083
Elliott Hughes72884782016-10-24 18:29:21 -07002084 for (int i = 1; i < argc; i++) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002085 if (!strcmp(argv[i], "-s")) {
2086 where = SD_DEST;
2087 }
2088 }
2089
2090 // Find last APK argument.
2091 // All other arguments passed through verbatim.
2092 int last_apk = -1;
Elliott Hughes72884782016-10-24 18:29:21 -07002093 for (int i = argc - 1; i >= 0; i--) {
2094 if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002095 last_apk = i;
2096 break;
2097 }
2098 }
2099
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002100 if (last_apk == -1) return syntax_error("need APK file on command line");
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002101
2102 int result = -1;
2103 std::vector<const char*> apk_file = {argv[last_apk]};
2104 std::string apk_dest = android::base::StringPrintf(
Colin Cross58021d12017-02-23 21:23:05 -08002105 where, android::base::Basename(argv[last_apk]).c_str());
Dan Albert06b0d6b2017-05-18 22:56:48 -07002106 if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002107 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
Josh Gaob122b172017-08-16 16:57:01 -07002108 result = pm_command(argc, argv);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002109
2110cleanup_apk:
Josh Gaob122b172017-08-16 16:57:01 -07002111 delete_file(apk_dest);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002112 return result;
2113}