blob: b8f790dcf87020f8c8899c5de14400a69f9c910a [file] [log] [blame]
The Android Open Source Project9ca14dc2009-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 Cui19bec5b2015-09-22 15:52:57 -070017#define TRACE_TAG ADB
Dan Albertdb6fe642015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20
Dan Albertb302d122015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080023#include <errno.h>
Elliott Hughesd1a5b2b2015-04-17 14:07:52 -070024#include <inttypes.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080025#include <limits.h>
26#include <stdarg.h>
Dan Albertb302d122015-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 Project9ca14dc2009-03-03 19:32:55 -080031#include <sys/stat.h>
Dan Albertb302d122015-02-24 15:51:19 -080032#include <sys/types.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080033
David Pursell8a5a5aa2015-09-08 17:17:02 -070034#include <memory>
Elliott Hughes170b5682015-04-17 10:59:34 -070035#include <string>
Elliott Hughes73925982016-11-15 12:37:32 -080036#include <thread>
Josh Gao5d093b22015-10-30 16:57:19 -070037#include <vector>
Elliott Hughes170b5682015-04-17 10:59:34 -070038
Elliott Hughese0a6e2a2016-05-26 22:43:19 -070039#include <android-base/file.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080040#include <android-base/logging.h>
Tao Wucaedcb52016-09-16 13:01:24 -070041#include <android-base/parseint.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080042#include <android-base/stringprintf.h>
43#include <android-base/strings.h>
Elliott Hughes170b5682015-04-17 10:59:34 -070044
Yabin Cui6704a3c2014-11-17 14:48:25 -080045#if !defined(_WIN32)
Josh Gaof344ecf2015-10-23 15:03:31 -070046#include <signal.h>
Elliott Hughes4c5e8042015-11-04 13:07:47 -080047#include <sys/ioctl.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080048#include <termios.h>
Dan Albertb302d122015-02-24 15:51:19 -080049#include <unistd.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080050#endif
51
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080052#include "adb.h"
Nick Kralevich6183c962014-11-13 15:17:29 -080053#include "adb_auth.h"
Dan Albert66a91b02015-02-24 21:26:58 -080054#include "adb_client.h"
55#include "adb_io.h"
Josh Gaoea7457b2016-08-30 15:39:25 -070056#include "adb_unique_fd.h"
Elliott Hughes38104452015-04-17 13:57:15 -070057#include "adb_utils.h"
Felipe Leme042c3512016-07-19 17:07:22 -070058#include "bugreport.h"
59#include "commandline.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080060#include "file_sync_service.h"
David Pursell22fc5e92015-09-30 13:35:42 -070061#include "services.h"
David Pursell8a5a5aa2015-09-08 17:17:02 -070062#include "shell_service.h"
Josh Gao70267e42016-11-15 18:55:47 -080063#include "sysdeps/chrono.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080064
Elliott Hughes3aec2ba2015-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 Kennedy1e2f7dc2015-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 Project9ca14dc2009-03-03 19:32:55 -080070
Matt Gumbel411775c2012-11-14 10:16:17 -080071extern int gListenAll;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080072
Felipe Leme60192aa2016-07-26 12:14:39 -070073DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
74
Elliott Hughes314db002017-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 Project9ca14dc2009-03-03 19:32:55 -080079 exit(1);
80 }
Elliott Hughes314db002017-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 Project9ca14dc2009-03-03 19:32:55 -080082}
83
Elliott Hughes38104452015-04-17 13:57:15 -070084static void help() {
Elliott Hughes687f8b42016-09-28 15:25:47 -070085 fprintf(stdout, "%s\n", adb_version().c_str());
Felipe Lemee4893a22016-07-29 17:57:00 -070086 // clang-format off
Elliott Hughes687f8b42016-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 Hughes2d821142017-01-13 16:58:25 -080091 " -e use TCP/IP device (error if multiple TCP/IP devices available)\n"
Elliott Hughes314db002017-05-01 11:04:31 -070092 " -s SERIAL use device with given serial (overrides $ANDROID_SERIAL)\n"
Elliott Hughes687f8b42016-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 Project9ca14dc2009-03-03 19:32:55 -080096 "\n"
Elliott Hughes687f8b42016-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 Hughes52746b02015-06-12 14:26:29 -0700101 "\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800102 "networking:\n"
Elliott Hughes687f8b42016-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 Project9ca14dc2009-03-03 19:32:55 -0800127 "\n"
Elliott Hughes687f8b42016-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 Hughes314db002017-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 Hughes687f8b42016-09-28 15:25:47 -0700136 " -l: list but don't copy\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800137 "\n"
Elliott Hughes687f8b42016-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 Project9ca14dc2009-03-03 19:32:55 -0800147 "\n"
Elliott Hughes687f8b42016-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 Halsethd8dedd12017-04-11 19:15:17 +0100164 " to show usage run \"adb shell bu help\"\n"
Elliott Hughes687f8b42016-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"
Tim1b29ed32010-02-16 20:18:29 +0000201 "\n"
Yabin Cuid78ed222016-04-05 13:50:44 -0700202 "internal debugging:\n"
Elliott Hughes687f8b42016-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 Cui3cf1b362017-03-10 16:01:01 -0800207 " reconnect offline reset offline/unauthorized devices to force reconnect\n"
Elliott Hughes687f8b42016-09-28 15:25:47 -0700208 "\n"
Elliott Hughes52746b02015-06-12 14:26:29 -0700209 "environment variables:\n"
Elliott Hughes687f8b42016-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 Lemee4893a22016-07-29 17:57:00 -0700216 // clang-format on
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800217}
218
Yabin Cui6704a3c2014-11-17 14:48:25 -0800219#if defined(_WIN32)
220
Elliott Hughes6a096932015-04-16 16:47:02 -0700221// Implemented in sysdeps_win32.cpp.
Elliott Hughesa8265792015-11-03 11:18:40 -0800222void stdin_raw_init();
223void stdin_raw_restore();
Yabin Cui6704a3c2014-11-17 14:48:25 -0800224
225#else
Alistair Buxton7c5dcbb2013-03-01 22:16:41 +0100226static termios g_saved_terminal_state;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800227
Elliott Hughesa8265792015-11-03 11:18:40 -0800228static void stdin_raw_init() {
229 if (tcgetattr(STDIN_FILENO, &g_saved_terminal_state)) return;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800230
Alistair Buxton7c5dcbb2013-03-01 22:16:41 +0100231 termios tio;
Elliott Hughesa8265792015-11-03 11:18:40 -0800232 if (tcgetattr(STDIN_FILENO, &tio)) return;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800233
Alistair Buxton7c5dcbb2013-03-01 22:16:41 +0100234 cfmakeraw(&tio);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800235
Alistair Buxton7c5dcbb2013-03-01 22:16:41 +0100236 // No timeout but request at least one character per read.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800237 tio.c_cc[VTIME] = 0;
238 tio.c_cc[VMIN] = 1;
239
Elliott Hughesa8265792015-11-03 11:18:40 -0800240 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800241}
242
Elliott Hughesa8265792015-11-03 11:18:40 -0800243static void stdin_raw_restore() {
244 tcsetattr(STDIN_FILENO, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800245}
246#endif
247
David Pursell8a5a5aa2015-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 Leme60192aa2016-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 Pursell8a5a5aa2015-09-08 17:17:02 -0700255 int exit_code = 0;
Felipe Leme5ad50902016-06-06 16:05:36 -0700256 if (fd < 0) return exit_code;
257
David Pursell8a5a5aa2015-09-08 17:17:02 -0700258 std::unique_ptr<ShellProtocol> protocol;
259 int length = 0;
David Pursell8a5a5aa2015-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 Leme5ad50902016-06-06 16:05:36 -0700272 while (true) {
David Pursell8a5a5aa2015-09-08 17:17:02 -0700273 if (use_shell_protocol) {
274 if (!protocol->Read()) {
275 break;
276 }
Felipe Leme60192aa2016-07-26 12:14:39 -0700277 length = protocol->data_length();
David Pursell8a5a5aa2015-09-08 17:17:02 -0700278 switch (protocol->id()) {
279 case ShellProtocol::kIdStdout:
Felipe Leme60192aa2016-07-26 12:14:39 -0700280 callback->OnStdout(buffer_ptr, length);
David Pursell8a5a5aa2015-09-08 17:17:02 -0700281 break;
282 case ShellProtocol::kIdStderr:
Felipe Leme60192aa2016-07-26 12:14:39 -0700283 callback->OnStderr(buffer_ptr, length);
David Pursell8a5a5aa2015-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 Leme60192aa2016-07-26 12:14:39 -0700299 callback->OnStdout(buffer_ptr, length);
Felipe Lemeb6447032016-04-01 17:43:27 -0700300 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800301 }
David Pursell8a5a5aa2015-09-08 17:17:02 -0700302
Felipe Leme60192aa2016-07-26 12:14:39 -0700303 return callback->Done(exit_code);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800304}
305
Jeff Sharkey0e0d2512014-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 Hughes0bd85872015-08-25 10:59:45 -0700311 if (len <= 0) {
Jeff Sharkey0e0d2512014-06-09 17:30:57 -0700312 break;
313 }
314
315 buf += len;
316 count -= len;
317 }
318 *buf = '\0';
319}
320
Christopher Tatee0e9f562016-07-06 13:22:22 -0700321static void stdinout_raw_prologue(int inFd, int outFd, int& old_stdin_mode, int& old_stdout_mode) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -0700322 if (inFd == STDIN_FILENO) {
Elliott Hughesa8265792015-11-03 11:18:40 -0800323 stdin_raw_init();
Spencer Lowe7af2d32015-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 Sharkeyc52ec1a2014-05-26 18:30:43 -0700330 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800331
Spencer Lowe7af2d32015-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 Tatee0e9f562016-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 Lowe7af2d32015-05-22 16:48:31 -0700373
Elliott Hughes7cf35752015-04-17 17:03:59 -0700374 while (true) {
Jeff Sharkeyc52ec1a2014-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 Tate73779122011-04-21 12:53:28 -0700380 if (len == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700381 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tate73779122011-04-21 12:53:28 -0700382 break;
383 }
384 if (len < 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700385 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tate73779122011-04-21 12:53:28 -0700386 break;
387 }
Jeff Sharkeyc52ec1a2014-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 Tatefba22972011-06-01 17:56:23 -0700394 total += len;
Christopher Tate73779122011-04-21 12:53:28 -0700395 }
Yabin Cui6704a3c2014-11-17 14:48:25 -0800396
Christopher Tatee0e9f562016-07-06 13:22:22 -0700397 stdinout_raw_epilogue(inFd, outFd, old_stdin_mode, old_stdout_mode);
Spencer Lowe7af2d32015-05-22 16:48:31 -0700398
Yabin Cui815ad882015-09-02 17:44:28 -0700399 D("copy_to_file() finished after %lu bytes", total);
Christopher Tatea162e242011-06-10 11:38:37 -0700400 free(buf);
Christopher Tate73779122011-04-21 12:53:28 -0700401}
402
Elliott Hughesa8265792015-11-03 11:18:40 -0800403static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) {
Elliott Hughesa8265792015-11-03 11:18:40 -0800404 // Old devices can't handle window size changes.
405 if (shell == nullptr) return;
406
Spencer Low55441402015-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 Hughesa8265792015-11-03 11:18:40 -0800416 winsize ws;
Spencer Low55441402015-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 Hughesa8265792015-11-03 11:18:40 -0800437 if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return;
Spencer Low55441402015-11-07 17:34:39 -0800438#endif
Elliott Hughesa8265792015-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 Hughesa8265792015-11-03 11:18:40 -0800444}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800445
David Pursell8a5a5aa2015-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 Pursell3fe11f62015-10-06 15:30:03 -0700449 bool raw_stdin;
David Pursell8a5a5aa2015-09-08 17:17:02 -0700450 std::unique_ptr<ShellProtocol> protocol;
Elliott Hughes4cf6f102015-11-04 13:36:32 -0800451 char escape_char;
David Pursell8a5a5aa2015-09-08 17:17:02 -0700452};
453
David Pursell8a5a5aa2015-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 Gao382ea6e2016-02-12 14:31:15 -0800457static void stdin_read_thread_loop(void* x) {
David Pursell8a5a5aa2015-09-08 17:17:02 -0700458 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800459
Elliott Hughesa8265792015-11-03 11:18:40 -0800460#if !defined(_WIN32)
461 // Mask SIGTTIN in case we're in a backgrounded process.
Josh Gaof344ecf2015-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 Low55441402015-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 Hughesa8265792015-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 Hughes4cf6f102015-11-04 13:36:32 -0800483 char raw_buffer[BUFSIZ];
David Pursell8a5a5aa2015-09-08 17:17:02 -0700484 char* buffer_ptr = raw_buffer;
485 size_t buffer_size = sizeof(raw_buffer);
Elliott Hughesa8265792015-11-03 11:18:40 -0800486 if (args->protocol != nullptr) {
David Pursell8a5a5aa2015-09-08 17:17:02 -0700487 buffer_ptr = args->protocol->data();
488 buffer_size = args->protocol->data_capacity();
489 }
490
Elliott Hughes4cf6f102015-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 Hughesb628cb12015-08-03 10:38:08 -0700499 while (true) {
Spencer Low55441402015-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 Hughesa8265792015-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 Low55441402015-11-07 17:34:39 -0800508 D("stdin_read_thread_loop(): post unix_read_interruptible(fdi=%d,...)", args->stdin_fd);
David Pursell3fe11f62015-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 Hughes4cf6f102015-11-04 13:36:32 -0800519 // If we made stdin raw, check input for escape sequences. In
David Pursell3fe11f62015-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 Hughes4cf6f102015-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 Hughesa8265792015-11-03 11:18:40 -0800538 stdin_raw_restore();
David Pursell3fe11f62015-10-06 15:30:03 -0700539 exit(0);
Elliott Hughes4cf6f102015-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 Pursell3fe11f62015-10-06 15:30:03 -0700546 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800547 }
Elliott Hughes4cf6f102015-11-04 13:36:32 -0800548 state = (ch == '\n' || ch == '\r') ? kStartOfLine : kMidFlow;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800549 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800550 }
David Pursell8a5a5aa2015-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 Project9ca14dc2009-03-03 19:32:55 -0800559 }
560 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800561}
562
David Pursell3fe11f62015-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 Hughes401847e2015-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 Pursell3fe11f62015-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 Hughes4cf6f102015-11-04 13:36:32 -0800596 char escape_char,
David Pursell3fe11f62015-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 Hughes04a98c22015-04-29 08:35:59 -0700607 std::string error;
David Pursella07dbad2015-09-22 10:43:08 -0700608 int fd = adb_connect(service_string, &error);
Elliott Hughes04a98c22015-04-29 08:35:59 -0700609 if (fd < 0) {
610 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800611 return 1;
612 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800613
David Pursell8a5a5aa2015-09-08 17:17:02 -0700614 StdinReadArgs* args = new StdinReadArgs;
615 if (!args) {
616 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesd0269c92015-04-21 19:39:52 -0700617 return 1;
618 }
David Pursell3fe11f62015-10-06 15:30:03 -0700619 args->stdin_fd = STDIN_FILENO;
David Pursell8a5a5aa2015-09-08 17:17:02 -0700620 args->write_fd = fd;
David Pursell3fe11f62015-10-06 15:30:03 -0700621 args->raw_stdin = raw_stdin;
Elliott Hughes4cf6f102015-11-04 13:36:32 -0800622 args->escape_char = escape_char;
David Pursell8a5a5aa2015-09-08 17:17:02 -0700623 if (use_shell_protocol) {
624 args->protocol.reset(new ShellProtocol(args->write_fd));
625 }
Elliott Hughesd0269c92015-04-21 19:39:52 -0700626
Elliott Hughesa8265792015-11-03 11:18:40 -0800627 if (raw_stdin) stdin_raw_init();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800628
Elliott Hughesa8265792015-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 Gao0f3312a2017-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 Hughesf2517142015-05-05 13:41:21 -0700653
Elliott Hughesa8265792015-11-03 11:18:40 -0800654 // TODO: properly exit stdin_read_thread_loop and close |fd|.
David Pursell3fe11f62015-10-06 15:30:03 -0700655
Elliott Hughesa8265792015-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 Pursell3fe11f62015-10-06 15:30:03 -0700659
David Pursell8a5a5aa2015-09-08 17:17:02 -0700660 return exit_code;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800661}
662
Josh Gao91d53b52016-01-31 19:12:26 -0800663static int adb_shell(int argc, const char** argv) {
David Pursell9650d862016-01-21 19:56:50 -0800664 FeatureSet features;
Josh Gao91d53b52016-01-31 19:12:26 -0800665 std::string error;
Josh Gao91d53b52016-01-31 19:12:26 -0800666 if (!adb_get_feature_set(&features, &error)) {
667 fprintf(stderr, "error: %s\n", error.c_str());
David Pursell9650d862016-01-21 19:56:50 -0800668 return 1;
669 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800670
Elliott Hughes02e33782016-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 Hughesda945812015-04-29 12:28:13 -0700677
Elliott Hughesa8265792015-11-03 11:18:40 -0800678 // Parse shell-specific command-line options.
Elliott Hughes02e33782016-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 Hughes65bc2272017-04-18 14:34:16 -0700686 return syntax_error("-e requires a single-character argument or 'none'");
Elliott Hughes02e33782016-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 Hughes4cf6f102015-11-04 13:36:32 -0800712 return 1;
Elliott Hughesa8265792015-11-03 11:18:40 -0800713 }
Elliott Hughesda945812015-04-29 12:28:13 -0700714 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800715
Elliott Hughes02e33782016-10-19 14:47:11 -0700716 bool is_interactive = (optind == argc);
David Pursell182dc322016-01-27 16:07:52 -0800717
Elliott Hughes02e33782016-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 Hughesa8265792015-11-03 11:18:40 -0800726 shell_type_arg = kShellServiceArgRaw;
Elliott Hughes02e33782016-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 Hughesa8265792015-11-03 11:18:40 -0800749 } else {
Elliott Hughes02e33782016-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 Hughesa8265792015-11-03 11:18:40 -0800752 }
David Purselle570b982015-09-14 15:33:50 -0700753 }
Elliott Hughesa8265792015-11-03 11:18:40 -0800754
755 std::string command;
Elliott Hughes02e33782016-10-19 14:47:11 -0700756 if (optind < argc) {
Elliott Hughesa8265792015-11-03 11:18:40 -0800757 // We don't escape here, just like ssh(1). http://b/20564385.
Elliott Hughes02e33782016-10-19 14:47:11 -0700758 command = android::base::Join(std::vector<const char*>(argv + optind, argv + argc), ' ');
Elliott Hughesa8265792015-11-03 11:18:40 -0800759 }
760
Elliott Hughes4cf6f102015-11-04 13:36:32 -0800761 return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command);
David Purselle570b982015-09-14 15:33:50 -0700762}
763
Elliott Hughes96038eb2017-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 Hughes04a98c22015-04-29 08:35:59 -0700774 std::string error;
Elliott Hughesda945812015-04-29 12:28:13 -0700775 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes04a98c22015-04-29 08:35:59 -0700776 if (fd < 0) {
777 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker6b217ed2012-01-09 14:54:53 -0800778 return -1;
779 }
780
781 int opt = CHUNK_SIZE;
Spencer Low31aafa62015-01-25 14:40:16 -0800782 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker6b217ed2012-01-09 14:54:53 -0800783
Elliott Hughesda945812015-04-29 12:28:13 -0700784 unsigned total = sz;
Dan Albertf30d73c2015-02-25 17:51:28 -0800785 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800786
Elliott Hughes96038eb2017-03-21 17:14:18 -0700787 const char* x = strrchr(service, ':');
788 if (x) service = x + 1;
Doug Zongker6b217ed2012-01-09 14:54:53 -0800789
Elliott Hughesda945812015-04-29 12:28:13 -0700790 while (sz > 0) {
Doug Zongker6b217ed2012-01-09 14:54:53 -0800791 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes04a98c22015-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 Lowcc4a4b12015-10-14 17:32:44 -0700796 adb_close(fd);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800797 return -1;
798 }
799 sz -= xfer;
800 ptr += xfer;
Elliott Hughes96038eb2017-03-21 17:14:18 -0700801 printf("sending: '%s' %4d%% \r", filename, (int)(100LL - ((100LL * sz) / (total))));
802 fflush(stdout);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800803 }
Elliott Hughes96038eb2017-03-21 17:14:18 -0700804 printf("\n");
Doug Zongker6b217ed2012-01-09 14:54:53 -0800805
Elliott Hughes88b4c852015-04-30 17:32:03 -0700806 if (!adb_status(fd, &error)) {
807 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Spencer Lowcc4a4b12015-10-14 17:32:44 -0700808 adb_close(fd);
Doug Zongker6b217ed2012-01-09 14:54:53 -0800809 return -1;
810 }
811
812 adb_close(fd);
813 return 0;
814}
815
Doug Zongkerbcad29f2014-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 Hughes96038eb2017-03-21 17:14:18 -0700837static int adb_sideload_host(const char* filename) {
Elliott Hughes65bc2272017-04-18 14:34:16 -0700838 // TODO: use a LinePrinter instead...
839 fprintf(stdout, "opening '%s'...\n", filename);
840 fflush(stdout);
841
Elliott Hughes96038eb2017-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 Zongkerbcad29f2014-06-26 15:35:36 -0700850 return -1;
851 }
852
Elliott Hughes65bc2272017-04-18 14:34:16 -0700853 fprintf(stdout, "connecting...\n");
854 fflush(stdout);
Elliott Hughes96038eb2017-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 Hughes04a98c22015-04-29 08:35:59 -0700857 std::string error;
Elliott Hughes96038eb2017-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 Zongkerbcad29f2014-06-26 15:35:36 -0700861 // is an older device that doesn't support sideload-host.
Elliott Hughes74d8e612016-06-15 14:45:34 -0700862 fprintf(stderr, "falling back to older sideload method...\n");
Elliott Hughes96038eb2017-03-21 17:14:18 -0700863 return adb_download_buffer("sideload", filename);
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700864 }
865
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700866 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughes96038eb2017-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 Zongkerbcad29f2014-06-26 15:35:36 -0700870
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700871 size_t xfer = 0;
872 int last_percent = -1;
Elliott Hughes7cf35752015-04-17 17:03:59 -0700873 while (true) {
Elliott Hughes96038eb2017-03-21 17:14:18 -0700874 if (!ReadFdExactly(device_fd, buf, 8)) {
Elliott Hughes04a98c22015-04-29 08:35:59 -0700875 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700876 return -1;
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700877 }
Elliott Hughesda945812015-04-29 12:28:13 -0700878 buf[8] = '\0';
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700879
Elliott Hughesda945812015-04-29 12:28:13 -0700880 if (strcmp("DONEDONE", buf) == 0) {
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700881 printf("\rTotal xfer: %.2fx%*s\n",
Elliott Hughes96038eb2017-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 Hughese0a6e2a2016-05-26 22:43:19 -0700884 return 0;
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700885 }
886
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700887 int block = strtol(buf, NULL, 10);
888
889 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughes96038eb2017-03-21 17:14:18 -0700890 if (offset >= static_cast<size_t>(sb.st_size)) {
Elliott Hughes04a98c22015-04-29 08:35:59 -0700891 fprintf(stderr, "* attempt to read block %d past end\n", block);
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700892 return -1;
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700893 }
Elliott Hughes96038eb2017-03-21 17:14:18 -0700894
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700895 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
Elliott Hughes96038eb2017-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 Zongkerbcad29f2014-06-26 15:35:36 -0700898 }
899
Elliott Hughes96038eb2017-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 Hughes04a98c22015-04-29 08:35:59 -0700911 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700912 return -1;
Doug Zongkerbcad29f2014-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 Hughes96038eb2017-03-21 17:14:18 -0700922 int percent = static_cast<int>(xfer * 47LL / (sb.st_size ? sb.st_size : 1));
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700923 if (percent != last_percent) {
Elliott Hughes96038eb2017-03-21 17:14:18 -0700924 printf("\rserving: '%s' (~%d%%) ", filename, percent);
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700925 fflush(stdout);
926 last_percent = percent;
927 }
928 }
Doug Zongkerbcad29f2014-06-26 15:35:36 -0700929}
930
The Android Open Source Project9ca14dc2009-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 Hughes38104452015-04-17 13:57:15 -0700938static int ppp(int argc, const char** argv) {
Yabin Cui2fa43212014-11-11 09:24:11 -0800939#if defined(_WIN32)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800940 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
941 return -1;
942#else
Elliott Hughes65bc2272017-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 Project9ca14dc2009-03-03 19:32:55 -0800944
Dan Albertf30d73c2015-02-25 17:51:28 -0800945 const char* adb_service_name = argv[1];
Elliott Hughes04a98c22015-04-29 08:35:59 -0700946 std::string error;
947 int fd = adb_connect(adb_service_name, &error);
948 if (fd < 0) {
Elliott Hughes65bc2272017-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 Project9ca14dc2009-03-03 19:32:55 -0800950 return 1;
951 }
952
Elliott Hughes04a98c22015-04-29 08:35:59 -0700953 pid_t pid = fork();
The Android Open Source Project9ca14dc2009-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 Cui2fa43212014-11-11 09:24:11 -0800991#endif /* !defined(_WIN32) */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800992}
993
Josh Gao63cede32016-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 Sartre6cd9bc32015-11-27 18:56:48 +0100997 fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
998 return false;
999 }
1000
Elliott Hugheseaabdd62015-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 Gao63cede32016-04-13 12:14:16 -07001003 if (components.size() == 3) {
1004 auto it = components.begin() + 2;
Elliott Hugheseaabdd62015-05-04 19:29:32 -07001005 if (t == kTransportUsb) {
Josh Gao63cede32016-04-13 12:14:16 -07001006 components.insert(it, "usb");
Elliott Hugheseaabdd62015-05-04 19:29:32 -07001007 } else if (t == kTransportLocal) {
Josh Gao63cede32016-04-13 12:14:16 -07001008 components.insert(it, "local");
Elliott Hugheseaabdd62015-05-04 19:29:32 -07001009 } else {
Josh Gao63cede32016-04-13 12:14:16 -07001010 components.insert(it, "any");
Elliott Hugheseaabdd62015-05-04 19:29:32 -07001011 }
Josh Gao63cede32016-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 Sartre6cd9bc32015-11-27 18:56:48 +01001015 return false;
1016 }
1017
Josh Gao071328d2016-04-13 12:18:58 -07001018 if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
1019 components[3] != "recovery" && components[3] != "sideload") {
Josh Gao63cede32016-04-13 12:14:16 -07001020 fprintf(stderr,
1021 "adb: unknown state %s; "
Josh Gao071328d2016-04-13 12:18:58 -07001022 "expected 'any', 'bootloader', 'device', 'recovery', or 'sideload'\n",
Josh Gao63cede32016-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 Hughesd98ca8a2015-05-29 17:55:19 -07001028 return adb_command(cmd);
Elliott Hugheseaabdd62015-05-04 19:29:32 -07001029}
1030
Josh Gaod1d03392016-03-04 15:16:18 -08001031static bool adb_root(const char* command) {
1032 std::string error;
Josh Gaod1d03392016-03-04 15:16:18 -08001033
Elliott Hughese0a6e2a2016-05-26 22:43:19 -07001034 unique_fd fd(adb_connect(android::base::StringPrintf("%s:", command), &error));
1035 if (fd < 0) {
Josh Gaod1d03392016-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 Hughese0a6e2a2016-05-26 22:43:19 -07001045 ssize_t bytes_read = adb_read(fd, cur, bytes_left);
Josh Gaod1d03392016-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 Gaod3d9cbf2016-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 Gao70267e42016-11-15 18:55:47 -08001069 std::this_thread::sleep_for(3s);
Josh Gaod3d9cbf2016-06-16 14:00:09 -07001070 return true;
Josh Gaod1d03392016-03-04 15:16:18 -08001071}
1072
Felipe Leme042c3512016-07-19 17:07:22 -07001073int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
Felipe Leme60192aa2016-07-26 12:14:39 -07001074 bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
Elliott Hughes170b5682015-04-17 10:59:34 -07001075 int fd;
David Pursell9650d862016-01-21 19:56:50 -08001076 bool use_shell_protocol = false;
1077
Elliott Hughes170b5682015-04-17 10:59:34 -07001078 while (true) {
David Pursell9650d862016-01-21 19:56:50 -08001079 bool attempt_connection = true;
1080
Felipe Leme60192aa2016-07-26 12:14:39 -07001081 // Use shell protocol if it's supported and the caller doesn't explicitly
1082 // disable it.
David Pursell9650d862016-01-21 19:56:50 -08001083 if (!disable_shell_protocol) {
1084 FeatureSet features;
Josh Gao91d53b52016-01-31 19:12:26 -08001085 std::string error;
1086 if (adb_get_feature_set(&features, &error)) {
David Pursell9650d862016-01-21 19:56:50 -08001087 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
1088 } else {
1089 // Device was unreachable.
1090 attempt_connection = false;
1091 }
Elliott Hughes04a98c22015-04-29 08:35:59 -07001092 }
David Pursell9650d862016-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 Leme60192aa2016-07-26 12:14:39 -07001104 fprintf(stderr, "- waiting for device -\n");
Josh Gao6a7e5732016-02-24 15:16:17 -08001105 if (!wait_for_device("wait-for-device", transport_type, serial)) {
1106 return 1;
1107 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001108 }
1109
Felipe Leme60192aa2016-07-26 12:14:39 -07001110 int exit_code = read_and_dump(fd, use_shell_protocol, callback);
David Purselle570b982015-09-14 15:33:50 -07001111
1112 if (adb_close(fd) < 0) {
1113 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes170b5682015-04-17 10:59:34 -07001114 }
David Purselle570b982015-09-14 15:33:50 -07001115
1116 return exit_code;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001117}
1118
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001119static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes170b5682015-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 Project9ca14dc2009-03-03 19:32:55 -08001122
David Pursell22fc5e92015-09-30 13:35:42 -07001123 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001124
Jeff Sharkey824d1062014-06-10 11:31:24 -07001125 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes170b5682015-04-17 10:59:34 -07001126 cmd += " -v long";
Christopher Tate7b9b5162011-11-30 13:00:33 -08001127 }
1128
Elliott Hughese4b64792015-04-17 20:11:08 -07001129 --argc;
1130 ++argv;
Elliott Hughes170b5682015-04-17 10:59:34 -07001131 while (argc-- > 0) {
Elliott Hughese4b64792015-04-17 20:11:08 -07001132 cmd += " " + escape_arg(*argv++);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001133 }
1134
David Pursell22fc5e92015-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 Project9ca14dc2009-03-03 19:32:55 -08001137}
1138
Christopher Tatee0e9f562016-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 Albertf30d73c2015-02-25 17:51:28 -08001162static int backup(int argc, const char** argv) {
Elliott Hughes1c1f7dc2015-08-21 20:31:31 -07001163 const char* filename = "backup.ab";
Christopher Tate73779122011-04-21 12:53:28 -07001164
Christopher Tatefba22972011-06-01 17:56:23 -07001165 /* find, extract, and use any -f argument */
Elliott Hughese4b64792015-04-17 20:11:08 -07001166 for (int i = 1; i < argc; i++) {
Christopher Tatefba22972011-06-01 17:56:23 -07001167 if (!strcmp("-f", argv[i])) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001168 if (i == argc - 1) return syntax_error("backup -f passed with no filename");
Christopher Tatefba22972011-06-01 17:56:23 -07001169 filename = argv[i+1];
Elliott Hughese4b64792015-04-17 20:11:08 -07001170 for (int j = i+2; j <= argc; ) {
Christopher Tatefba22972011-06-01 17:56:23 -07001171 argv[i++] = argv[j++];
1172 }
1173 argc -= 2;
1174 argv[argc] = NULL;
1175 }
Christopher Tate73779122011-04-21 12:53:28 -07001176 }
1177
Elliott Hughes9406f7e2015-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 Hughes65bc2272017-04-18 14:34:16 -07001180 if (argc < 2) return syntax_error("backup either needs a list of packages or -all/-shared");
Christopher Tatecf4f16a2011-08-22 17:12:08 -07001181
Christopher Tate1e9f2392011-12-08 19:04:34 -08001182 adb_unlink(filename);
Elliott Hughese4b64792015-04-17 20:11:08 -07001183 int outFd = adb_creat(filename, 0640);
Christopher Tate73779122011-04-21 12:53:28 -07001184 if (outFd < 0) {
Elliott Hughes9406f7e2015-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 Tate73779122011-04-21 12:53:28 -07001187 }
1188
Elliott Hughese4b64792015-04-17 20:11:08 -07001189 std::string cmd = "backup:";
1190 --argc;
1191 ++argv;
1192 while (argc-- > 0) {
1193 cmd += " " + escape_arg(*argv++);
Christopher Tate73779122011-04-21 12:53:28 -07001194 }
1195
Yabin Cui815ad882015-09-02 17:44:28 -07001196 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes04a98c22015-04-29 08:35:59 -07001197 std::string error;
Elliott Hughesda945812015-04-29 12:28:13 -07001198 int fd = adb_connect(cmd, &error);
Christopher Tate73779122011-04-21 12:53:28 -07001199 if (fd < 0) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001200 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tate73779122011-04-21 12:53:28 -07001201 adb_close(outFd);
Elliott Hughes9406f7e2015-11-13 11:04:10 -08001202 return EXIT_FAILURE;
Christopher Tate73779122011-04-21 12:53:28 -07001203 }
1204
Elliott Hughes65bc2272017-04-18 14:34:16 -07001205 fprintf(stdout, "Now unlock your device and confirm the backup operation...\n");
Elliott Hughes9406f7e2015-11-13 11:04:10 -08001206 fflush(stdout);
1207
Christopher Tate73779122011-04-21 12:53:28 -07001208 copy_to_file(fd, outFd);
1209
1210 adb_close(fd);
1211 adb_close(outFd);
Elliott Hughes9406f7e2015-11-13 11:04:10 -08001212 return EXIT_SUCCESS;
Christopher Tate73779122011-04-21 12:53:28 -07001213}
1214
Dan Albertf30d73c2015-02-25 17:51:28 -08001215static int restore(int argc, const char** argv) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001216 if (argc != 2) return syntax_error("restore requires an argument");
Christopher Tatecf5379b2011-05-17 15:52:54 -07001217
Elliott Hughes04a98c22015-04-29 08:35:59 -07001218 const char* filename = argv[1];
1219 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tatecf5379b2011-05-17 15:52:54 -07001220 if (tarFd < 0) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001221 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tatecf5379b2011-05-17 15:52:54 -07001222 return -1;
1223 }
1224
Elliott Hughes04a98c22015-04-29 08:35:59 -07001225 std::string error;
1226 int fd = adb_connect("restore:", &error);
Christopher Tatecf5379b2011-05-17 15:52:54 -07001227 if (fd < 0) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001228 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tatecf5379b2011-05-17 15:52:54 -07001229 adb_close(tarFd);
1230 return -1;
1231 }
1232
Elliott Hughes65bc2272017-04-18 14:34:16 -07001233 fprintf(stdout, "Now unlock your device and confirm the restore operation.\n");
1234 fflush(stdout);
1235
Christopher Tatecf5379b2011-05-17 15:52:54 -07001236 copy_to_file(tarFd, fd);
1237
Christopher Tatee0e9f562016-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 Gao95230e82016-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 Tatecf5379b2011-05-17 15:52:54 -07001244 adb_close(fd);
1245 adb_close(tarFd);
1246 return 0;
1247}
1248
Josh Gao5d093b22015-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 Lindner9f9d1452014-03-11 17:55:59 -07001253
Josh Gao5d093b22015-10-30 16:57:19 -07001254 srcs->clear();
1255 bool ignore_flags = false;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001256 while (narg > 0) {
Josh Gao5d093b22015-10-30 16:57:19 -07001257 if (ignore_flags || *arg[0] != '-') {
1258 srcs->push_back(*arg);
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001259 } else {
Josh Gao5d093b22015-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 Hughes65bc2272017-04-18 14:34:16 -07001267 syntax_error("unrecognized option '%s'", *arg);
Josh Gao5d093b22015-10-30 16:57:19 -07001268 exit(1);
1269 }
Lajos Molnar4e23e3c2013-04-19 12:41:09 -07001270 }
Mark Lindner9f9d1452014-03-11 17:55:59 -07001271 ++arg;
1272 --narg;
1273 }
1274
Josh Gao5d093b22015-10-30 16:57:19 -07001275 if (srcs->size() > 1) {
1276 *dst = srcs->back();
1277 srcs->pop_back();
Mark Lindner9f9d1452014-03-11 17:55:59 -07001278 }
1279}
1280
Elliott Hughesda945812015-04-29 12:28:13 -07001281static int adb_connect_command(const std::string& command) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001282 std::string error;
1283 int fd = adb_connect(command, &error);
Elliott Hughesdabb9742015-05-07 23:37:40 -07001284 if (fd < 0) {
1285 fprintf(stderr, "error: %s\n", error.c_str());
1286 return 1;
Tao Bao0db67642015-03-29 11:22:34 -07001287 }
Elliott Hughesdabb9742015-05-07 23:37:40 -07001288 read_and_dump(fd);
1289 adb_close(fd);
1290 return 0;
Tao Bao0db67642015-03-29 11:22:34 -07001291}
1292
Elliott Hughesda945812015-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 Lowe98825e2015-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 Kennedy8c5cf622016-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 Hughes02e33782016-10-19 14:47:11 -07001326int adb_commandline(int argc, const char** argv) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001327 int no_daemon = 0;
1328 int is_daemon = 0;
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001329 int is_server = 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001330 int r;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001331 TransportType transport_type = kTransportAny;
Siva Velusamya55dbd82015-08-07 10:10:29 -07001332 int ack_reply_fd = -1;
Siva Velusamya55dbd82015-08-07 10:10:29 -07001333
Elliott Hughes4919c172015-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 Gaobb4f8602016-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 Hilzinger92ca4fa2010-04-19 12:21:12 +01001342
Elliott Hughes67943d12015-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 Andrews03b4b372014-12-05 17:37:24 -08001346 while (argc > 0) {
1347 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001348 is_server = 1;
Riley Andrews03b4b372014-12-05 17:37:24 -08001349 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Project9ca14dc2009-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 Velusamya55dbd82015-08-07 10:10:29 -07001354 } else if (!strcmp(argv[0], "--reply-fd")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001355 if (argc < 2) return syntax_error("--reply-fd requires an argument");
Siva Velusamya55dbd82015-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 Lowe98825e2015-09-07 16:20:13 -07001360 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamya55dbd82015-08-07 10:10:29 -07001361 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
Elliott Hughes97e74bb2017-02-06 16:20:30 -08001362 return 1;
Siva Velusamya55dbd82015-08-07 10:10:29 -07001363 }
The Android Open Source Project9ca14dc2009-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 Hughes65bc2272017-04-18 14:34:16 -07001368 if (argc < 2 || argv[0][2] != '\0') return syntax_error("-s requires an argument");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001369 serial = argv[1];
1370 argc--;
1371 argv++;
1372 }
1373 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001374 transport_type = kTransportUsb;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001375 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001376 transport_type = kTransportLocal;
Matt Gumbel411775c2012-11-14 10:16:17 -08001377 } else if (!strcmp(argv[0],"-a")) {
1378 gListenAll = 1;
Riley Andrews03b4b372014-12-05 17:37:24 -08001379 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbel411775c2012-11-14 10:16:17 -08001380 if (argv[0][2] == '\0') {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001381 if (argc < 2) return syntax_error("-H requires an argument");
Josh Gaobb4f8602016-08-25 16:00:22 -07001382 server_host_str = argv[1];
Matt Gumbel411775c2012-11-14 10:16:17 -08001383 argc--;
1384 argv++;
1385 } else {
Josh Gaobb4f8602016-08-25 16:00:22 -07001386 server_host_str = argv[0] + 2;
Matt Gumbel411775c2012-11-14 10:16:17 -08001387 }
Riley Andrews03b4b372014-12-05 17:37:24 -08001388 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbel411775c2012-11-14 10:16:17 -08001389 if (argv[0][2] == '\0') {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001390 if (argc < 2) return syntax_error("-P requires an argument");
Matt Gumbel411775c2012-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 Gaobb4f8602016-08-25 16:00:22 -07001397 } else if (!strcmp(argv[0], "-L")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001398 if (argc < 2) return syntax_error("-L requires an argument");
Josh Gaobb4f8602016-08-25 16:00:22 -07001399 server_socket_str = argv[1];
1400 argc--;
1401 argv++;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001402 } else {
Josh Gaobb4f8602016-08-25 16:00:22 -07001403 /* out of recognized modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001404 break;
1405 }
1406 argc--;
1407 argv++;
1408 }
1409
Josh Gaobb4f8602016-08-25 16:00:22 -07001410 if ((server_host_str || server_port_str) && server_socket_str) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001411 return syntax_error("-L is incompatible with -H or -P");
Josh Gaobb4f8602016-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 Wucaedcb52016-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 Gaobb4f8602016-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 Wucaedcb52016-09-16 13:01:24 -07001424 int server_port = DEFAULT_ADB_PORT;
Josh Gaobb4f8602016-08-25 16:00:22 -07001425 server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
Tao Wucaedcb52016-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 Gaobb4f8602016-08-25 16:00:22 -07001435
1436 int rc;
1437 char* temp;
1438 if (server_host_str) {
Tao Wucaedcb52016-09-16 13:01:24 -07001439 rc = asprintf(&temp, "tcp:%s:%d", server_host_str, server_port);
Josh Gaobb4f8602016-08-25 16:00:22 -07001440 } else {
Tao Wucaedcb52016-09-16 13:01:24 -07001441 rc = asprintf(&temp, "tcp:%d", server_port);
Josh Gaobb4f8602016-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 Hughes67943d12015-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 Hughes3aec2ba2015-05-05 13:10:43 -07001456 adb_set_transport(transport_type, serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001457
David 'Digit' Turner6826db62011-01-31 14:23:56 +01001458 if (is_server) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001459 if (no_daemon || is_daemon) {
Spencer Lowb28812f2015-08-08 15:07:07 -07001460 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamya55dbd82015-08-07 10:10:29 -07001461 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
Elliott Hughes97e74bb2017-02-06 16:20:30 -08001462 return 1;
Siva Velusamya55dbd82015-08-07 10:10:29 -07001463 }
Josh Gaobb4f8602016-08-25 16:00:22 -07001464 r = adb_server_main(is_daemon, server_socket_str, ack_reply_fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001465 } else {
Josh Gaobb4f8602016-08-25 16:00:22 -07001466 r = launch_server(server_socket_str);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001467 }
Riley Andrews03b4b372014-12-05 17:37:24 -08001468 if (r) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001469 fprintf(stderr,"* could not start server *\n");
1470 }
1471 return r;
1472 }
1473
Riley Andrews03b4b372014-12-05 17:37:24 -08001474 if (argc == 0) {
Elliott Hughes97e74bb2017-02-06 16:20:30 -08001475 help();
1476 return 1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001477 }
1478
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001479 /* handle wait-for-* prefix */
1480 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertf30d73c2015-02-25 17:51:28 -08001481 const char* service = argv[0];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001482
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001483 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001484 return 1;
1485 }
1486
Elliott Hugheseaabdd62015-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 Andrewsfacb92d2014-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 Andrews03b4b372014-12-05 17:37:24 -08001499 if (!strcmp(argv[0], "devices")) {
Dan Albertf30d73c2015-02-25 17:51:28 -08001500 const char *listopt;
Elliott Hughesda945812015-04-29 12:28:13 -07001501 if (argc < 2) {
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001502 listopt = "";
Elliott Hughesda945812015-04-29 12:28:13 -07001503 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001504 listopt = argv[1];
Elliott Hughesda945812015-04-29 12:28:13 -07001505 } else {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001506 return syntax_error("adb devices [-l]");
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001507 }
Elliott Hughesda945812015-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 Project9ca14dc2009-03-03 19:32:55 -08001512 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001513 else if (!strcmp(argv[0], "connect")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001514 if (argc != 2) return syntax_error("adb connect <host>[:<port>]");
Elliott Hughesda945812015-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 Lockwood01c2c302010-05-24 10:44:35 -04001518 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001519 else if (!strcmp(argv[0], "disconnect")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001520 if (argc > 2) return syntax_error("adb disconnect [<host>[:<port>]]");
Elliott Hughesda945812015-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 Lockwood26b88e32009-08-24 15:58:40 -07001525 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001526 else if (!strcmp(argv[0], "emu")) {
Spencer Low7dc759f2015-05-06 16:13:42 -07001527 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001528 }
Elliott Hughesa8265792015-11-03 11:18:40 -08001529 else if (!strcmp(argv[0], "shell")) {
Josh Gao91d53b52016-01-31 19:12:26 -08001530 return adb_shell(argc, argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001531 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001532 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001533 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001534
Elliott Hughes65bc2272017-04-18 14:34:16 -07001535 if (argc < 2) return syntax_error("adb %s command", argv[0]);
Zach Riggle328870b2016-04-14 17:18:04 -04001536
Elliott Hughes170b5682015-04-17 10:59:34 -07001537 std::string cmd = "exec:";
1538 cmd += argv[1];
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001539 argc -= 2;
1540 argv += 2;
1541 while (argc-- > 0) {
Elliott Hughese4b64792015-04-17 20:11:08 -07001542 cmd += " " + escape_arg(*argv++);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001543 }
1544
Elliott Hughes04a98c22015-04-29 08:35:59 -07001545 std::string error;
Elliott Hughesda945812015-04-29 12:28:13 -07001546 int fd = adb_connect(cmd, &error);
Jeff Sharkeyc52ec1a2014-05-26 18:30:43 -07001547 if (fd < 0) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001548 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkeyc52ec1a2014-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 Andrewsfacb92d2014-12-05 17:32:46 -08001561 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001562 std::string error;
1563 int fd = _adb_connect("host:kill", &error);
Spencer Low85ee64b2015-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 Project9ca14dc2009-03-03 19:32:55 -08001567 fprintf(stderr,"* server not running *\n");
Spencer Low85ee64b2015-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 Project9ca14dc2009-03-03 19:32:55 -08001573 return 1;
Spencer Low85ee64b2015-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 Lowcc4a4b12015-10-14 17:32:44 -07001577 ReadOrderlyShutdown(fd);
Spencer Low85ee64b2015-08-11 17:05:02 -07001578 adb_close(fd);
1579 return 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001580 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001581 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001582 else if (!strcmp(argv[0], "sideload")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001583 if (argc != 2) return syntax_error("sideload requires an argument");
Doug Zongkerbcad29f2014-06-26 15:35:36 -07001584 if (adb_sideload_host(argv[1])) {
Doug Zongker6b217ed2012-01-09 14:54:53 -08001585 return 1;
1586 } else {
1587 return 0;
1588 }
1589 }
Elliott Hughesd94e8ba2015-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 Andrewsfacb92d2014-12-05 17:32:46 -08001593 else if (!strcmp(argv[0], "remount") ||
1594 !strcmp(argv[0], "reboot") ||
1595 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001596 !strcmp(argv[0], "usb") ||
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001597 !strcmp(argv[0], "disable-verity") ||
1598 !strcmp(argv[0], "enable-verity")) {
Elliott Hughesdabb9742015-05-07 23:37:40 -07001599 std::string command;
Tao Bao0db67642015-03-29 11:22:34 -07001600 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughesdabb9742015-05-07 23:37:40 -07001601 command = "reboot:bootloader";
Tao Bao0db67642015-03-29 11:22:34 -07001602 } else if (argc > 1) {
Elliott Hughesdabb9742015-05-07 23:37:40 -07001603 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao0db67642015-03-29 11:22:34 -07001604 } else {
Elliott Hughesdabb9742015-05-07 23:37:40 -07001605 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Project9c753402009-03-13 13:04:37 -07001606 }
Tao Bao0db67642015-03-29 11:22:34 -07001607 return adb_connect_command(command);
Josh Gaod1d03392016-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 Leme042c3512016-07-19 17:07:22 -07001611 Bugreport bugreport;
1612 return bugreport.DoIt(transport_type, serial, argc, argv);
Felipe Lemeb6447032016-04-01 17:43:27 -07001613 } else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001614 bool reverse = !strcmp(argv[0], "reverse");
1615 ++argv;
1616 --argc;
Elliott Hughes65bc2272017-04-18 14:34:16 -07001617 if (argc < 1) return syntax_error("%s requires an argument", argv[0]);
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001618
1619 // Determine the <host-prefix> for this command.
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001620 std::string host_prefix;
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001621 if (reverse) {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001622 host_prefix = "reverse";
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001623 } else {
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001624 if (serial) {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001625 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001626 } else if (transport_type == kTransportUsb) {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001627 host_prefix = "host-usb";
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001628 } else if (transport_type == kTransportLocal) {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001629 host_prefix = "host-local";
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001630 } else {
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001631 host_prefix = "host";
David 'Digit' Turner963a4492013-03-21 21:07:42 +01001632 }
David 'Digit' Turner6c489802012-11-14 15:01:55 +01001633 }
1634
David Pursell19d0c232016-04-07 11:25:48 -07001635 std::string cmd, error;
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001636 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001637 if (argc != 1) return syntax_error("--list doesn't take any arguments");
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001638 return adb_query_command(host_prefix + ":list-forward");
1639 } else if (strcmp(argv[0], "--remove-all") == 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001640 if (argc != 1) return syntax_error("--remove-all doesn't take any arguments");
Elliott Hughesd98ca8a2015-05-29 17:55:19 -07001641 cmd = host_prefix + ":killforward-all";
1642 } else if (strcmp(argv[0], "--remove") == 0) {
1643 // forward --remove <local>
Elliott Hughes65bc2272017-04-18 14:34:16 -07001644 if (argc != 2) return syntax_error("--remove requires an argument");
Elliott Hughesd98ca8a2015-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 Hughes65bc2272017-04-18 14:34:16 -07001648 if (argc != 3) return syntax_error("--no-rebind takes two arguments");
David Pursell19d0c232016-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 Hughesd98ca8a2015-05-29 17:55:19 -07001652 } else {
1653 // forward <local> <remote>
Elliott Hughes65bc2272017-04-18 14:34:16 -07001654 if (argc != 2) return syntax_error("forward takes two arguments");
David Pursell19d0c232016-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' Turner6c489802012-11-14 15:01:55 +01001658 }
1659
David Pursell19d0c232016-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 Project9ca14dc2009-03-03 19:32:55 -08001680 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001681 /* do_sync_*() commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001682 else if (!strcmp(argv[0], "ls")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001683 if (argc != 2) return syntax_error("ls requires an argument");
Elliott Hughesb628cb12015-08-03 10:38:08 -07001684 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001685 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001686 else if (!strcmp(argv[0], "push")) {
Josh Gao5d093b22015-10-30 16:57:19 -07001687 bool copy_attrs = false;
1688 std::vector<const char*> srcs;
1689 const char* dst = nullptr;
Mark Lindner9f9d1452014-03-11 17:55:59 -07001690
Josh Gao5d093b22015-10-30 16:57:19 -07001691 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
Elliott Hughes65bc2272017-04-18 14:34:16 -07001692 if (srcs.empty() || !dst) return syntax_error("push requires an argument");
Josh Gao5d093b22015-10-30 16:57:19 -07001693 return do_sync_push(srcs, dst) ? 0 : 1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001694 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0], "pull")) {
Josh Gao5d093b22015-10-30 16:57:19 -07001696 bool copy_attrs = false;
1697 std::vector<const char*> srcs;
1698 const char* dst = ".";
Mark Lindner9f9d1452014-03-11 17:55:59 -07001699
Josh Gao5d093b22015-10-30 16:57:19 -07001700 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
Elliott Hughes65bc2272017-04-18 14:34:16 -07001701 if (srcs.empty()) return syntax_error("pull requires an argument");
Josh Gao5d093b22015-10-30 16:57:19 -07001702 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001703 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001704 else if (!strcmp(argv[0], "install")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001705 if (argc < 2) return syntax_error("install requires an argument");
Todd Kennedy8c5cf622016-07-20 16:22:37 -07001706 if (_use_legacy_install()) {
1707 return install_app_legacy(transport_type, serial, argc, argv);
David Pursell9650d862016-01-21 19:56:50 -08001708 }
Todd Kennedy8c5cf622016-07-20 16:22:37 -07001709 return install_app(transport_type, serial, argc, argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001710 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "install-multiple")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001712 if (argc < 2) return syntax_error("install-multiple requires an argument");
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001713 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001714 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001715 else if (!strcmp(argv[0], "uninstall")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001716 if (argc < 2) return syntax_error("uninstall requires an argument");
Todd Kennedy8c5cf622016-07-20 16:22:37 -07001717 if (_use_legacy_install()) {
1718 return uninstall_app_legacy(transport_type, serial, argc, argv);
David Pursell9650d862016-01-21 19:56:50 -08001719 }
Todd Kennedy8c5cf622016-07-20 16:22:37 -07001720 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001721 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001722 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001723 std::string src;
Elliott Hughes38104452015-04-17 13:57:15 -07001724 bool list_only = false;
Riley Andrews03b4b372014-12-05 17:37:24 -08001725 if (argc < 2) {
Elliott Hughes38104452015-04-17 13:57:15 -07001726 // No local path was specified.
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001727 src = "";
Anthony Newnamdd2db142010-02-22 08:36:49 -06001728 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001729 list_only = true;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001730 if (argc == 3) {
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001731 src = argv[2];
Anthony Newnamdd2db142010-02-22 08:36:49 -06001732 } else {
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001733 src = "";
Anthony Newnamdd2db142010-02-22 08:36:49 -06001734 }
Riley Andrews03b4b372014-12-05 17:37:24 -08001735 } else if (argc == 2) {
Elliott Hughes38104452015-04-17 13:57:15 -07001736 // A local path or "android"/"data" arg was specified.
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001737 src = argv[1];
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001738 } else {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001739 return syntax_error("adb sync [-l] [PARTITION]");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001740 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001741
Elliott Hughes314db002017-05-01 11:04:31 -07001742 if (src == "all") src = "";
1743
Elliott Hughesc5a12b22015-04-21 10:17:07 -07001744 if (src != "" &&
1745 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001746 return syntax_error("don't know how to sync %s partition", src.c_str());
Elliott Hughes38104452015-04-17 13:57:15 -07001747 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001748
Elliott Hughes38104452015-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 Hughes38104452015-04-17 13:57:15 -07001753
Elliott Hughesb628cb12015-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 Hughes38104452015-04-17 13:57:15 -07001757 }
Elliott Hughesb628cb12015-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 Hughes38104452015-04-17 13:57:15 -07001760 }
Elliott Hughesb628cb12015-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 Hughes38104452015-04-17 13:57:15 -07001763 }
Elliott Hughesb628cb12015-08-03 10:38:08 -07001764 if (okay && (src.empty() || src == "data")) {
1765 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes38104452015-04-17 13:57:15 -07001766 }
Elliott Hughesb628cb12015-08-03 10:38:08 -07001767 return okay ? 0 : 1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001768 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001769 /* passthrough commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001770 else if (!strcmp(argv[0],"get-state") ||
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001771 !strcmp(argv[0],"get-serialno") ||
1772 !strcmp(argv[0],"get-devpath"))
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001773 {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001774 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001775 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001776 /* other commands */
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001777 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001778 return logcat(transport_type, serial, argc, argv);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001779 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001780 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001781 return ppp(argc, argv);
1782 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001783 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes04a98c22015-04-29 08:35:59 -07001784 std::string error;
Spencer Low85ee64b2015-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 Project9ca14dc2009-03-03 19:32:55 -08001790 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001791 else if (!strcmp(argv[0], "backup")) {
Christopher Tate73779122011-04-21 12:53:28 -07001792 return backup(argc, argv);
1793 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001794 else if (!strcmp(argv[0], "restore")) {
Christopher Tatecf5379b2011-05-17 15:52:54 -07001795 return restore(argc, argv);
1796 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001797 else if (!strcmp(argv[0], "keygen")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001798 if (argc != 2) return syntax_error("keygen requires an argument");
Yabin Cui19bec5b2015-09-22 15:52:57 -07001799 // Always print key generation information for keygen command.
1800 adb_trace_enable(AUTH);
Nick Kralevich6183c962014-11-13 15:17:29 -08001801 return adb_auth_keygen(argv[1]);
1802 }
Riley Andrewsfacb92d2014-12-05 17:32:46 -08001803 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao0db67642015-03-29 11:22:34 -07001804 return adb_connect_command("jdwp");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001805 }
Josh Gao39d01bb2016-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 Project9ca14dc2009-03-03 19:32:55 -08001814 /* "adb /?" is a common idiom under Windows */
Elliott Hughes97e74bb2017-02-06 16:20:30 -08001815 else if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001816 help();
1817 return 0;
1818 }
Elliott Hughes97e74bb2017-02-06 16:20:30 -08001819 else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
Elliott Hughesb9f01642015-08-12 08:32:10 -07001820 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001821 return 0;
Josh Gao210b63f2017-02-22 17:07:01 -08001822 } else if (!strcmp(argv[0], "features")) {
David Pursella07dbad2015-09-22 10:43:08 -07001823 // Only list the features common to both the adb client and the device.
David Pursell9650d862016-01-21 19:56:50 -08001824 FeatureSet features;
Josh Gao91d53b52016-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 Pursell9650d862016-01-21 19:56:50 -08001828 return 1;
1829 }
1830
David Pursella07dbad2015-09-22 10:43:08 -07001831 for (const std::string& name : features) {
David Pursell22fc5e92015-09-30 13:35:42 -07001832 if (CanUseFeature(features, name)) {
David Pursella07dbad2015-09-22 10:43:08 -07001833 printf("%s\n", name.c_str());
1834 }
1835 }
1836 return 0;
Josh Gao210b63f2017-02-22 17:07:01 -08001837 } else if (!strcmp(argv[0], "host-features")) {
1838 return adb_query_command("host:host-features");
Yabin Cuid78ed222016-04-05 13:50:44 -07001839 } else if (!strcmp(argv[0], "reconnect")) {
1840 if (argc == 1) {
Yabin Cui3cf1b362017-03-10 16:01:01 -08001841 return adb_query_command(format_host_command(argv[0], transport_type, serial));
Josh Gao4e562502016-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 Hughes65bc2272017-04-18 14:34:16 -07001851 return syntax_error("adb reconnect [device|offline]");
Josh Gao4e562502016-10-27 14:01:08 -07001852 }
Yabin Cuid78ed222016-04-05 13:50:44 -07001853 }
Dan Albert996c12e2015-05-20 18:58:41 -07001854 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001855
Elliott Hughes65bc2272017-04-18 14:34:16 -07001856 syntax_error("unknown command %s", argv[0]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001857 return 1;
1858}
1859
Todd Kennedy1e2f7dc2015-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 Hughes170b5682015-04-17 10:59:34 -07001863 while (argc-- > 0) {
Todd Kennedy1e2f7dc2015-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 Hughese4b64792015-04-17 20:11:08 -07001873 cmd += " " + escape_arg(*argv++);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001874 }
1875
David Pursell22fc5e92015-09-30 13:35:42 -07001876 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001877}
1878
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001879static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08001880 // The last argument must be the APK file
1881 const char* file = argv[argc - 1];
Elliott Hughes976bd832016-10-24 18:29:21 -07001882 if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001883 return syntax_error("filename doesn't end .apk: %s", file);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001884 }
1885
Elliott Hughes976bd832016-10-24 18:29:21 -07001886 struct stat sb;
1887 if (stat(file, &sb) == -1) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001888 fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
Elliott Hughes976bd832016-10-24 18:29:21 -07001889 return 1;
Kenny Root3802c992011-08-05 11:19:45 -07001890 }
1891
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08001892 int localFd = adb_open(file, O_RDONLY);
1893 if (localFd < 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001894 fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08001895 return 1;
1896 }
Kenny Root3802c992011-08-05 11:19:45 -07001897
Todd Kennedy1e2f7dc2015-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 Hughes65bc2272017-04-18 14:34:16 -07001912 fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
Todd Kennedy1e2f7dc2015-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 Hughes65bc2272017-04-18 14:34:16 -07001924 if (!strncmp("Success", buf, 7)) {
1925 fputs(buf, stdout);
1926 return 0;
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08001927 }
Elliott Hughes65bc2272017-04-18 14:34:16 -07001928 fprintf(stderr, "adb: failed to install %s: %s", file, buf);
1929 return 1;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001930}
1931
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001932static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes38104452015-04-17 13:57:15 -07001933 const char** argv)
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001934{
Jeff Sharkey0e0d2512014-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 Hughes976bd832016-10-24 18:29:21 -07001938 uint64_t total_size = 0;
1939 for (int i = argc - 1; i >= 0; i--) {
Dan Albertf30d73c2015-02-25 17:51:28 -08001940 const char* file = argv[i];
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001941
Elliott Hughes976bd832016-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 Sharkey0e0d2512014-06-09 17:30:57 -07001945 first_apk = i;
1946 } else {
1947 break;
1948 }
Kenny Root3802c992011-08-05 11:19:45 -07001949 }
1950
Elliott Hughes65bc2272017-04-18 14:34:16 -07001951 if (first_apk == -1) return syntax_error("need APK file on command line");
Kenny Root3802c992011-08-05 11:19:45 -07001952
Todd Kennedy8c5cf622016-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 Hughes976bd832016-10-24 18:29:21 -07001961 for (int i = 1; i < first_apk; i++) {
Elliott Hughese4b64792015-04-17 20:11:08 -07001962 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001963 }
1964
1965 // Create install session
Elliott Hughes04a98c22015-04-29 08:35:59 -07001966 std::string error;
Elliott Hughesda945812015-04-29 12:28:13 -07001967 int fd = adb_connect(cmd, &error);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001968 if (fd < 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001969 fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08001970 return EXIT_FAILURE;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001971 }
Elliott Hughes170b5682015-04-17 10:59:34 -07001972 char buf[BUFSIZ];
Jeff Sharkey0e0d2512014-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 Hughes65bc2272017-04-18 14:34:16 -07001986 fprintf(stderr, "adb: failed to create session\n");
Christopher Tate29721da2014-07-14 16:45:13 -07001987 fputs(buf, stderr);
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08001988 return EXIT_FAILURE;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001989 }
1990
1991 // Valid session, now stream the APKs
1992 int success = 1;
Elliott Hughes976bd832016-10-24 18:29:21 -07001993 for (int i = first_apk; i < argc; i++) {
Dan Albertf30d73c2015-02-25 17:51:28 -08001994 const char* file = argv[i];
Elliott Hughes976bd832016-10-24 18:29:21 -07001995 struct stat sb;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001996 if (stat(file, &sb) == -1) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07001997 fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07001998 success = 0;
1999 goto finalize_session;
2000 }
2001
Elliott Hughesd1a5b2b2015-04-17 14:07:52 -07002002 std::string cmd = android::base::StringPrintf(
Todd Kennedy8c5cf622016-07-20 16:22:37 -07002003 "%s install-write -S %" PRIu64 " %d %d_%s -",
Colin Crosse6794072017-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 Sharkey0e0d2512014-06-09 17:30:57 -07002006
2007 int localFd = adb_open(file, O_RDONLY);
2008 if (localFd < 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07002009 fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002010 success = 0;
2011 goto finalize_session;
2012 }
2013
Elliott Hughes04a98c22015-04-29 08:35:59 -07002014 std::string error;
Elliott Hughesda945812015-04-29 12:28:13 -07002015 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002016 if (remoteFd < 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07002017 fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
Jeff Sharkey0e0d2512014-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 Hughes65bc2272017-04-18 14:34:16 -07002030 fprintf(stderr, "adb: failed to write %s\n", file);
Christopher Tate29721da2014-07-14 16:45:13 -07002031 fputs(buf, stderr);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002032 success = 0;
2033 goto finalize_session;
2034 }
2035 }
2036
2037finalize_session:
Jeff Sharkey01f6fbf2014-07-25 09:58:25 -07002038 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughesda945812015-04-29 12:28:13 -07002039 std::string service =
Todd Kennedy8c5cf622016-07-20 16:22:37 -07002040 android::base::StringPrintf("%s install-%s %d",
2041 install_cmd.c_str(), success ? "commit" : "abandon", session_id);
Elliott Hughesda945812015-04-29 12:28:13 -07002042 fd = adb_connect(service, &error);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002043 if (fd < 0) {
Elliott Hughes65bc2272017-04-18 14:34:16 -07002044 fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08002045 return EXIT_FAILURE;
Jeff Sharkey0e0d2512014-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 Hughes65bc2272017-04-18 14:34:16 -07002051 fputs(buf, stdout);
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002052 return 0;
Jeff Sharkey0e0d2512014-06-09 17:30:57 -07002053 }
Elliott Hughes65bc2272017-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 Project9ca14dc2009-03-03 19:32:55 -08002057}
Todd Kennedy1e2f7dc2015-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 Kennedy1e2f7dc2015-11-03 16:53:08 -08002097
Elliott Hughes976bd832016-10-24 18:29:21 -07002098 for (int i = 1; i < argc; i++) {
Todd Kennedy1e2f7dc2015-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 Hughes976bd832016-10-24 18:29:21 -07002107 for (int i = argc - 1; i >= 0; i--) {
2108 if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) {
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -08002109 last_apk = i;
2110 break;
2111 }
2112 }
2113
Elliott Hughes65bc2272017-04-18 14:34:16 -07002114 if (last_apk == -1) return syntax_error("need APK file on command line");
Todd Kennedy1e2f7dc2015-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 Crosse6794072017-02-23 21:23:05 -08002119 where, android::base::Basename(argv[last_apk]).c_str());
Todd Kennedy1e2f7dc2015-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}