blob: b8f790dcf87020f8c8899c5de14400a69f9c910a [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"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080064
Elliott Hughes3bd73c12015-05-05 13:10:43 -070065static int install_app(TransportType t, const char* serial, int argc, const char** argv);
66static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
67static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
Todd Kennedy6fa848a2015-11-03 16:53:08 -080068static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
69static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080070
Matt Gumbeld7b33082012-11-14 10:16:17 -080071extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080072
Felipe Leme0d4f0502016-07-26 12:14:39 -070073DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
74
Elliott Hughes0754cb92017-05-01 11:04:31 -070075static std::string product_file(const char* file) {
76 const char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
77 if (ANDROID_PRODUCT_OUT == nullptr) {
78 fprintf(stderr, "adb: product directory not specified; set $ANDROID_PRODUCT_OUT\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 exit(1);
80 }
Elliott Hughes0754cb92017-05-01 11:04:31 -070081 return android::base::StringPrintf("%s%s%s", ANDROID_PRODUCT_OUT, OS_PATH_SEPARATOR_STR, file);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080082}
83
Elliott Hughes58305772015-04-17 13:57:15 -070084static void help() {
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070085 fprintf(stdout, "%s\n", adb_version().c_str());
Felipe Lemeb3239722016-07-29 17:57:00 -070086 // clang-format off
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070087 fprintf(stdout,
88 "global options:\n"
89 " -a listen on all network interfaces, not just localhost\n"
90 " -d use USB device (error if multiple devices connected)\n"
Elliott Hughes83ab5c22017-01-13 16:58:25 -080091 " -e use TCP/IP device (error if multiple TCP/IP devices available)\n"
Elliott Hughes0754cb92017-05-01 11:04:31 -070092 " -s SERIAL use device with given serial (overrides $ANDROID_SERIAL)\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070093 " -H name of adb server host [default=localhost]\n"
94 " -P port of adb server [default=5037]\n"
95 " -L SOCKET listen on given socket for adb server [default=tcp:localhost:5037]\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -070097 "general commands:\n"
98 " devices [-l] list connected devices (-l for long output)\n"
99 " help show this help message\n"
100 " version show version num\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700101 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 "networking:\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700103 " connect HOST[:PORT] connect to a device via TCP/IP [default port=5555]\n"
104 " disconnect [HOST[:PORT]]\n"
105 " disconnect from given TCP/IP device [default port=5555], or all\n"
106 " forward --list list all forward socket connections\n"
107 " forward [--no-rebind] LOCAL REMOTE\n"
108 " forward socket connection using:\n"
109 " tcp:<port> (<local> may be \"tcp:0\" to pick any open port)\n"
110 " localabstract:<unix domain socket name>\n"
111 " localreserved:<unix domain socket name>\n"
112 " localfilesystem:<unix domain socket name>\n"
113 " dev:<character device name>\n"
114 " jdwp:<process pid> (remote only)\n"
115 " forward --remove LOCAL remove specific forward socket connection\n"
116 " forward --remove-all remove all forward socket connections\n"
117 " ppp TTY [PARAMETER...] run PPP over USB\n"
118 " reverse --list list all reverse socket connections from device\n"
119 " reverse [--no-rebind] REMOTE LOCAL\n"
120 " reverse socket connection using:\n"
121 " tcp:<port> (<remote> may be \"tcp:0\" to pick any open port)\n"
122 " localabstract:<unix domain socket name>\n"
123 " localreserved:<unix domain socket name>\n"
124 " localfilesystem:<unix domain socket name>\n"
125 " reverse --remove REMOTE remove specific reverse socket connection\n"
126 " reverse --remove-all remove all reverse socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800127 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700128 "file transfer:\n"
129 " push LOCAL... REMOTE\n"
130 " copy local files/directories to device\n"
131 " pull [-a] REMOTE... LOCAL\n"
132 " copy files/dirs from device\n"
133 " -a: preserve file timestamp and mode\n"
Elliott Hughes0754cb92017-05-01 11:04:31 -0700134 " sync [system|vendor|oem|data|all]\n"
135 " sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700136 " -l: list but don't copy\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800137 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700138 "shell:\n"
139 " shell [-e ESCAPE] [-n] [-Tt] [-x] [COMMAND...]\n"
140 " run remote shell command (interactive shell if no command given)\n"
141 " -e: choose escape character, or \"none\"; default '~'\n"
142 " -n: don't read from stdin\n"
143 " -T: disable PTY allocation\n"
144 " -t: force PTY allocation\n"
145 " -x: disable remote exit codes and stdout/stderr separation\n"
146 " emu COMMAND run emulator console command\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800147 "\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700148 "app installation:\n"
149 " install [-lrtsdg] PACKAGE\n"
150 " install-multiple [-lrtsdpg] PACKAGE...\n"
151 " push package(s) to the device and install them\n"
152 " -l: forward lock application\n"
153 " -r: replace existing application\n"
154 " -t: allow test packages\n"
155 " -s: install application on sdcard\n"
156 " -d: allow version code downgrade (debuggable packages only)\n"
157 " -p: partial application install (install-multiple only)\n"
158 " -g: grant all runtime permissions\n"
159 " uninstall [-k] PACKAGE\n"
160 " remove this app package from the device\n"
161 " '-k': keep the data and cache directories\n"
162 "\n"
163 "backup/restore:\n"
Johan Toras Halsetheca1b3b2017-04-11 19:15:17 +0100164 " to show usage run \"adb shell bu help\"\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700165 "\n"
166 "debugging:\n"
167 " bugreport [PATH]\n"
168 " write bugreport to given PATH [default=bugreport.zip];\n"
169 " if PATH is a directory, the bug report is saved in that directory.\n"
170 " devices that don't support zipped bug reports output to stdout.\n"
171 " jdwp list pids of processes hosting a JDWP transport\n"
172 " logcat show device log (logcat --help for more)\n"
173 "\n"
174 "security:\n"
175 " disable-verity disable dm-verity checking on userdebug builds\n"
176 " enable-verity re-enable dm-verity checking on userdebug builds\n"
177 " keygen FILE\n"
178 " generate adb public/private key; private key stored in FILE,\n"
179 " public key stored in FILE.pub (existing files overwritten)\n"
180 "\n"
181 "scripting:\n"
182 " wait-for[-TRANSPORT]-STATE\n"
183 " wait for device to be in the given state\n"
184 " State: device, recovery, sideload, or bootloader\n"
185 " Transport: usb, local, or any [default=any]\n"
186 " get-state print offline | bootloader | device\n"
187 " get-serialno print <serial-number>\n"
188 " get-devpath print <device-path>\n"
189 " remount\n"
190 " remount /system, /vendor, and /oem partitions read-write\n"
191 " reboot [bootloader|recovery|sideload|sideload-auto-reboot]\n"
192 " reboot the device; defaults to booting system image but\n"
193 " supports bootloader and recovery too. sideload reboots\n"
194 " into recovery and automatically starts sideload mode,\n"
195 " sideload-auto-reboot is the same but reboots after sideloading.\n"
196 " sideload OTAPACKAGE sideload the given full OTA package\n"
197 " root restart adbd with root permissions\n"
198 " unroot restart adbd without root permissions\n"
199 " usb restart adb server listening on USB\n"
200 " tcpip PORT restart adb server listening on TCP on PORT\n"
Timcd643152010-02-16 20:18:29 +0000201 "\n"
Yabin Cui1f4ec192016-04-05 13:50:44 -0700202 "internal debugging:\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700203 " start-server ensure that there is a server running\n"
204 " kill-server kill the server if it is running\n"
205 " reconnect kick connection from host side to force reconnect\n"
206 " reconnect device kick connection from device side to force reconnect\n"
Yabin Cuib5e11412017-03-10 16:01:01 -0800207 " reconnect offline reset offline/unauthorized devices to force reconnect\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700208 "\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700209 "environment variables:\n"
Elliott Hughes4bf9bc12016-09-28 15:25:47 -0700210 " $ADB_TRACE\n"
211 " comma-separated list of debug info to log:\n"
212 " all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp\n"
213 " $ADB_VENDOR_KEYS colon-separated list of keys (files or directories)\n"
214 " $ANDROID_SERIAL serial number to connect to (see -s)\n"
215 " $ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)\n");
Felipe Lemeb3239722016-07-29 17:57:00 -0700216 // clang-format on
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800217}
218
Yabin Cuid325e862014-11-17 14:48:25 -0800219#if defined(_WIN32)
220
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700221// Implemented in sysdeps_win32.cpp.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800222void stdin_raw_init();
223void stdin_raw_restore();
Yabin Cuid325e862014-11-17 14:48:25 -0800224
225#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100226static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800228static void stdin_raw_init() {
229 if (tcgetattr(STDIN_FILENO, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100231 termios tio;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800232 if (tcgetattr(STDIN_FILENO, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100234 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800235
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100236 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800237 tio.c_cc[VTIME] = 0;
238 tio.c_cc[VMIN] = 1;
239
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800240 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241}
242
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800243static void stdin_raw_restore() {
244 tcsetattr(STDIN_FILENO, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245}
246#endif
247
David Pursell606835a2015-09-08 17:17:02 -0700248// Reads from |fd| and prints received data. If |use_shell_protocol| is true
249// this expects that incoming data will use the shell protocol, in which case
250// stdout/stderr are routed independently and the remote exit code will be
251// returned.
Felipe Leme0d4f0502016-07-26 12:14:39 -0700252// if |callback| is non-null, stdout/stderr output will be handled by it.
253int read_and_dump(int fd, bool use_shell_protocol = false,
254 StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK) {
David Pursell606835a2015-09-08 17:17:02 -0700255 int exit_code = 0;
Felipe Lemed1dd1252016-06-06 16:05:36 -0700256 if (fd < 0) return exit_code;
257
David Pursell606835a2015-09-08 17:17:02 -0700258 std::unique_ptr<ShellProtocol> protocol;
259 int length = 0;
David Pursell606835a2015-09-08 17:17:02 -0700260
261 char raw_buffer[BUFSIZ];
262 char* buffer_ptr = raw_buffer;
263 if (use_shell_protocol) {
264 protocol.reset(new ShellProtocol(fd));
265 if (!protocol) {
266 LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
267 return 1;
268 }
269 buffer_ptr = protocol->data();
270 }
271
Felipe Lemed1dd1252016-06-06 16:05:36 -0700272 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700273 if (use_shell_protocol) {
274 if (!protocol->Read()) {
275 break;
276 }
Felipe Leme0d4f0502016-07-26 12:14:39 -0700277 length = protocol->data_length();
David Pursell606835a2015-09-08 17:17:02 -0700278 switch (protocol->id()) {
279 case ShellProtocol::kIdStdout:
Felipe Leme0d4f0502016-07-26 12:14:39 -0700280 callback->OnStdout(buffer_ptr, length);
David Pursell606835a2015-09-08 17:17:02 -0700281 break;
282 case ShellProtocol::kIdStderr:
Felipe Leme0d4f0502016-07-26 12:14:39 -0700283 callback->OnStderr(buffer_ptr, length);
David Pursell606835a2015-09-08 17:17:02 -0700284 break;
285 case ShellProtocol::kIdExit:
286 exit_code = protocol->data()[0];
287 continue;
288 default:
289 continue;
290 }
291 length = protocol->data_length();
292 } else {
293 D("read_and_dump(): pre adb_read(fd=%d)", fd);
294 length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
295 D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
296 if (length <= 0) {
297 break;
298 }
Felipe Leme0d4f0502016-07-26 12:14:39 -0700299 callback->OnStdout(buffer_ptr, length);
Felipe Leme44a42672016-04-01 17:43:27 -0700300 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301 }
David Pursell606835a2015-09-08 17:17:02 -0700302
Felipe Leme0d4f0502016-07-26 12:14:39 -0700303 return callback->Done(exit_code);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800304}
305
Jeff Sharkey960df972014-06-09 17:30:57 -0700306static void read_status_line(int fd, char* buf, size_t count)
307{
308 count--;
309 while (count > 0) {
310 int len = adb_read(fd, buf, count);
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700311 if (len <= 0) {
Jeff Sharkey960df972014-06-09 17:30:57 -0700312 break;
313 }
314
315 buf += len;
316 count -= len;
317 }
318 *buf = '\0';
319}
320
Christopher Tatec42f1bb2016-07-06 13:22:22 -0700321static void stdinout_raw_prologue(int inFd, int outFd, int& old_stdin_mode, int& old_stdout_mode) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700322 if (inFd == STDIN_FILENO) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800323 stdin_raw_init();
Spencer Lowb7dfb792015-05-22 16:48:31 -0700324#ifdef _WIN32
325 old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
326 if (old_stdin_mode == -1) {
327 fatal_errno("could not set stdin to binary");
328 }
329#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700330 }
Yabin Cuid325e862014-11-17 14:48:25 -0800331
Spencer Lowb7dfb792015-05-22 16:48:31 -0700332#ifdef _WIN32
333 if (outFd == STDOUT_FILENO) {
334 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
335 if (old_stdout_mode == -1) {
336 fatal_errno("could not set stdout to binary");
337 }
338 }
339#endif
Christopher Tatec42f1bb2016-07-06 13:22:22 -0700340}
341
342static void stdinout_raw_epilogue(int inFd, int outFd, int old_stdin_mode, int old_stdout_mode) {
343 if (inFd == STDIN_FILENO) {
344 stdin_raw_restore();
345#ifdef _WIN32
346 if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
347 fatal_errno("could not restore stdin mode");
348 }
349#endif
350 }
351
352#ifdef _WIN32
353 if (outFd == STDOUT_FILENO) {
354 if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
355 fatal_errno("could not restore stdout mode");
356 }
357 }
358#endif
359}
360
361static void copy_to_file(int inFd, int outFd) {
362 const size_t BUFSIZE = 32 * 1024;
363 char* buf = (char*) malloc(BUFSIZE);
364 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
365 int len;
366 long total = 0;
367 int old_stdin_mode = -1;
368 int old_stdout_mode = -1;
369
370 D("copy_to_file(%d -> %d)", inFd, outFd);
371
372 stdinout_raw_prologue(inFd, outFd, old_stdin_mode, old_stdout_mode);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700373
Elliott Hughesa7090b92015-04-17 17:03:59 -0700374 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700375 if (inFd == STDIN_FILENO) {
376 len = unix_read(inFd, buf, BUFSIZE);
377 } else {
378 len = adb_read(inFd, buf, BUFSIZE);
379 }
Christopher Tated2f54152011-04-21 12:53:28 -0700380 if (len == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700381 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tated2f54152011-04-21 12:53:28 -0700382 break;
383 }
384 if (len < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700385 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tated2f54152011-04-21 12:53:28 -0700386 break;
387 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700388 if (outFd == STDOUT_FILENO) {
389 fwrite(buf, 1, len, stdout);
390 fflush(stdout);
391 } else {
392 adb_write(outFd, buf, len);
393 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700394 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700395 }
Yabin Cuid325e862014-11-17 14:48:25 -0800396
Christopher Tatec42f1bb2016-07-06 13:22:22 -0700397 stdinout_raw_epilogue(inFd, outFd, old_stdin_mode, old_stdout_mode);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700398
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700399 D("copy_to_file() finished after %lu bytes", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700400 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700401}
402
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800403static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800404 // Old devices can't handle window size changes.
405 if (shell == nullptr) return;
406
Spencer Low2e02dc62015-11-07 17:34:39 -0800407#if defined(_WIN32)
408 struct winsize {
409 unsigned short ws_row;
410 unsigned short ws_col;
411 unsigned short ws_xpixel;
412 unsigned short ws_ypixel;
413 };
414#endif
415
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800416 winsize ws;
Spencer Low2e02dc62015-11-07 17:34:39 -0800417
418#if defined(_WIN32)
419 // If stdout is redirected to a non-console, we won't be able to get the
420 // console size, but that makes sense.
421 const intptr_t intptr_handle = _get_osfhandle(STDOUT_FILENO);
422 if (intptr_handle == -1) return;
423
424 const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle);
425
426 CONSOLE_SCREEN_BUFFER_INFO info;
427 memset(&info, 0, sizeof(info));
428 if (!GetConsoleScreenBufferInfo(handle, &info)) return;
429
430 memset(&ws, 0, sizeof(ws));
431 // The number of visible rows, excluding offscreen scroll-back rows which are in info.dwSize.Y.
432 ws.ws_row = info.srWindow.Bottom - info.srWindow.Top + 1;
433 // If the user has disabled "Wrap text output on resize", they can make the screen buffer wider
434 // than the window, in which case we should use the width of the buffer.
435 ws.ws_col = info.dwSize.X;
436#else
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800437 if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return;
Spencer Low2e02dc62015-11-07 17:34:39 -0800438#endif
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800439
440 // Send the new window size as human-readable ASCII for debugging convenience.
441 size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d",
442 ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel);
443 shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800444}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800445
David Pursell606835a2015-09-08 17:17:02 -0700446// Used to pass multiple values to the stdin read thread.
447struct StdinReadArgs {
448 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700449 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700450 std::unique_ptr<ShellProtocol> protocol;
Elliott Hughes28416d62015-11-04 13:36:32 -0800451 char escape_char;
David Pursell606835a2015-09-08 17:17:02 -0700452};
453
David Pursell606835a2015-09-08 17:17:02 -0700454// Loops to read from stdin and push the data to the given FD.
455// The argument should be a pointer to a StdinReadArgs object. This function
456// will take ownership of the object and delete it when finished.
Josh Gaod9db09c2016-02-12 14:31:15 -0800457static void stdin_read_thread_loop(void* x) {
David Pursell606835a2015-09-08 17:17:02 -0700458 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800459
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800460#if !defined(_WIN32)
461 // Mask SIGTTIN in case we're in a backgrounded process.
Josh Gao8dcdb572015-10-23 15:03:31 -0700462 sigset_t sigset;
463 sigemptyset(&sigset);
464 sigaddset(&sigset, SIGTTIN);
465 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
466#endif
467
Spencer Low2e02dc62015-11-07 17:34:39 -0800468#if defined(_WIN32)
469 // _get_interesting_input_record_uncached() causes unix_read_interruptible()
470 // to return -1 with errno == EINTR if the window size changes.
471#else
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800472 // Unblock SIGWINCH for this thread, so our read(2) below will be
473 // interrupted if the window size changes.
474 sigset_t mask;
475 sigemptyset(&mask);
476 sigaddset(&mask, SIGWINCH);
477 pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
478#endif
479
480 // Set up the initial window size.
481 send_window_size_change(args->stdin_fd, args->protocol);
482
Elliott Hughes28416d62015-11-04 13:36:32 -0800483 char raw_buffer[BUFSIZ];
David Pursell606835a2015-09-08 17:17:02 -0700484 char* buffer_ptr = raw_buffer;
485 size_t buffer_size = sizeof(raw_buffer);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800486 if (args->protocol != nullptr) {
David Pursell606835a2015-09-08 17:17:02 -0700487 buffer_ptr = args->protocol->data();
488 buffer_size = args->protocol->data_capacity();
489 }
490
Elliott Hughes28416d62015-11-04 13:36:32 -0800491 // If we need to parse escape sequences, make life easy.
492 if (args->raw_stdin && args->escape_char != '\0') {
493 buffer_size = 1;
494 }
495
496 enum EscapeState { kMidFlow, kStartOfLine, kInEscape };
497 EscapeState state = kStartOfLine;
498
Elliott Hughesaa245492015-08-03 10:38:08 -0700499 while (true) {
Spencer Low2e02dc62015-11-07 17:34:39 -0800500 // Use unix_read_interruptible() rather than adb_read() for stdin.
501 D("stdin_read_thread_loop(): pre unix_read_interruptible(fdi=%d,...)", args->stdin_fd);
502 int r = unix_read_interruptible(args->stdin_fd, buffer_ptr,
503 buffer_size);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800504 if (r == -1 && errno == EINTR) {
505 send_window_size_change(args->stdin_fd, args->protocol);
506 continue;
507 }
Spencer Low2e02dc62015-11-07 17:34:39 -0800508 D("stdin_read_thread_loop(): post unix_read_interruptible(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700509 if (r <= 0) {
510 // Only devices using the shell protocol know to close subprocess
511 // stdin. For older devices we want to just leave the connection
512 // open, otherwise an unpredictable amount of return data could
513 // be lost due to the FD closing before all data has been received.
514 if (args->protocol) {
515 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
516 }
517 break;
518 }
Elliott Hughes28416d62015-11-04 13:36:32 -0800519 // If we made stdin raw, check input for escape sequences. In
David Pursell1ed57f02015-10-06 15:30:03 -0700520 // this situation signals like Ctrl+C are sent remotely rather than
521 // interpreted locally so this provides an emergency out if the remote
522 // process starts ignoring the signal. SSH also does this, see the
523 // "escape characters" section on the ssh man page for more info.
Elliott Hughes28416d62015-11-04 13:36:32 -0800524 if (args->raw_stdin && args->escape_char != '\0') {
525 char ch = buffer_ptr[0];
526 if (ch == args->escape_char) {
527 if (state == kStartOfLine) {
528 state = kInEscape;
529 // Swallow the escape character.
530 continue;
531 } else {
532 state = kMidFlow;
533 }
534 } else {
535 if (state == kInEscape) {
536 if (ch == '.') {
537 fprintf(stderr,"\r\n[ disconnected ]\r\n");
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800538 stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700539 exit(0);
Elliott Hughes28416d62015-11-04 13:36:32 -0800540 } else {
541 // We swallowed an escape character that wasn't part of
542 // a valid escape sequence; time to cough it up.
543 buffer_ptr[0] = args->escape_char;
544 buffer_ptr[1] = ch;
545 ++r;
David Pursell1ed57f02015-10-06 15:30:03 -0700546 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800547 }
Elliott Hughes28416d62015-11-04 13:36:32 -0800548 state = (ch == '\n' || ch == '\r') ? kStartOfLine : kMidFlow;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800549 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550 }
David Pursell606835a2015-09-08 17:17:02 -0700551 if (args->protocol) {
552 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
553 break;
554 }
555 } else {
556 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
557 break;
558 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800559 }
560 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800561}
562
David Pursell1ed57f02015-10-06 15:30:03 -0700563// Returns a shell service string with the indicated arguments and command.
564static std::string ShellServiceString(bool use_shell_protocol,
565 const std::string& type_arg,
566 const std::string& command) {
567 std::vector<std::string> args;
568 if (use_shell_protocol) {
569 args.push_back(kShellServiceArgShellProtocol);
Elliott Hughesc2252df2015-11-18 12:45:48 -0800570
571 const char* terminal_type = getenv("TERM");
572 if (terminal_type != nullptr) {
573 args.push_back(std::string("TERM=") + terminal_type);
574 }
David Pursell1ed57f02015-10-06 15:30:03 -0700575 }
576 if (!type_arg.empty()) {
577 args.push_back(type_arg);
578 }
579
580 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
581 return android::base::StringPrintf("shell%s%s:%s",
582 args.empty() ? "" : ",",
583 android::base::Join(args, ',').c_str(),
584 command.c_str());
585}
586
587// Connects to a shell on the device and read/writes data.
588//
589// Note: currently this function doesn't properly clean up resources; the
590// FD connected to the adb server is never closed and the stdin read thread
591// may never exit.
592//
593// On success returns the remote exit code if |use_shell_protocol| is true,
594// 0 otherwise. On failure returns 1.
595static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
Elliott Hughes28416d62015-11-04 13:36:32 -0800596 char escape_char,
David Pursell1ed57f02015-10-06 15:30:03 -0700597 const std::string& command) {
598 std::string service_string = ShellServiceString(use_shell_protocol,
599 type_arg, command);
600
601 // Make local stdin raw if the device allocates a PTY, which happens if:
602 // 1. We are explicitly asking for a PTY shell, or
603 // 2. We don't specify shell type and are starting an interactive session.
604 bool raw_stdin = (type_arg == kShellServiceArgPty ||
605 (type_arg.empty() && command.empty()));
606
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700607 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700608 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700609 if (fd < 0) {
610 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800611 return 1;
612 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613
David Pursell606835a2015-09-08 17:17:02 -0700614 StdinReadArgs* args = new StdinReadArgs;
615 if (!args) {
616 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700617 return 1;
618 }
David Pursell1ed57f02015-10-06 15:30:03 -0700619 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700620 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700621 args->raw_stdin = raw_stdin;
Elliott Hughes28416d62015-11-04 13:36:32 -0800622 args->escape_char = escape_char;
David Pursell606835a2015-09-08 17:17:02 -0700623 if (use_shell_protocol) {
624 args->protocol.reset(new ShellProtocol(args->write_fd));
625 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700626
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800627 if (raw_stdin) stdin_raw_init();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800628
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800629#if !defined(_WIN32)
630 // Ensure our process is notified if the local window size changes.
631 // We use sigaction(2) to ensure that the SA_RESTART flag is not set,
632 // because the whole reason we're sending signals is to unblock the read(2)!
633 // That also means we don't need to do anything in the signal handler:
634 // the side effect of delivering the signal is all we need.
635 struct sigaction sa;
636 memset(&sa, 0, sizeof(sa));
637 sa.sa_handler = [](int) {};
638 sa.sa_flags = 0;
639 sigaction(SIGWINCH, &sa, nullptr);
640
641 // Now block SIGWINCH in this thread (the main thread) and all threads spawned
642 // from it. The stdin read thread will unblock this signal to ensure that it's
643 // the thread that receives the signal.
644 sigset_t mask;
645 sigemptyset(&mask);
646 sigaddset(&mask, SIGWINCH);
647 pthread_sigmask(SIG_BLOCK, &mask, nullptr);
648#endif
649
650 // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
Josh Gaoe1dacfc2017-04-12 17:00:49 -0700651 std::thread(stdin_read_thread_loop, args).detach();
652 int exit_code = read_and_dump(fd, use_shell_protocol);
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700653
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800654 // TODO: properly exit stdin_read_thread_loop and close |fd|.
David Pursell1ed57f02015-10-06 15:30:03 -0700655
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800656 // TODO: we should probably install signal handlers for this.
657 // TODO: can we use atexit? even on Windows?
658 if (raw_stdin) stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700659
David Pursell606835a2015-09-08 17:17:02 -0700660 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800661}
662
Josh Gaof3f6a1d2016-01-31 19:12:26 -0800663static int adb_shell(int argc, const char** argv) {
David Pursell0aacbbe2016-01-21 19:56:50 -0800664 FeatureSet features;
Josh Gaof3f6a1d2016-01-31 19:12:26 -0800665 std::string error;
Josh Gaof3f6a1d2016-01-31 19:12:26 -0800666 if (!adb_get_feature_set(&features, &error)) {
667 fprintf(stderr, "error: %s\n", error.c_str());
David Pursell0aacbbe2016-01-21 19:56:50 -0800668 return 1;
669 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800670
Elliott Hughescabfa112016-10-19 14:47:11 -0700671 enum PtyAllocationMode { kPtyAuto, kPtyNo, kPtyYes, kPtyDefinitely };
672
673 // Defaults.
674 char escape_char = '~'; // -e
675 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2); // -x
676 PtyAllocationMode tty = use_shell_protocol ? kPtyAuto : kPtyDefinitely; // -t/-T
Elliott Hughes6452a892015-04-29 12:28:13 -0700677
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800678 // Parse shell-specific command-line options.
Elliott Hughescabfa112016-10-19 14:47:11 -0700679 argv[0] = "adb shell"; // So getopt(3) error messages start "adb shell".
680 optind = 1; // argv[0] is always "shell", so set `optind` appropriately.
681 int opt;
682 while ((opt = getopt(argc, const_cast<char**>(argv), "+e:ntTx")) != -1) {
683 switch (opt) {
684 case 'e':
685 if (!(strlen(optarg) == 1 || strcmp(optarg, "none") == 0)) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700686 return syntax_error("-e requires a single-character argument or 'none'");
Elliott Hughescabfa112016-10-19 14:47:11 -0700687 }
688 escape_char = (strcmp(optarg, "none") == 0) ? 0 : optarg[0];
689 break;
690 case 'n':
691 close_stdin();
692 break;
693 case 'x':
694 // This option basically asks for historical behavior, so set options that
695 // correspond to the historical defaults. This is slightly weird in that -Tx
696 // is fine (because we'll undo the -T) but -xT isn't, but that does seem to
697 // be our least worst choice...
698 use_shell_protocol = false;
699 tty = kPtyDefinitely;
700 escape_char = '~';
701 break;
702 case 't':
703 // Like ssh, -t arguments are cumulative so that multiple -t's
704 // are needed to force a PTY.
705 tty = (tty >= kPtyYes) ? kPtyDefinitely : kPtyYes;
706 break;
707 case 'T':
708 tty = kPtyNo;
709 break;
710 default:
711 // getopt(3) already printed an error message for us.
Elliott Hughes28416d62015-11-04 13:36:32 -0800712 return 1;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800713 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700714 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715
Elliott Hughescabfa112016-10-19 14:47:11 -0700716 bool is_interactive = (optind == argc);
David Pursell57dd5ae2016-01-27 16:07:52 -0800717
Elliott Hughescabfa112016-10-19 14:47:11 -0700718 std::string shell_type_arg = kShellServiceArgPty;
719 if (tty == kPtyNo) {
720 shell_type_arg = kShellServiceArgRaw;
721 } else if (tty == kPtyAuto) {
722 // If stdin isn't a TTY, default to a raw shell; this lets
723 // things like `adb shell < my_script.sh` work as expected.
724 // Non-interactive shells should also not have a pty.
725 if (!unix_isatty(STDIN_FILENO) || !is_interactive) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800726 shell_type_arg = kShellServiceArgRaw;
Elliott Hughescabfa112016-10-19 14:47:11 -0700727 }
728 } else if (tty == kPtyYes) {
729 // A single -t arg isn't enough to override implicit -T.
730 if (!unix_isatty(STDIN_FILENO)) {
731 fprintf(stderr,
732 "Remote PTY will not be allocated because stdin is not a terminal.\n"
733 "Use multiple -t options to force remote PTY allocation.\n");
734 shell_type_arg = kShellServiceArgRaw;
735 }
736 }
737
738 D("shell -e 0x%x t=%d use_shell_protocol=%s shell_type_arg=%s\n",
739 escape_char, tty,
740 use_shell_protocol ? "true" : "false",
741 (shell_type_arg == kShellServiceArgPty) ? "pty" : "raw");
742
743 // Raw mode is only supported when talking to a new device *and* using the shell protocol.
744 if (!use_shell_protocol) {
745 if (shell_type_arg != kShellServiceArgPty) {
746 fprintf(stderr, "error: %s only supports allocating a pty\n",
747 !CanUseFeature(features, kFeatureShell2) ? "device" : "-x");
748 return 1;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800749 } else {
Elliott Hughescabfa112016-10-19 14:47:11 -0700750 // If we're not using the shell protocol, the type argument must be empty.
751 shell_type_arg = "";
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800752 }
David Pursell71c83122015-09-14 15:33:50 -0700753 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800754
755 std::string command;
Elliott Hughescabfa112016-10-19 14:47:11 -0700756 if (optind < argc) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800757 // We don't escape here, just like ssh(1). http://b/20564385.
Elliott Hughescabfa112016-10-19 14:47:11 -0700758 command = android::base::Join(std::vector<const char*>(argv + optind, argv + argc), ' ');
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800759 }
760
Elliott Hughes28416d62015-11-04 13:36:32 -0800761 return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command);
David Pursell71c83122015-09-14 15:33:50 -0700762}
763
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700764static int adb_download_buffer(const char* service, const char* filename) {
765 std::string content;
766 if (!android::base::ReadFileToString(filename, &content)) {
767 fprintf(stderr, "error: couldn't read %s: %s\n", filename, strerror(errno));
768 return -1;
769 }
770
771 const uint8_t* data = reinterpret_cast<const uint8_t*>(content.data());
772 unsigned sz = content.size();
773
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700774 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700775 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700776 if (fd < 0) {
777 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800778 return -1;
779 }
780
781 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800782 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800783
Elliott Hughes6452a892015-04-29 12:28:13 -0700784 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800785 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800786
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700787 const char* x = strrchr(service, ':');
788 if (x) service = x + 1;
Doug Zongker447f0612012-01-09 14:54:53 -0800789
Elliott Hughes6452a892015-04-29 12:28:13 -0700790 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800791 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700792 if (!WriteFdExactly(fd, ptr, xfer)) {
793 std::string error;
794 adb_status(fd, &error);
795 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700796 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800797 return -1;
798 }
799 sz -= xfer;
800 ptr += xfer;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700801 printf("sending: '%s' %4d%% \r", filename, (int)(100LL - ((100LL * sz) / (total))));
802 fflush(stdout);
Doug Zongker447f0612012-01-09 14:54:53 -0800803 }
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700804 printf("\n");
Doug Zongker447f0612012-01-09 14:54:53 -0800805
Elliott Hughese67f1f82015-04-30 17:32:03 -0700806 if (!adb_status(fd, &error)) {
807 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700808 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800809 return -1;
810 }
811
812 adb_close(fd);
813 return 0;
814}
815
Doug Zongker71fe5842014-06-26 15:35:36 -0700816#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
817
818/*
819 * The sideload-host protocol serves the data in a file (given on the
820 * command line) to the client, using a simple protocol:
821 *
822 * - The connect message includes the total number of bytes in the
823 * file and a block size chosen by us.
824 *
825 * - The other side sends the desired block number as eight decimal
826 * digits (eg "00000023" for block 23). Blocks are numbered from
827 * zero.
828 *
829 * - We send back the data of the requested block. The last block is
830 * likely to be partial; when the last block is requested we only
831 * send the part of the block that exists, it's not padded up to the
832 * block size.
833 *
834 * - When the other side sends "DONEDONE" instead of a block number,
835 * we hang up.
836 */
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700837static int adb_sideload_host(const char* filename) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700838 // TODO: use a LinePrinter instead...
839 fprintf(stdout, "opening '%s'...\n", filename);
840 fflush(stdout);
841
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700842 struct stat sb;
843 if (stat(filename, &sb) == -1) {
844 fprintf(stderr, "failed to stat file %s: %s\n", filename, strerror(errno));
845 return -1;
846 }
847 unique_fd package_fd(adb_open(filename, O_RDONLY));
848 if (package_fd == -1) {
849 fprintf(stderr, "failed to open file %s: %s\n", filename, strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700850 return -1;
851 }
852
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700853 fprintf(stdout, "connecting...\n");
854 fflush(stdout);
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 Hughes14415142016-06-15 14:45:34 -0700862 fprintf(stderr, "falling back to older sideload method...\n");
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700863 return adb_download_buffer("sideload", filename);
Doug Zongker71fe5842014-06-26 15:35:36 -0700864 }
865
Elliott Hughese8b663f2016-05-26 22:43:19 -0700866 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700867 adb_setsockopt(device_fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
868
869 char buf[SIDELOAD_HOST_BLOCK_SIZE];
Doug Zongker71fe5842014-06-26 15:35:36 -0700870
Elliott Hughese8b663f2016-05-26 22:43:19 -0700871 size_t xfer = 0;
872 int last_percent = -1;
Elliott Hughesa7090b92015-04-17 17:03:59 -0700873 while (true) {
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700874 if (!ReadFdExactly(device_fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700875 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Elliott Hughese8b663f2016-05-26 22:43:19 -0700876 return -1;
Doug Zongker71fe5842014-06-26 15:35:36 -0700877 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700878 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700879
Elliott Hughes6452a892015-04-29 12:28:13 -0700880 if (strcmp("DONEDONE", buf) == 0) {
Elliott Hughese8b663f2016-05-26 22:43:19 -0700881 printf("\rTotal xfer: %.2fx%*s\n",
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700882 static_cast<double>(xfer) / (sb.st_size ? sb.st_size : 1),
883 static_cast<int>(strlen(filename) + 10), "");
Elliott Hughese8b663f2016-05-26 22:43:19 -0700884 return 0;
Doug Zongker71fe5842014-06-26 15:35:36 -0700885 }
886
Doug Zongker71fe5842014-06-26 15:35:36 -0700887 int block = strtol(buf, NULL, 10);
888
889 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700890 if (offset >= static_cast<size_t>(sb.st_size)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700891 fprintf(stderr, "* attempt to read block %d past end\n", block);
Elliott Hughese8b663f2016-05-26 22:43:19 -0700892 return -1;
Doug Zongker71fe5842014-06-26 15:35:36 -0700893 }
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700894
Doug Zongker71fe5842014-06-26 15:35:36 -0700895 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700896 if ((offset + SIDELOAD_HOST_BLOCK_SIZE) > static_cast<size_t>(sb.st_size)) {
897 to_write = sb.st_size - offset;
Doug Zongker71fe5842014-06-26 15:35:36 -0700898 }
899
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700900 if (adb_lseek(package_fd, offset, SEEK_SET) != static_cast<int>(offset)) {
901 fprintf(stderr, "* failed to seek to package block: %s\n", strerror(errno));
902 return -1;
903 }
904 if (!ReadFdExactly(package_fd, buf, to_write)) {
905 fprintf(stderr, "* failed to read package block: %s\n", strerror(errno));
906 return -1;
907 }
908
909 if (!WriteFdExactly(device_fd, buf, to_write)) {
910 adb_status(device_fd, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700911 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Elliott Hughese8b663f2016-05-26 22:43:19 -0700912 return -1;
Doug Zongker71fe5842014-06-26 15:35:36 -0700913 }
914 xfer += to_write;
915
916 // For normal OTA packages, we expect to transfer every byte
917 // twice, plus a bit of overhead (one read during
918 // verification, one read of each byte for installation, plus
919 // extra access to things like the zip central directory).
920 // This estimate of the completion becomes 100% when we've
921 // transferred ~2.13 (=100/47) times the package size.
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700922 int percent = static_cast<int>(xfer * 47LL / (sb.st_size ? sb.st_size : 1));
Doug Zongker71fe5842014-06-26 15:35:36 -0700923 if (percent != last_percent) {
Elliott Hughesee1ac7102017-03-21 17:14:18 -0700924 printf("\rserving: '%s' (~%d%%) ", filename, percent);
Doug Zongker71fe5842014-06-26 15:35:36 -0700925 fflush(stdout);
926 last_percent = percent;
927 }
928 }
Doug Zongker71fe5842014-06-26 15:35:36 -0700929}
930
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800931/**
932 * Run ppp in "notty" mode against a resource listed as the first parameter
933 * eg:
934 *
935 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
936 *
937 */
Elliott Hughes58305772015-04-17 13:57:15 -0700938static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800939#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800940 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
941 return -1;
942#else
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700943 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 -0800944
Dan Albertbac34742015-02-25 17:51:28 -0800945 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700946 std::string error;
947 int fd = adb_connect(adb_service_name, &error);
948 if (fd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -0700949 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 -0800950 return 1;
951 }
952
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700953 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800954
955 if (pid < 0) {
956 perror("from fork()");
957 return 1;
958 } else if (pid == 0) {
959 int err;
960 int i;
961 const char **ppp_args;
962
963 // copy args
964 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
965 ppp_args[0] = "pppd";
966 for (i = 2 ; i < argc ; i++) {
967 //argv[2] and beyond become ppp_args[1] and beyond
968 ppp_args[i - 1] = argv[i];
969 }
970 ppp_args[i-1] = NULL;
971
972 // child side
973
974 dup2(fd, STDIN_FILENO);
975 dup2(fd, STDOUT_FILENO);
976 adb_close(STDERR_FILENO);
977 adb_close(fd);
978
979 err = execvp("pppd", (char * const *)ppp_args);
980
981 if (err < 0) {
982 perror("execing pppd");
983 }
984 exit(-1);
985 } else {
986 // parent side
987
988 adb_close(fd);
989 return 0;
990 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800991#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992}
993
Josh Gao08881e72016-04-13 12:14:16 -0700994static bool wait_for_device(const char* service, TransportType t, const char* serial) {
995 std::vector<std::string> components = android::base::Split(service, "-");
996 if (components.size() < 3 || components.size() > 4) {
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100997 fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
998 return false;
999 }
1000
Elliott Hughes2b101112015-05-04 19:29:32 -07001001 // Was the caller vague about what they'd like us to wait for?
1002 // If so, check they weren't more specific in their choice of transport type.
Josh Gao08881e72016-04-13 12:14:16 -07001003 if (components.size() == 3) {
1004 auto it = components.begin() + 2;
Elliott Hughes2b101112015-05-04 19:29:32 -07001005 if (t == kTransportUsb) {
Josh Gao08881e72016-04-13 12:14:16 -07001006 components.insert(it, "usb");
Elliott Hughes2b101112015-05-04 19:29:32 -07001007 } else if (t == kTransportLocal) {
Josh Gao08881e72016-04-13 12:14:16 -07001008 components.insert(it, "local");
Elliott Hughes2b101112015-05-04 19:29:32 -07001009 } else {
Josh Gao08881e72016-04-13 12:14:16 -07001010 components.insert(it, "any");
Elliott Hughes2b101112015-05-04 19:29:32 -07001011 }
Josh Gao08881e72016-04-13 12:14:16 -07001012 } else if (components[2] != "any" && components[2] != "local" && components[2] != "usb") {
1013 fprintf(stderr, "adb: unknown type %s; expected 'any', 'local', or 'usb'\n",
1014 components[2].c_str());
Leo Sartre1fbc9db2015-11-27 18:56:48 +01001015 return false;
1016 }
1017
Josh Gao86441c32016-04-13 12:18:58 -07001018 if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
1019 components[3] != "recovery" && components[3] != "sideload") {
Josh Gao08881e72016-04-13 12:14:16 -07001020 fprintf(stderr,
1021 "adb: unknown state %s; "
Josh Gao86441c32016-04-13 12:18:58 -07001022 "expected 'any', 'bootloader', 'device', 'recovery', or 'sideload'\n",
Josh Gao08881e72016-04-13 12:14:16 -07001023 components[3].c_str());
1024 return false;
1025 }
1026
1027 std::string cmd = format_host_command(android::base::Join(components, "-").c_str(), t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -07001028 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -07001029}
1030
Josh Gao06c73ae2016-03-04 15:16:18 -08001031static bool adb_root(const char* command) {
1032 std::string error;
Josh Gao06c73ae2016-03-04 15:16:18 -08001033
Elliott Hughese8b663f2016-05-26 22:43:19 -07001034 unique_fd fd(adb_connect(android::base::StringPrintf("%s:", command), &error));
1035 if (fd < 0) {
Josh Gao06c73ae2016-03-04 15:16:18 -08001036 fprintf(stderr, "adb: unable to connect for %s: %s\n", command, error.c_str());
1037 return false;
1038 }
1039
1040 // Figure out whether we actually did anything.
1041 char buf[256];
1042 char* cur = buf;
1043 ssize_t bytes_left = sizeof(buf);
1044 while (bytes_left > 0) {
Elliott Hughese8b663f2016-05-26 22:43:19 -07001045 ssize_t bytes_read = adb_read(fd, cur, bytes_left);
Josh Gao06c73ae2016-03-04 15:16:18 -08001046 if (bytes_read == 0) {
1047 break;
1048 } else if (bytes_read < 0) {
1049 fprintf(stderr, "adb: error while reading for %s: %s\n", command, strerror(errno));
1050 return false;
1051 }
1052 cur += bytes_read;
1053 bytes_left -= bytes_read;
1054 }
1055
1056 if (bytes_left == 0) {
1057 fprintf(stderr, "adb: unexpected output length for %s\n", command);
1058 return false;
1059 }
1060
1061 fflush(stdout);
1062 WriteFdExactly(STDOUT_FILENO, buf, sizeof(buf) - bytes_left);
1063 if (cur != buf && strstr(buf, "restarting") == nullptr) {
1064 return true;
1065 }
1066
Josh Gao05824732016-06-16 14:00:09 -07001067 // Give adbd some time to kill itself and come back up.
1068 // 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 -08001069 std::this_thread::sleep_for(3s);
Josh Gao05824732016-06-16 14:00:09 -07001070 return true;
Josh Gao06c73ae2016-03-04 15:16:18 -08001071}
1072
Felipe Leme698e0652016-07-19 17:07:22 -07001073int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
Felipe Leme0d4f0502016-07-26 12:14:39 -07001074 bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001075 int fd;
David Pursell0aacbbe2016-01-21 19:56:50 -08001076 bool use_shell_protocol = false;
1077
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001078 while (true) {
David Pursell0aacbbe2016-01-21 19:56:50 -08001079 bool attempt_connection = true;
1080
Felipe Leme0d4f0502016-07-26 12:14:39 -07001081 // Use shell protocol if it's supported and the caller doesn't explicitly
1082 // disable it.
David Pursell0aacbbe2016-01-21 19:56:50 -08001083 if (!disable_shell_protocol) {
1084 FeatureSet features;
Josh Gaof3f6a1d2016-01-31 19:12:26 -08001085 std::string error;
1086 if (adb_get_feature_set(&features, &error)) {
David Pursell0aacbbe2016-01-21 19:56:50 -08001087 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
1088 } else {
1089 // Device was unreachable.
1090 attempt_connection = false;
1091 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001092 }
David Pursell0aacbbe2016-01-21 19:56:50 -08001093
1094 if (attempt_connection) {
1095 std::string error;
1096 std::string service_string = ShellServiceString(use_shell_protocol, "", command);
1097
1098 fd = adb_connect(service_string, &error);
1099 if (fd >= 0) {
1100 break;
1101 }
1102 }
1103
Felipe Leme0d4f0502016-07-26 12:14:39 -07001104 fprintf(stderr, "- waiting for device -\n");
Josh Gaob6117c42016-02-24 15:16:17 -08001105 if (!wait_for_device("wait-for-device", transport_type, serial)) {
1106 return 1;
1107 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001108 }
1109
Felipe Leme0d4f0502016-07-26 12:14:39 -07001110 int exit_code = read_and_dump(fd, use_shell_protocol, callback);
David Pursell71c83122015-09-14 15:33:50 -07001111
1112 if (adb_close(fd) < 0) {
1113 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001114 }
David Pursell71c83122015-09-14 15:33:50 -07001115
1116 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001117}
1118
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001119static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001120 char* log_tags = getenv("ANDROID_LOG_TAGS");
1121 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001122
David Pursell70ef7b42015-09-30 13:35:42 -07001123 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001124
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001125 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001126 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -08001127 }
1128
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001129 --argc;
1130 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001131 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001132 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133 }
1134
David Pursell70ef7b42015-09-30 13:35:42 -07001135 // No need for shell protocol with logcat, always disable for simplicity.
1136 return send_shell_command(transport, serial, cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137}
1138
Christopher Tatec42f1bb2016-07-06 13:22:22 -07001139static void write_zeros(int bytes, int fd) {
1140 int old_stdin_mode = -1;
1141 int old_stdout_mode = -1;
1142 char* buf = (char*) calloc(1, bytes);
1143 if (buf == nullptr) fatal("couldn't allocate buffer for write_zeros");
1144
1145 D("write_zeros(%d) -> %d", bytes, fd);
1146
1147 stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
1148
1149 if (fd == STDOUT_FILENO) {
1150 fwrite(buf, 1, bytes, stdout);
1151 fflush(stdout);
1152 } else {
1153 adb_write(fd, buf, bytes);
1154 }
1155
1156 stdinout_raw_prologue(-1, fd, old_stdin_mode, old_stdout_mode);
1157
1158 D("write_zeros() finished");
1159 free(buf);
1160}
1161
Dan Albertbac34742015-02-25 17:51:28 -08001162static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -07001163 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -07001164
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001165 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001166 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001167 if (!strcmp("-f", argv[i])) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001168 if (i == argc - 1) return syntax_error("backup -f passed with no filename");
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001169 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001170 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001171 argv[i++] = argv[j++];
1172 }
1173 argc -= 2;
1174 argv[argc] = NULL;
1175 }
Christopher Tated2f54152011-04-21 12:53:28 -07001176 }
1177
Elliott Hughes56e68132015-11-13 11:04:10 -08001178 // Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
1179 // a list of packages is required.
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001180 if (argc < 2) return syntax_error("backup either needs a list of packages or -all/-shared");
Christopher Tatebb86bc52011-08-22 17:12:08 -07001181
Christopher Tateb1dfffe2011-12-08 19:04:34 -08001182 adb_unlink(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001183 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -07001184 if (outFd < 0) {
Elliott Hughes56e68132015-11-13 11:04:10 -08001185 fprintf(stderr, "adb: backup unable to create file '%s': %s\n", filename, strerror(errno));
1186 return EXIT_FAILURE;
Christopher Tated2f54152011-04-21 12:53:28 -07001187 }
1188
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001189 std::string cmd = "backup:";
1190 --argc;
1191 ++argv;
1192 while (argc-- > 0) {
1193 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -07001194 }
1195
Yabin Cui7a3f8d62015-09-02 17:44:28 -07001196 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001197 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001198 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -07001199 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001200 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -07001201 adb_close(outFd);
Elliott Hughes56e68132015-11-13 11:04:10 -08001202 return EXIT_FAILURE;
Christopher Tated2f54152011-04-21 12:53:28 -07001203 }
1204
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001205 fprintf(stdout, "Now unlock your device and confirm the backup operation...\n");
Elliott Hughes56e68132015-11-13 11:04:10 -08001206 fflush(stdout);
1207
Christopher Tated2f54152011-04-21 12:53:28 -07001208 copy_to_file(fd, outFd);
1209
1210 adb_close(fd);
1211 adb_close(outFd);
Elliott Hughes56e68132015-11-13 11:04:10 -08001212 return EXIT_SUCCESS;
Christopher Tated2f54152011-04-21 12:53:28 -07001213}
1214
Dan Albertbac34742015-02-25 17:51:28 -08001215static int restore(int argc, const char** argv) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001216 if (argc != 2) return syntax_error("restore requires an argument");
Christopher Tate702967a2011-05-17 15:52:54 -07001217
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001218 const char* filename = argv[1];
1219 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -07001220 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001221 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -07001222 return -1;
1223 }
1224
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001225 std::string error;
1226 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -07001227 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001228 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -07001229 adb_close(tarFd);
1230 return -1;
1231 }
1232
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001233 fprintf(stdout, "Now unlock your device and confirm the restore operation.\n");
1234 fflush(stdout);
1235
Christopher Tate702967a2011-05-17 15:52:54 -07001236 copy_to_file(tarFd, fd);
1237
Christopher Tatec42f1bb2016-07-06 13:22:22 -07001238 // Provide an in-band EOD marker in case the archive file is malformed
1239 write_zeros(512*2, fd);
1240
Josh Gao5767d0d2016-03-04 15:51:03 -08001241 // Wait until the other side finishes, or it'll get sent SIGHUP.
1242 copy_to_file(fd, STDOUT_FILENO);
1243
Christopher Tate702967a2011-05-17 15:52:54 -07001244 adb_close(fd);
1245 adb_close(tarFd);
1246 return 0;
1247}
1248
Josh Gao05786772015-10-30 16:57:19 -07001249static void parse_push_pull_args(const char** arg, int narg,
1250 std::vector<const char*>* srcs,
1251 const char** dst, bool* copy_attrs) {
1252 *copy_attrs = false;
Mark Lindner76f2a932014-03-11 17:55:59 -07001253
Josh Gao05786772015-10-30 16:57:19 -07001254 srcs->clear();
1255 bool ignore_flags = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001256 while (narg > 0) {
Josh Gao05786772015-10-30 16:57:19 -07001257 if (ignore_flags || *arg[0] != '-') {
1258 srcs->push_back(*arg);
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001259 } else {
Josh Gao05786772015-10-30 16:57:19 -07001260 if (!strcmp(*arg, "-p")) {
1261 // Silently ignore for backwards compatibility.
1262 } else if (!strcmp(*arg, "-a")) {
1263 *copy_attrs = true;
1264 } else if (!strcmp(*arg, "--")) {
1265 ignore_flags = true;
1266 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001267 syntax_error("unrecognized option '%s'", *arg);
Josh Gao05786772015-10-30 16:57:19 -07001268 exit(1);
1269 }
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001270 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001271 ++arg;
1272 --narg;
1273 }
1274
Josh Gao05786772015-10-30 16:57:19 -07001275 if (srcs->size() > 1) {
1276 *dst = srcs->back();
1277 srcs->pop_back();
Mark Lindner76f2a932014-03-11 17:55:59 -07001278 }
1279}
1280
Elliott Hughes6452a892015-04-29 12:28:13 -07001281static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001282 std::string error;
1283 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001284 if (fd < 0) {
1285 fprintf(stderr, "error: %s\n", error.c_str());
1286 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001287 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001288 read_and_dump(fd);
1289 adb_close(fd);
1290 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001291}
1292
Elliott Hughes6452a892015-04-29 12:28:13 -07001293static int adb_query_command(const std::string& command) {
1294 std::string result;
1295 std::string error;
1296 if (!adb_query(command, &result, &error)) {
1297 fprintf(stderr, "error: %s\n", error.c_str());
1298 return 1;
1299 }
1300 printf("%s\n", result.c_str());
1301 return 0;
1302}
1303
Spencer Lowa13df302015-09-07 16:20:13 -07001304// Disallow stdin, stdout, and stderr.
1305static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1306#ifdef _WIN32
1307 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1308 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1309 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1310 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1311#else
1312 return ack_reply_fd > 2;
1313#endif
1314}
1315
Todd Kennedy248722e2016-07-20 16:22:37 -07001316static bool _use_legacy_install() {
1317 FeatureSet features;
1318 std::string error;
1319 if (!adb_get_feature_set(&features, &error)) {
1320 fprintf(stderr, "error: %s\n", error.c_str());
1321 return true;
1322 }
1323 return !CanUseFeature(features, kFeatureCmd);
1324}
1325
Elliott Hughescabfa112016-10-19 14:47:11 -07001326int adb_commandline(int argc, const char** argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001327 int no_daemon = 0;
1328 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001329 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001331 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001332 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001333
Elliott Hughes65433da2015-11-18 18:07:48 -08001334#if !defined(_WIN32)
1335 // We'd rather have EPIPE than SIGPIPE.
1336 signal(SIGPIPE, SIG_IGN);
1337#endif
1338
Josh Gao9c869b52016-08-25 16:00:22 -07001339 const char* server_host_str = nullptr;
1340 const char* server_port_str = nullptr;
1341 const char* server_socket_str = nullptr;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001342
Elliott Hughes8d28e192015-10-07 14:55:10 -07001343 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1344 const char* serial = nullptr;
1345
Riley Andrews98f58e82014-12-05 17:37:24 -08001346 while (argc > 0) {
1347 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001348 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001349 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001350 no_daemon = 1;
1351 } else if (!strcmp(argv[0], "fork-server")) {
1352 /* this is a special flag used only when the ADB client launches the ADB Server */
1353 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001354 } else if (!strcmp(argv[0], "--reply-fd")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001355 if (argc < 2) return syntax_error("--reply-fd requires an argument");
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001356 const char* reply_fd_str = argv[1];
1357 argc--;
1358 argv++;
1359 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001360 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001361 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001362 return 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001363 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1365 if (isdigit(argv[0][2])) {
1366 serial = argv[0] + 2;
1367 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001368 if (argc < 2 || argv[0][2] != '\0') return syntax_error("-s requires an argument");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001369 serial = argv[1];
1370 argc--;
1371 argv++;
1372 }
1373 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001374 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001375 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001376 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001377 } else if (!strcmp(argv[0],"-a")) {
1378 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001379 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001380 if (argv[0][2] == '\0') {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001381 if (argc < 2) return syntax_error("-H requires an argument");
Josh Gao9c869b52016-08-25 16:00:22 -07001382 server_host_str = argv[1];
Matt Gumbeld7b33082012-11-14 10:16:17 -08001383 argc--;
1384 argv++;
1385 } else {
Josh Gao9c869b52016-08-25 16:00:22 -07001386 server_host_str = argv[0] + 2;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001387 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001388 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001389 if (argv[0][2] == '\0') {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001390 if (argc < 2) return syntax_error("-P requires an argument");
Matt Gumbeld7b33082012-11-14 10:16:17 -08001391 server_port_str = argv[1];
1392 argc--;
1393 argv++;
1394 } else {
1395 server_port_str = argv[0] + 2;
1396 }
Josh Gao9c869b52016-08-25 16:00:22 -07001397 } else if (!strcmp(argv[0], "-L")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001398 if (argc < 2) return syntax_error("-L requires an argument");
Josh Gao9c869b52016-08-25 16:00:22 -07001399 server_socket_str = argv[1];
1400 argc--;
1401 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 } else {
Josh Gao9c869b52016-08-25 16:00:22 -07001403 /* out of recognized modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001404 break;
1405 }
1406 argc--;
1407 argv++;
1408 }
1409
Josh Gao9c869b52016-08-25 16:00:22 -07001410 if ((server_host_str || server_port_str) && server_socket_str) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001411 return syntax_error("-L is incompatible with -H or -P");
Josh Gao9c869b52016-08-25 16:00:22 -07001412 }
1413
1414 // If -L, -H, or -P are specified, ignore environment variables.
1415 // Otherwise, prefer ADB_SERVER_SOCKET over ANDROID_ADB_SERVER_ADDRESS/PORT.
Tao Wu135f4ab2016-09-16 13:01:24 -07001416 if (!server_host_str && !server_port_str && !server_socket_str) {
1417 server_socket_str = getenv("ADB_SERVER_SOCKET");
Josh Gao9c869b52016-08-25 16:00:22 -07001418 }
1419
1420 if (!server_socket_str) {
1421 // tcp:1234 and tcp:localhost:1234 are different with -a, so don't default to localhost
1422 server_host_str = server_host_str ? server_host_str : getenv("ANDROID_ADB_SERVER_ADDRESS");
1423
Tao Wu135f4ab2016-09-16 13:01:24 -07001424 int server_port = DEFAULT_ADB_PORT;
Josh Gao9c869b52016-08-25 16:00:22 -07001425 server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
Tao Wu135f4ab2016-09-16 13:01:24 -07001426 if (server_port_str && strlen(server_port_str) > 0) {
1427 if (!android::base::ParseInt(server_port_str, &server_port, 1, 65535)) {
1428 fprintf(stderr,
1429 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive"
1430 " number less than 65535. Got \"%s\"\n",
1431 server_port_str);
1432 exit(1);
1433 }
1434 }
Josh Gao9c869b52016-08-25 16:00:22 -07001435
1436 int rc;
1437 char* temp;
1438 if (server_host_str) {
Tao Wu135f4ab2016-09-16 13:01:24 -07001439 rc = asprintf(&temp, "tcp:%s:%d", server_host_str, server_port);
Josh Gao9c869b52016-08-25 16:00:22 -07001440 } else {
Tao Wu135f4ab2016-09-16 13:01:24 -07001441 rc = asprintf(&temp, "tcp:%d", server_port);
Josh Gao9c869b52016-08-25 16:00:22 -07001442 }
1443 if (rc < 0) {
1444 fatal("failed to allocate server socket specification");
1445 }
1446 server_socket_str = temp;
1447 }
1448
1449 adb_set_socket_spec(server_socket_str);
1450
Elliott Hughes8d28e192015-10-07 14:55:10 -07001451 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1452 if (transport_type == kTransportAny && serial == nullptr) {
1453 serial = getenv("ANDROID_SERIAL");
1454 }
1455
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001456 adb_set_transport(transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001457
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001458 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001459 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001460 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001461 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001462 return 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001463 }
Josh Gao9c869b52016-08-25 16:00:22 -07001464 r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001465 } else {
Josh Gao9c869b52016-08-25 16:00:22 -07001466 r = launch_server(server_socket_str);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001467 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001468 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001469 fprintf(stderr,"* could not start server *\n");
1470 }
1471 return r;
1472 }
1473
Riley Andrews98f58e82014-12-05 17:37:24 -08001474 if (argc == 0) {
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001475 help();
1476 return 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477 }
1478
Riley Andrewsc8514c82014-12-05 17:32:46 -08001479 /* handle wait-for-* prefix */
1480 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001481 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001482
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001483 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001484 return 1;
1485 }
1486
Elliott Hughes2b101112015-05-04 19:29:32 -07001487 // Allow a command to be run after wait-for-device,
1488 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001489 if (argc == 1) {
1490 return 0;
1491 }
1492
1493 /* Fall through */
1494 argc--;
1495 argv++;
1496 }
1497
1498 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001499 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001500 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001501 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001502 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001503 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001504 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001505 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001506 return syntax_error("adb devices [-l]");
Scott Andersone109d262012-04-20 11:21:14 -07001507 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001508
1509 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1510 printf("List of devices attached\n");
1511 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001512 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001513 else if (!strcmp(argv[0], "connect")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001514 if (argc != 2) return syntax_error("adb connect <host>[:<port>]");
Elliott Hughes6452a892015-04-29 12:28:13 -07001515
1516 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1517 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001518 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001519 else if (!strcmp(argv[0], "disconnect")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001520 if (argc > 2) return syntax_error("adb disconnect [<host>[:<port>]]");
Elliott Hughes6452a892015-04-29 12:28:13 -07001521
1522 std::string query = android::base::StringPrintf("host:disconnect:%s",
1523 (argc == 2) ? argv[1] : "");
1524 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001525 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001526 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001527 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001528 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -08001529 else if (!strcmp(argv[0], "shell")) {
Josh Gaof3f6a1d2016-01-31 19:12:26 -08001530 return adb_shell(argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001532 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001533 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001534
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001535 if (argc < 2) return syntax_error("adb %s command", argv[0]);
Zach Riggleccafc792016-04-14 17:18:04 -04001536
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001537 std::string cmd = "exec:";
1538 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001539 argc -= 2;
1540 argv += 2;
1541 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001542 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001543 }
1544
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001545 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001546 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001547 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001548 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001549 return -1;
1550 }
1551
1552 if (exec_in) {
1553 copy_to_file(STDIN_FILENO, fd);
1554 } else {
1555 copy_to_file(fd, STDOUT_FILENO);
1556 }
1557
1558 adb_close(fd);
1559 return 0;
1560 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001561 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001562 std::string error;
1563 int fd = _adb_connect("host:kill", &error);
Spencer Lowf18fc082015-08-11 17:05:02 -07001564 if (fd == -2) {
1565 // Failed to make network connection to server. Don't output the
1566 // network error since that is expected.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001567 fprintf(stderr,"* server not running *\n");
Spencer Lowf18fc082015-08-11 17:05:02 -07001568 // Successful exit code because the server is already "killed".
1569 return 0;
1570 } else if (fd == -1) {
1571 // Some other error.
1572 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001573 return 1;
Spencer Lowf18fc082015-08-11 17:05:02 -07001574 } else {
1575 // Successfully connected, kill command sent, okay status came back.
1576 // Server should exit() in a moment, if not already.
Spencer Low351ecd12015-10-14 17:32:44 -07001577 ReadOrderlyShutdown(fd);
Spencer Lowf18fc082015-08-11 17:05:02 -07001578 adb_close(fd);
1579 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001580 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001581 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001582 else if (!strcmp(argv[0], "sideload")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001583 if (argc != 2) return syntax_error("sideload requires an argument");
Doug Zongker71fe5842014-06-26 15:35:36 -07001584 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001585 return 1;
1586 } else {
1587 return 0;
1588 }
1589 }
Elliott Hughes19d80b82015-07-21 16:13:40 -07001590 else if (!strcmp(argv[0], "tcpip") && argc > 1) {
1591 return adb_connect_command(android::base::StringPrintf("tcpip:%s", argv[1]));
1592 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001593 else if (!strcmp(argv[0], "remount") ||
1594 !strcmp(argv[0], "reboot") ||
1595 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001596 !strcmp(argv[0], "usb") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001597 !strcmp(argv[0], "disable-verity") ||
1598 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001599 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001600 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001601 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001602 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001603 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001604 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001605 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001606 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001607 return adb_connect_command(command);
Josh Gao06c73ae2016-03-04 15:16:18 -08001608 } else if (!strcmp(argv[0], "root") || !strcmp(argv[0], "unroot")) {
1609 return adb_root(argv[0]) ? 0 : 1;
1610 } else if (!strcmp(argv[0], "bugreport")) {
Felipe Leme698e0652016-07-19 17:07:22 -07001611 Bugreport bugreport;
1612 return bugreport.DoIt(transport_type, serial, argc, argv);
Felipe Leme44a42672016-04-01 17:43:27 -07001613 } else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001614 bool reverse = !strcmp(argv[0], "reverse");
1615 ++argv;
1616 --argc;
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001617 if (argc < 1) return syntax_error("%s requires an argument", argv[0]);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001618
1619 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001620 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001621 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001622 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001623 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001624 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001625 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001626 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001627 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001628 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001629 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001630 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001631 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001632 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001633 }
1634
David Purselleaae97e2016-04-07 11:25:48 -07001635 std::string cmd, error;
Elliott Hughes424af022015-05-29 17:55:19 -07001636 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001637 if (argc != 1) return syntax_error("--list doesn't take any arguments");
Elliott Hughes424af022015-05-29 17:55:19 -07001638 return adb_query_command(host_prefix + ":list-forward");
1639 } else if (strcmp(argv[0], "--remove-all") == 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001640 if (argc != 1) return syntax_error("--remove-all doesn't take any arguments");
Elliott Hughes424af022015-05-29 17:55:19 -07001641 cmd = host_prefix + ":killforward-all";
1642 } else if (strcmp(argv[0], "--remove") == 0) {
1643 // forward --remove <local>
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001644 if (argc != 2) return syntax_error("--remove requires an argument");
Elliott Hughes424af022015-05-29 17:55:19 -07001645 cmd = host_prefix + ":killforward:" + argv[1];
1646 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1647 // forward --no-rebind <local> <remote>
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001648 if (argc != 3) return syntax_error("--no-rebind takes two arguments");
David Purselleaae97e2016-04-07 11:25:48 -07001649 if (forward_targets_are_valid(argv[1], argv[2], &error)) {
1650 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1651 }
Elliott Hughes424af022015-05-29 17:55:19 -07001652 } else {
1653 // forward <local> <remote>
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001654 if (argc != 2) return syntax_error("forward takes two arguments");
David Purselleaae97e2016-04-07 11:25:48 -07001655 if (forward_targets_are_valid(argv[0], argv[1], &error)) {
1656 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
1657 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001658 }
1659
David Purselleaae97e2016-04-07 11:25:48 -07001660 if (!error.empty()) {
1661 fprintf(stderr, "error: %s\n", error.c_str());
1662 return 1;
1663 }
1664
1665 int fd = adb_connect(cmd, &error);
1666 if (fd < 0 || !adb_status(fd, &error)) {
1667 adb_close(fd);
1668 fprintf(stderr, "error: %s\n", error.c_str());
1669 return 1;
1670 }
1671
1672 // Server or device may optionally return a resolved TCP port number.
1673 std::string resolved_port;
1674 if (ReadProtocolString(fd, &resolved_port, &error) && !resolved_port.empty()) {
1675 printf("%s\n", resolved_port.c_str());
1676 }
1677
1678 ReadOrderlyShutdown(fd);
1679 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001681 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001682 else if (!strcmp(argv[0], "ls")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001683 if (argc != 2) return syntax_error("ls requires an argument");
Elliott Hughesaa245492015-08-03 10:38:08 -07001684 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001685 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001686 else if (!strcmp(argv[0], "push")) {
Josh Gao05786772015-10-30 16:57:19 -07001687 bool copy_attrs = false;
1688 std::vector<const char*> srcs;
1689 const char* dst = nullptr;
Mark Lindner76f2a932014-03-11 17:55:59 -07001690
Josh Gao05786772015-10-30 16:57:19 -07001691 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001692 if (srcs.empty() || !dst) return syntax_error("push requires an argument");
Josh Gao05786772015-10-30 16:57:19 -07001693 return do_sync_push(srcs, dst) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001694 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0], "pull")) {
Josh Gao05786772015-10-30 16:57:19 -07001696 bool copy_attrs = false;
1697 std::vector<const char*> srcs;
1698 const char* dst = ".";
Mark Lindner76f2a932014-03-11 17:55:59 -07001699
Josh Gao05786772015-10-30 16:57:19 -07001700 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001701 if (srcs.empty()) return syntax_error("pull requires an argument");
Josh Gao05786772015-10-30 16:57:19 -07001702 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001703 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001704 else if (!strcmp(argv[0], "install")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001705 if (argc < 2) return syntax_error("install requires an argument");
Todd Kennedy248722e2016-07-20 16:22:37 -07001706 if (_use_legacy_install()) {
1707 return install_app_legacy(transport_type, serial, argc, argv);
David Pursell0aacbbe2016-01-21 19:56:50 -08001708 }
Todd Kennedy248722e2016-07-20 16:22:37 -07001709 return install_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001710 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "install-multiple")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001712 if (argc < 2) return syntax_error("install-multiple requires an argument");
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001713 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001714 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001715 else if (!strcmp(argv[0], "uninstall")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001716 if (argc < 2) return syntax_error("uninstall requires an argument");
Todd Kennedy248722e2016-07-20 16:22:37 -07001717 if (_use_legacy_install()) {
1718 return uninstall_app_legacy(transport_type, serial, argc, argv);
David Pursell0aacbbe2016-01-21 19:56:50 -08001719 }
Todd Kennedy248722e2016-07-20 16:22:37 -07001720 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001721 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001722 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001723 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001724 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001725 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001726 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001727 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001728 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001729 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001730 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001731 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001732 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001733 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001734 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001735 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001736 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001737 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001738 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001739 return syntax_error("adb sync [-l] [PARTITION]");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001740 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001741
Elliott Hughes0754cb92017-05-01 11:04:31 -07001742 if (src == "all") src = "";
1743
Elliott Hughesd236d072015-04-21 10:17:07 -07001744 if (src != "" &&
1745 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001746 return syntax_error("don't know how to sync %s partition", src.c_str());
Elliott Hughes58305772015-04-17 13:57:15 -07001747 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001748
Elliott Hughes58305772015-04-17 13:57:15 -07001749 std::string system_src_path = product_file("system");
1750 std::string data_src_path = product_file("data");
1751 std::string vendor_src_path = product_file("vendor");
1752 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001753
Elliott Hughesaa245492015-08-03 10:38:08 -07001754 bool okay = true;
1755 if (okay && (src.empty() || src == "system")) {
1756 okay = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001757 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001758 if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1759 okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001760 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001761 if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1762 okay = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001763 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001764 if (okay && (src.empty() || src == "data")) {
1765 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001766 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001767 return okay ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001768 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001769 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001770 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001771 !strcmp(argv[0],"get-serialno") ||
1772 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001773 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001774 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001775 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001776 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001777 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001778 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001779 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001780 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001781 return ppp(argc, argv);
1782 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001783 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001784 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001785 const int result = adb_connect("host:start-server", &error);
1786 if (result < 0) {
1787 fprintf(stderr, "error: %s\n", error.c_str());
1788 }
1789 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001790 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001791 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001792 return backup(argc, argv);
1793 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001794 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001795 return restore(argc, argv);
1796 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001797 else if (!strcmp(argv[0], "keygen")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001798 if (argc != 2) return syntax_error("keygen requires an argument");
Yabin Cuiaed3c612015-09-22 15:52:57 -07001799 // Always print key generation information for keygen command.
1800 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001801 return adb_auth_keygen(argv[1]);
1802 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001803 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001804 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001805 }
Josh Gaob463baf2016-05-13 18:18:23 -07001806 else if (!strcmp(argv[0], "track-jdwp")) {
1807 return adb_connect_command("track-jdwp");
1808 }
1809 else if (!strcmp(argv[0], "track-devices")) {
1810 return adb_connect_command("host:track-devices");
1811 }
1812
1813
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001814 /* "adb /?" is a common idiom under Windows */
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001815 else if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001816 help();
1817 return 0;
1818 }
Elliott Hughes2ec36b02017-02-06 16:20:30 -08001819 else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001820 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001821 return 0;
Josh Gao5d1756c2017-02-22 17:07:01 -08001822 } else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001823 // Only list the features common to both the adb client and the device.
David Pursell0aacbbe2016-01-21 19:56:50 -08001824 FeatureSet features;
Josh Gaof3f6a1d2016-01-31 19:12:26 -08001825 std::string error;
1826 if (!adb_get_feature_set(&features, &error)) {
1827 fprintf(stderr, "error: %s\n", error.c_str());
David Pursell0aacbbe2016-01-21 19:56:50 -08001828 return 1;
1829 }
1830
David Pursell4e2fd362015-09-22 10:43:08 -07001831 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001832 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001833 printf("%s\n", name.c_str());
1834 }
1835 }
1836 return 0;
Josh Gao5d1756c2017-02-22 17:07:01 -08001837 } else if (!strcmp(argv[0], "host-features")) {
1838 return adb_query_command("host:host-features");
Yabin Cui1f4ec192016-04-05 13:50:44 -07001839 } else if (!strcmp(argv[0], "reconnect")) {
1840 if (argc == 1) {
Yabin Cuib5e11412017-03-10 16:01:01 -08001841 return adb_query_command(format_host_command(argv[0], transport_type, serial));
Josh Gao22d2b3e2016-10-27 14:01:08 -07001842 } else if (argc == 2) {
1843 if (!strcmp(argv[1], "device")) {
1844 std::string err;
1845 adb_connect("reconnect", &err);
1846 return 0;
1847 } else if (!strcmp(argv[1], "offline")) {
1848 std::string err;
1849 return adb_query_command("host:reconnect-offline");
1850 } else {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001851 return syntax_error("adb reconnect [device|offline]");
Josh Gao22d2b3e2016-10-27 14:01:08 -07001852 }
Yabin Cui1f4ec192016-04-05 13:50:44 -07001853 }
Dan Albert90d4b732015-05-20 18:58:41 -07001854 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001855
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001856 syntax_error("unknown command %s", argv[0]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001857 return 1;
1858}
1859
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001860static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
1861 // 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
1862 std::string cmd = "cmd package";
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001863 while (argc-- > 0) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001864 // deny the '-k' option until the remaining data/cache can be removed with adb/UI
1865 if (strcmp(*argv, "-k") == 0) {
1866 printf(
1867 "The -k option uninstalls the application while retaining the data/cache.\n"
1868 "At the moment, there is no way to remove the remaining data.\n"
1869 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1870 "If you truly wish to continue, execute 'adb shell cmd package uninstall -k'.\n");
1871 return EXIT_FAILURE;
1872 }
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001873 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001874 }
1875
David Pursell70ef7b42015-09-30 13:35:42 -07001876 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001877}
1878
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001879static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001880 // The last argument must be the APK file
1881 const char* file = argv[argc - 1];
Elliott Hughes72884782016-10-24 18:29:21 -07001882 if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001883 return syntax_error("filename doesn't end .apk: %s", file);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001884 }
1885
Elliott Hughes72884782016-10-24 18:29:21 -07001886 struct stat sb;
1887 if (stat(file, &sb) == -1) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001888 fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
Elliott Hughes72884782016-10-24 18:29:21 -07001889 return 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001890 }
1891
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001892 int localFd = adb_open(file, O_RDONLY);
1893 if (localFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001894 fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001895 return 1;
1896 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001897
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001898 std::string error;
1899 std::string cmd = "exec:cmd package";
1900
1901 // don't copy the APK name, but, copy the rest of the arguments as-is
1902 while (argc-- > 1) {
1903 cmd += " " + escape_arg(std::string(*argv++));
1904 }
1905
1906 // add size parameter [required for streaming installs]
1907 // do last to override any user specified value
1908 cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
1909
1910 int remoteFd = adb_connect(cmd, &error);
1911 if (remoteFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001912 fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001913 adb_close(localFd);
1914 return 1;
1915 }
1916
1917 char buf[BUFSIZ];
1918 copy_to_file(localFd, remoteFd);
1919 read_status_line(remoteFd, buf, sizeof(buf));
1920
1921 adb_close(localFd);
1922 adb_close(remoteFd);
1923
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001924 if (!strncmp("Success", buf, 7)) {
1925 fputs(buf, stdout);
1926 return 0;
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001927 }
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001928 fprintf(stderr, "adb: failed to install %s: %s", file, buf);
1929 return 1;
Jeff Sharkey960df972014-06-09 17:30:57 -07001930}
1931
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001932static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001933 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001934{
Jeff Sharkey960df972014-06-09 17:30:57 -07001935 // Find all APK arguments starting at end.
1936 // All other arguments passed through verbatim.
1937 int first_apk = -1;
Elliott Hughes72884782016-10-24 18:29:21 -07001938 uint64_t total_size = 0;
1939 for (int i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001940 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001941
Elliott Hughes72884782016-10-24 18:29:21 -07001942 if (android::base::EndsWithIgnoreCase(file, ".apk")) {
1943 struct stat sb;
1944 if (stat(file, &sb) != -1) total_size += sb.st_size;
Jeff Sharkey960df972014-06-09 17:30:57 -07001945 first_apk = i;
1946 } else {
1947 break;
1948 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001949 }
1950
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001951 if (first_apk == -1) return syntax_error("need APK file on command line");
Kenny Root597ea5b2011-08-05 11:19:45 -07001952
Todd Kennedy248722e2016-07-20 16:22:37 -07001953 std::string install_cmd;
1954 if (_use_legacy_install()) {
1955 install_cmd = "exec:pm";
1956 } else {
1957 install_cmd = "exec:cmd package";
1958 }
1959
1960 std::string cmd = android::base::StringPrintf("%s install-create -S %" PRIu64, install_cmd.c_str(), total_size);
Elliott Hughes72884782016-10-24 18:29:21 -07001961 for (int i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001962 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001963 }
1964
1965 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001966 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001967 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001968 if (fd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001969 fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001970 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001971 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001972 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001973 read_status_line(fd, buf, sizeof(buf));
1974 adb_close(fd);
1975
1976 int session_id = -1;
1977 if (!strncmp("Success", buf, 7)) {
1978 char* start = strrchr(buf, '[');
1979 char* end = strrchr(buf, ']');
1980 if (start && end) {
1981 *end = '\0';
1982 session_id = strtol(start + 1, NULL, 10);
1983 }
1984 }
1985 if (session_id < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001986 fprintf(stderr, "adb: failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001987 fputs(buf, stderr);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001988 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001989 }
1990
1991 // Valid session, now stream the APKs
1992 int success = 1;
Elliott Hughes72884782016-10-24 18:29:21 -07001993 for (int i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001994 const char* file = argv[i];
Elliott Hughes72884782016-10-24 18:29:21 -07001995 struct stat sb;
Jeff Sharkey960df972014-06-09 17:30:57 -07001996 if (stat(file, &sb) == -1) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07001997 fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001998 success = 0;
1999 goto finalize_session;
2000 }
2001
Elliott Hughes2940ccf2015-04-17 14:07:52 -07002002 std::string cmd = android::base::StringPrintf(
Todd Kennedy248722e2016-07-20 16:22:37 -07002003 "%s install-write -S %" PRIu64 " %d %d_%s -",
Colin Cross58021d12017-02-23 21:23:05 -08002004 install_cmd.c_str(), static_cast<uint64_t>(sb.st_size), session_id, i,
2005 android::base::Basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07002006
2007 int localFd = adb_open(file, O_RDONLY);
2008 if (localFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002009 fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07002010 success = 0;
2011 goto finalize_session;
2012 }
2013
Elliott Hughes078f0fc2015-04-29 08:35:59 -07002014 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07002015 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07002016 if (remoteFd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002017 fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07002018 adb_close(localFd);
2019 success = 0;
2020 goto finalize_session;
2021 }
2022
2023 copy_to_file(localFd, remoteFd);
2024 read_status_line(remoteFd, buf, sizeof(buf));
2025
2026 adb_close(localFd);
2027 adb_close(remoteFd);
2028
2029 if (strncmp("Success", buf, 7)) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002030 fprintf(stderr, "adb: failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002031 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002032 success = 0;
2033 goto finalize_session;
2034 }
2035 }
2036
2037finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002038 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07002039 std::string service =
Todd Kennedy248722e2016-07-20 16:22:37 -07002040 android::base::StringPrintf("%s install-%s %d",
2041 install_cmd.c_str(), success ? "commit" : "abandon", session_id);
Elliott Hughes6452a892015-04-29 12:28:13 -07002042 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07002043 if (fd < 0) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002044 fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002045 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07002046 }
2047 read_status_line(fd, buf, sizeof(buf));
2048 adb_close(fd);
2049
2050 if (!strncmp("Success", buf, 7)) {
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002051 fputs(buf, stdout);
Jeff Sharkey960df972014-06-09 17:30:57 -07002052 return 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07002053 }
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002054 fprintf(stderr, "adb: failed to finalize session\n");
2055 fputs(buf, stderr);
2056 return EXIT_FAILURE;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002057}
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002058
2059static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
2060 std::string cmd = "pm";
2061
2062 while (argc-- > 0) {
2063 cmd += " " + escape_arg(*argv++);
2064 }
2065
2066 return send_shell_command(transport, serial, cmd, false);
2067}
2068
2069static int uninstall_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
2070 /* if the user choose the -k option, we refuse to do it until devices are
2071 out with the option to uninstall the remaining data somehow (adb/ui) */
2072 int i;
2073 for (i = 1; i < argc; i++) {
2074 if (!strcmp(argv[i], "-k")) {
2075 printf(
2076 "The -k option uninstalls the application while retaining the data/cache.\n"
2077 "At the moment, there is no way to remove the remaining data.\n"
2078 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
2079 "If you truly wish to continue, execute 'adb shell pm uninstall -k'\n.");
2080 return EXIT_FAILURE;
2081 }
2082 }
2083
2084 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
2085 return pm_command(transport, serial, argc, argv);
2086}
2087
2088static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
2089 std::string cmd = "rm -f " + escape_arg(filename);
2090 return send_shell_command(transport, serial, cmd, false);
2091}
2092
2093static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
2094 static const char *const DATA_DEST = "/data/local/tmp/%s";
2095 static const char *const SD_DEST = "/sdcard/tmp/%s";
2096 const char* where = DATA_DEST;
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002097
Elliott Hughes72884782016-10-24 18:29:21 -07002098 for (int i = 1; i < argc; i++) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002099 if (!strcmp(argv[i], "-s")) {
2100 where = SD_DEST;
2101 }
2102 }
2103
2104 // Find last APK argument.
2105 // All other arguments passed through verbatim.
2106 int last_apk = -1;
Elliott Hughes72884782016-10-24 18:29:21 -07002107 for (int i = argc - 1; i >= 0; i--) {
2108 if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002109 last_apk = i;
2110 break;
2111 }
2112 }
2113
Elliott Hughes1fc8f6e2017-04-18 14:34:16 -07002114 if (last_apk == -1) return syntax_error("need APK file on command line");
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002115
2116 int result = -1;
2117 std::vector<const char*> apk_file = {argv[last_apk]};
2118 std::string apk_dest = android::base::StringPrintf(
Colin Cross58021d12017-02-23 21:23:05 -08002119 where, android::base::Basename(argv[last_apk]).c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08002120 if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
2121 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
2122 result = pm_command(transport, serial, argc, argv);
2123
2124cleanup_apk:
2125 delete_file(transport, serial, apk_dest);
2126 return result;
2127}