blob: 81158e9da7912df442b29fd2e168a2ff3f93d65f [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG ADB
Dan Albert33134262015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20
Dan Albert76649012015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
Elliott Hughes2940ccf2015-04-17 14:07:52 -070024#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <limits.h>
26#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <stdint.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080032#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033
David Pursell606835a2015-09-08 17:17:02 -070034#include <memory>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070035#include <string>
Josh Gao05786772015-10-30 16:57:19 -070036#include <vector>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070037
David Pursell606835a2015-09-08 17:17:02 -070038#include <base/logging.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070039#include <base/stringprintf.h>
David Pursell4e2fd362015-09-22 10:43:08 -070040#include <base/strings.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070041
Yabin Cuid325e862014-11-17 14:48:25 -080042#if !defined(_WIN32)
Josh Gao8dcdb572015-10-23 15:03:31 -070043#include <signal.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080044#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080045#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046#endif
47
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080049#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080050#include "adb_client.h"
51#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070052#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080053#include "file_sync_service.h"
David Pursell70ef7b42015-09-30 13:35:42 -070054#include "services.h"
David Pursell606835a2015-09-08 17:17:02 -070055#include "shell_service.h"
56#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080057
Elliott Hughes3bd73c12015-05-05 13:10:43 -070058static int install_app(TransportType t, const char* serial, int argc, const char** argv);
59static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
60static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
Todd Kennedyd0398002015-11-03 16:53:08 -080061static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
62static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080063
Elliott Hughes58305772015-04-17 13:57:15 -070064static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080065extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066
Elliott Hughes58305772015-04-17 13:57:15 -070067static std::string product_file(const char *extra) {
68 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080069 fprintf(stderr, "adb: Product directory not specified; "
70 "use -p or define ANDROID_PRODUCT_OUT\n");
71 exit(1);
72 }
73
Elliott Hughes58305772015-04-17 13:57:15 -070074 return android::base::StringPrintf("%s%s%s",
75 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080076}
77
Elliott Hughes58305772015-04-17 13:57:15 -070078static void help() {
Elliott Hughes42ae2602015-08-12 08:32:10 -070079 fprintf(stderr, "%s\n", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080080 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -080081 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080082 " -d - directs command to the only connected USB device\n"
83 " returns an error if more than one USB device is present.\n"
84 " -e - directs command to the only running emulator.\n"
85 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070086 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070087 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070088 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080089 " -p <product name or path> - simple product name like 'sooner', or\n"
90 " a relative/absolute path to a product\n"
91 " out directory like 'out/target/product/sooner'.\n"
92 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
93 " environment variable is used, which must\n"
94 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080095 " -H - Name of adb server host (default: localhost)\n"
96 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070097 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070098 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040099 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
100 " Port 5555 is used by default if no port number is specified.\n"
101 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
102 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200103 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400104 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800105 "\n"
106 "device commands:\n"
Josh Gao05786772015-10-30 16:57:19 -0700107 " adb push <local>... <remote>\n"
108 " - copy files/dirs to device\n"
109 " adb pull [-a] <remote>... <local>\n"
110 " - copy files/dirs from device\n"
111 " (-a preserves file timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800112 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600113 " (-l means list but don't copy)\n"
David Pursell70ef7b42015-09-30 13:35:42 -0700114 " adb shell [-Ttx] - run remote shell interactively\n"
115 " adb shell [-Ttx] <command> - run remote shell command\n"
David Pursell4e2fd362015-09-22 10:43:08 -0700116 " (-T disables PTY allocation)\n"
117 " (-t forces PTY allocation)\n"
David Pursell70ef7b42015-09-30 13:35:42 -0700118 " (-x disables remote exit codes and stdout/stderr separation)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119 " adb emu <command> - run emulator console command\n"
120 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100121 " adb forward --list - list all forward socket connections.\n"
122 " the format is a list of lines with the following format:\n"
123 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800124 " adb forward <local> <remote> - forward socket connections\n"
125 " forward specs are one of: \n"
126 " tcp:<port>\n"
127 " localabstract:<unix domain socket name>\n"
128 " localreserved:<unix domain socket name>\n"
129 " localfilesystem:<unix domain socket name>\n"
130 " dev:<character device name>\n"
131 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100132 " adb forward --no-rebind <local> <remote>\n"
133 " - same as 'adb forward <local> <remote>' but fails\n"
134 " if <local> is already forwarded\n"
135 " adb forward --remove <local> - remove a specific forward socket connection\n"
136 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100137 " adb reverse --list - list all reverse socket connections from device\n"
138 " adb reverse <remote> <local> - reverse socket connections\n"
139 " reverse specs are one of:\n"
140 " tcp:<port>\n"
141 " localabstract:<unix domain socket name>\n"
142 " localreserved:<unix domain socket name>\n"
143 " localfilesystem:<unix domain socket name>\n"
Spencer Low587ea202015-11-02 17:34:49 -0800144 " adb reverse --no-rebind <remote> <local>\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100145 " - same as 'adb reverse <remote> <local>' but fails\n"
146 " if <remote> is already reversed.\n"
147 " adb reverse --remove <remote>\n"
148 " - remove a specific reversed socket connection\n"
149 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900151 " adb install [-lrtsdg] <file>\n"
Svetoslav23d84072015-06-01 16:02:50 -0700152 " - push this package file to the device and install it\n"
153 " (-l: forward lock application)\n"
154 " (-r: replace existing application)\n"
155 " (-t: allow test packages)\n"
156 " (-s: install application on sdcard)\n"
157 " (-d: allow version code downgrade)\n"
158 " (-g: grant all runtime permissions)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900159 " adb install-multiple [-lrtsdpg] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700160 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700161 " (-l: forward lock application)\n"
162 " (-r: replace existing application)\n"
163 " (-t: allow test packages)\n"
164 " (-s: install application on sdcard)\n"
165 " (-d: allow version code downgrade)\n"
166 " (-p: partial application install)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900167 " (-g: grant all runtime permissions)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168 " adb uninstall [-k] <package> - remove this app package from the device\n"
169 " ('-k' means keep the data and cache directories)\n"
170 " adb bugreport - return all information from the device\n"
171 " that should be included in a bug report.\n"
172 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800173 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700174 " - write an archive of the device's data to <file>.\n"
175 " If no -f option is supplied then the data is written\n"
176 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700177 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700178 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800179 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
180 " (aka .obb) files associated with each application; the default\n"
181 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700182 " (-shared|-noshared enable/disable backup of the device's\n"
183 " shared storage / SD card contents; the default is noshared.)\n"
184 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700185 " (-system|-nosystem toggles whether -all automatically includes\n"
186 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700187 " (<packages...> is the list of applications to be backed up. If\n"
188 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700189 " list is optional. Applications explicitly given on the\n"
190 " command line will be included even if -nosystem would\n"
191 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700192 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700193 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700194 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800195 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
196 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800197 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
198 " and the public key is stored in <file>.pub. Any existing files\n"
199 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 " adb help - show this help message\n"
201 " adb version - show version num\n"
202 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800203 "scripting:\n"
204 " adb wait-for-device - block until device is online\n"
205 " adb start-server - ensure that there is a server running\n"
206 " adb kill-server - kill the server if it is running\n"
207 " adb get-state - prints: offline | bootloader | device\n"
208 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700209 " adb get-devpath - prints: <device-path>\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000210 " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
Tao Bao175b7bb2015-03-29 11:22:34 -0700211 " adb reboot [bootloader|recovery]\n"
212 " - reboots the device, optionally into the bootloader or recovery program.\n"
213 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
214 " adb reboot sideload-auto-reboot\n"
215 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700216 " adb sideload <file> - sideloads the given package\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700217 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500218 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800219 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000220 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700221 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800222 "networking:\n"
223 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500224 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800225 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
226 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
227 "\n"
228 "adb sync notes: adb sync [ <directory> ]\n"
229 " <localdir> can be interpreted in several ways:\n"
230 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000231 " - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800232 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000233 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000235 "\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700236 "environment variables:\n"
Timcd643152010-02-16 20:18:29 +0000237 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
238 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
239 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
240 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 );
242}
243
Elliott Hughes58305772015-04-17 13:57:15 -0700244static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245 help();
246 return 1;
247}
248
Yabin Cuid325e862014-11-17 14:48:25 -0800249#if defined(_WIN32)
250
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700251// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800252void stdin_raw_init(int fd);
253void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800254
255#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100256static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100258static void stdin_raw_init(int fd) {
259 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800260
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100261 termios tio;
262 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100264 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100266 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 tio.c_cc[VTIME] = 0;
268 tio.c_cc[VMIN] = 1;
269
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100270 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800271}
272
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100273static void stdin_raw_restore(int fd) {
274 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800275}
276#endif
277
David Pursell606835a2015-09-08 17:17:02 -0700278// Reads from |fd| and prints received data. If |use_shell_protocol| is true
279// this expects that incoming data will use the shell protocol, in which case
280// stdout/stderr are routed independently and the remote exit code will be
281// returned.
282static int read_and_dump(int fd, bool use_shell_protocol=false) {
283 int exit_code = 0;
284 std::unique_ptr<ShellProtocol> protocol;
285 int length = 0;
286 FILE* outfile = stdout;
287
288 char raw_buffer[BUFSIZ];
289 char* buffer_ptr = raw_buffer;
290 if (use_shell_protocol) {
291 protocol.reset(new ShellProtocol(fd));
292 if (!protocol) {
293 LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
294 return 1;
295 }
296 buffer_ptr = protocol->data();
297 }
298
Elliott Hughes5677c232015-05-07 23:37:40 -0700299 while (fd >= 0) {
David Pursell606835a2015-09-08 17:17:02 -0700300 if (use_shell_protocol) {
301 if (!protocol->Read()) {
302 break;
303 }
304 switch (protocol->id()) {
305 case ShellProtocol::kIdStdout:
306 outfile = stdout;
307 break;
308 case ShellProtocol::kIdStderr:
309 outfile = stderr;
310 break;
311 case ShellProtocol::kIdExit:
312 exit_code = protocol->data()[0];
313 continue;
314 default:
315 continue;
316 }
317 length = protocol->data_length();
318 } else {
319 D("read_and_dump(): pre adb_read(fd=%d)", fd);
320 length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
321 D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
322 if (length <= 0) {
323 break;
324 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800325 }
326
David Pursell606835a2015-09-08 17:17:02 -0700327 fwrite(buffer_ptr, 1, length, outfile);
328 fflush(outfile);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800329 }
David Pursell606835a2015-09-08 17:17:02 -0700330
331 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800332}
333
Jeff Sharkey960df972014-06-09 17:30:57 -0700334static void read_status_line(int fd, char* buf, size_t count)
335{
336 count--;
337 while (count > 0) {
338 int len = adb_read(fd, buf, count);
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700339 if (len <= 0) {
Jeff Sharkey960df972014-06-09 17:30:57 -0700340 break;
341 }
342
343 buf += len;
344 count -= len;
345 }
346 *buf = '\0';
347}
348
Christopher Tated2f54152011-04-21 12:53:28 -0700349static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700350 const size_t BUFSIZE = 32 * 1024;
351 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700352 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700353 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700354 long total = 0;
Spencer Lowb7dfb792015-05-22 16:48:31 -0700355#ifdef _WIN32
356 int old_stdin_mode = -1;
357 int old_stdout_mode = -1;
358#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700359
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700360 D("copy_to_file(%d -> %d)", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800361
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700362 if (inFd == STDIN_FILENO) {
363 stdin_raw_init(STDIN_FILENO);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700364#ifdef _WIN32
365 old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
366 if (old_stdin_mode == -1) {
367 fatal_errno("could not set stdin to binary");
368 }
369#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700370 }
Yabin Cuid325e862014-11-17 14:48:25 -0800371
Spencer Lowb7dfb792015-05-22 16:48:31 -0700372#ifdef _WIN32
373 if (outFd == STDOUT_FILENO) {
374 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
375 if (old_stdout_mode == -1) {
376 fatal_errno("could not set stdout to binary");
377 }
378 }
379#endif
380
Elliott Hughesa7090b92015-04-17 17:03:59 -0700381 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700382 if (inFd == STDIN_FILENO) {
383 len = unix_read(inFd, buf, BUFSIZE);
384 } else {
385 len = adb_read(inFd, buf, BUFSIZE);
386 }
Christopher Tated2f54152011-04-21 12:53:28 -0700387 if (len == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700388 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tated2f54152011-04-21 12:53:28 -0700389 break;
390 }
391 if (len < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700392 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tated2f54152011-04-21 12:53:28 -0700393 break;
394 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700395 if (outFd == STDOUT_FILENO) {
396 fwrite(buf, 1, len, stdout);
397 fflush(stdout);
398 } else {
399 adb_write(outFd, buf, len);
400 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700401 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700402 }
Yabin Cuid325e862014-11-17 14:48:25 -0800403
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700404 if (inFd == STDIN_FILENO) {
405 stdin_raw_restore(STDIN_FILENO);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700406#ifdef _WIN32
407 if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
408 fatal_errno("could not restore stdin mode");
409 }
410#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700411 }
Yabin Cuid325e862014-11-17 14:48:25 -0800412
Spencer Lowb7dfb792015-05-22 16:48:31 -0700413#ifdef _WIN32
414 if (outFd == STDOUT_FILENO) {
415 if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
416 fatal_errno("could not restore stdout mode");
417 }
418 }
419#endif
420
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700421 D("copy_to_file() finished after %lu bytes", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700422 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700423}
424
David Pursell606835a2015-09-08 17:17:02 -0700425namespace {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426
David Pursell606835a2015-09-08 17:17:02 -0700427// Used to pass multiple values to the stdin read thread.
428struct StdinReadArgs {
429 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700430 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700431 std::unique_ptr<ShellProtocol> protocol;
432};
433
434} // namespace
435
436// Loops to read from stdin and push the data to the given FD.
437// The argument should be a pointer to a StdinReadArgs object. This function
438// will take ownership of the object and delete it when finished.
439static void* stdin_read_thread(void* x) {
440 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
441 int state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800442
Siva Velusamy49ee7cf2015-08-28 16:37:29 -0700443 adb_thread_setname("stdin reader");
444
Josh Gao4a139722015-10-30 18:38:34 -0700445#ifndef _WIN32
Josh Gao8dcdb572015-10-23 15:03:31 -0700446 // Mask SIGTTIN in case we're in a backgrounded process
447 sigset_t sigset;
448 sigemptyset(&sigset);
449 sigaddset(&sigset, SIGTTIN);
450 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
451#endif
452
David Pursell606835a2015-09-08 17:17:02 -0700453 char raw_buffer[1024];
454 char* buffer_ptr = raw_buffer;
455 size_t buffer_size = sizeof(raw_buffer);
456 if (args->protocol) {
457 buffer_ptr = args->protocol->data();
458 buffer_size = args->protocol->data_capacity();
459 }
460
Elliott Hughesaa245492015-08-03 10:38:08 -0700461 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700462 // Use unix_read() rather than adb_read() for stdin.
463 D("stdin_read_thread(): pre unix_read(fdi=%d,...)", args->stdin_fd);
464 int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size);
465 D("stdin_read_thread(): post unix_read(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700466 if (r <= 0) {
467 // Only devices using the shell protocol know to close subprocess
468 // stdin. For older devices we want to just leave the connection
469 // open, otherwise an unpredictable amount of return data could
470 // be lost due to the FD closing before all data has been received.
471 if (args->protocol) {
472 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
473 }
474 break;
475 }
476 // If we made stdin raw, check input for the "~." escape sequence. In
477 // this situation signals like Ctrl+C are sent remotely rather than
478 // interpreted locally so this provides an emergency out if the remote
479 // process starts ignoring the signal. SSH also does this, see the
480 // "escape characters" section on the ssh man page for more info.
481 if (args->raw_stdin) {
482 for (int n = 0; n < r; n++){
483 switch(buffer_ptr[n]) {
484 case '\n':
485 state = 1;
486 break;
487 case '\r':
488 state = 1;
489 break;
490 case '~':
David Pursell08a27092015-10-20 14:19:36 -0700491 if(state == 1) {
492 state++;
493 } else {
494 state = 0;
495 }
David Pursell1ed57f02015-10-06 15:30:03 -0700496 break;
497 case '.':
498 if(state == 2) {
499 stdin_raw_restore(args->stdin_fd);
500 fprintf(stderr,"\n* disconnect *\n");
501 exit(0);
502 }
503 default:
504 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800505 }
506 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800507 }
David Pursell606835a2015-09-08 17:17:02 -0700508 if (args->protocol) {
509 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
510 break;
511 }
512 } else {
513 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
514 break;
515 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800516 }
517 }
David Pursell606835a2015-09-08 17:17:02 -0700518
519 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800520}
521
David Pursell1ed57f02015-10-06 15:30:03 -0700522// Returns a shell service string with the indicated arguments and command.
523static std::string ShellServiceString(bool use_shell_protocol,
524 const std::string& type_arg,
525 const std::string& command) {
526 std::vector<std::string> args;
527 if (use_shell_protocol) {
528 args.push_back(kShellServiceArgShellProtocol);
529 }
530 if (!type_arg.empty()) {
531 args.push_back(type_arg);
532 }
533
534 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
535 return android::base::StringPrintf("shell%s%s:%s",
536 args.empty() ? "" : ",",
537 android::base::Join(args, ',').c_str(),
538 command.c_str());
539}
540
541// Connects to a shell on the device and read/writes data.
542//
543// Note: currently this function doesn't properly clean up resources; the
544// FD connected to the adb server is never closed and the stdin read thread
545// may never exit.
546//
547// On success returns the remote exit code if |use_shell_protocol| is true,
548// 0 otherwise. On failure returns 1.
549static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
550 const std::string& command) {
551 std::string service_string = ShellServiceString(use_shell_protocol,
552 type_arg, command);
553
554 // Make local stdin raw if the device allocates a PTY, which happens if:
555 // 1. We are explicitly asking for a PTY shell, or
556 // 2. We don't specify shell type and are starting an interactive session.
557 bool raw_stdin = (type_arg == kShellServiceArgPty ||
558 (type_arg.empty() && command.empty()));
559
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700560 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700561 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700562 if (fd < 0) {
563 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800564 return 1;
565 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800566
David Pursell606835a2015-09-08 17:17:02 -0700567 StdinReadArgs* args = new StdinReadArgs;
568 if (!args) {
569 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700570 return 1;
571 }
David Pursell1ed57f02015-10-06 15:30:03 -0700572 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700573 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700574 args->raw_stdin = raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700575 if (use_shell_protocol) {
576 args->protocol.reset(new ShellProtocol(args->write_fd));
577 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700578
David Pursell1ed57f02015-10-06 15:30:03 -0700579 if (raw_stdin) {
580 stdin_raw_init(STDIN_FILENO);
581 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800582
David Pursell606835a2015-09-08 17:17:02 -0700583 int exit_code = 0;
584 if (!adb_thread_create(stdin_read_thread, args)) {
585 PLOG(ERROR) << "error starting stdin read thread";
586 exit_code = 1;
587 delete args;
588 } else {
589 exit_code = read_and_dump(fd, use_shell_protocol);
590 }
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700591
David Pursell1ed57f02015-10-06 15:30:03 -0700592 if (raw_stdin) {
593 stdin_raw_restore(STDIN_FILENO);
594 }
595
596 // TODO(dpursell): properly exit stdin_read_thread and close |fd|.
597
David Pursell606835a2015-09-08 17:17:02 -0700598 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800599}
600
601
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700602static std::string format_host_command(const char* command, TransportType type, const char* serial) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800603 if (serial) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700604 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800605 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700606
607 const char* prefix = "host";
608 if (type == kTransportUsb) {
609 prefix = "host-usb";
610 } else if (type == kTransportLocal) {
611 prefix = "host-local";
612 }
613 return android::base::StringPrintf("%s:%s", prefix, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800614}
615
David Pursell4e2fd362015-09-22 10:43:08 -0700616// Returns the FeatureSet for the indicated transport.
617static FeatureSet GetFeatureSet(TransportType transport_type,
David Pursell71c83122015-09-14 15:33:50 -0700618 const char* serial) {
David Pursell4e2fd362015-09-22 10:43:08 -0700619 std::string result, error;
620
621 if (adb_query(format_host_command("features", transport_type, serial),
622 &result, &error)) {
623 return StringToFeatureSet(result);
David Pursell71c83122015-09-14 15:33:50 -0700624 }
David Pursell4e2fd362015-09-22 10:43:08 -0700625 return FeatureSet();
David Pursell71c83122015-09-14 15:33:50 -0700626}
627
Elliott Hughes6452a892015-04-29 12:28:13 -0700628static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700629 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800630{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700631 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700632 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700633 if (fd < 0) {
634 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800635 return -1;
636 }
637
638 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800639 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800640
Elliott Hughes6452a892015-04-29 12:28:13 -0700641 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800642 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800643
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700644 if (show_progress) {
Elliott Hughes3e7048c2015-07-27 21:21:39 -0700645 const char* x = strrchr(service, ':');
646 if (x) service = x + 1;
Doug Zongker447f0612012-01-09 14:54:53 -0800647 }
648
Elliott Hughes6452a892015-04-29 12:28:13 -0700649 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800650 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700651 if (!WriteFdExactly(fd, ptr, xfer)) {
652 std::string error;
653 adb_status(fd, &error);
654 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700655 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800656 return -1;
657 }
658 sz -= xfer;
659 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700660 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100661 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800662 fflush(stdout);
663 }
664 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700665 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800666 printf("\n");
667 }
668
Elliott Hughese67f1f82015-04-30 17:32:03 -0700669 if (!adb_status(fd, &error)) {
670 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700671 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800672 return -1;
673 }
674
675 adb_close(fd);
676 return 0;
677}
678
Doug Zongker71fe5842014-06-26 15:35:36 -0700679#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
680
681/*
682 * The sideload-host protocol serves the data in a file (given on the
683 * command line) to the client, using a simple protocol:
684 *
685 * - The connect message includes the total number of bytes in the
686 * file and a block size chosen by us.
687 *
688 * - The other side sends the desired block number as eight decimal
689 * digits (eg "00000023" for block 23). Blocks are numbered from
690 * zero.
691 *
692 * - We send back the data of the requested block. The last block is
693 * likely to be partial; when the last block is requested we only
694 * send the part of the block that exists, it's not padded up to the
695 * block size.
696 *
697 * - When the other side sends "DONEDONE" instead of a block number,
698 * we hang up.
699 */
Elliott Hughes58305772015-04-17 13:57:15 -0700700static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700701 unsigned sz;
702 size_t xfer = 0;
703 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800704 int last_percent = -1;
705 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700706
707 printf("loading: '%s'", fn);
708 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800709 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700710 if (data == 0) {
711 printf("\n");
712 fprintf(stderr, "* cannot read '%s' *\n", fn);
713 return -1;
714 }
715
Elliott Hughes6452a892015-04-29 12:28:13 -0700716 std::string service =
717 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700718 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700719 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700720 if (fd < 0) {
721 // Try falling back to the older sideload method. Maybe this
722 // is an older device that doesn't support sideload-host.
723 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700724 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700725 goto done;
726 }
727
Spencer Lowf055c192015-01-25 14:40:16 -0800728 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700729
Elliott Hughesa7090b92015-04-17 17:03:59 -0700730 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700731 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800732 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700733 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700734 status = -1;
735 goto done;
736 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700737 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700738
Elliott Hughes6452a892015-04-29 12:28:13 -0700739 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700740 status = 0;
741 break;
742 }
743
Doug Zongker71fe5842014-06-26 15:35:36 -0700744 int block = strtol(buf, NULL, 10);
745
746 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
747 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700748 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700749 status = -1;
750 goto done;
751 }
752 uint8_t* start = data + offset;
753 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
754 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
755 if (offset_end > sz) {
756 to_write = sz - offset;
757 }
758
Dan Albertcc731cc2015-02-24 21:26:58 -0800759 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700760 adb_status(fd, &error);
761 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700762 status = -1;
763 goto done;
764 }
765 xfer += to_write;
766
767 // For normal OTA packages, we expect to transfer every byte
768 // twice, plus a bit of overhead (one read during
769 // verification, one read of each byte for installation, plus
770 // extra access to things like the zip central directory).
771 // This estimate of the completion becomes 100% when we've
772 // transferred ~2.13 (=100/47) times the package size.
773 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
774 if (percent != last_percent) {
775 printf("\rserving: '%s' (~%d%%) ", fn, percent);
776 fflush(stdout);
777 last_percent = percent;
778 }
779 }
780
Colin Cross6d6a8982014-07-07 14:12:41 -0700781 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700782
783 done:
784 if (fd >= 0) adb_close(fd);
785 free(data);
786 return status;
787}
788
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800789/**
790 * Run ppp in "notty" mode against a resource listed as the first parameter
791 * eg:
792 *
793 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
794 *
795 */
Elliott Hughes58305772015-04-17 13:57:15 -0700796static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800797#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800798 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
799 return -1;
800#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800801 if (argc < 2) {
802 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
803 argv[0]);
804
805 return 1;
806 }
807
Dan Albertbac34742015-02-25 17:51:28 -0800808 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700809 std::string error;
810 int fd = adb_connect(adb_service_name, &error);
811 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800812 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700813 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800814 return 1;
815 }
816
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700817 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800818
819 if (pid < 0) {
820 perror("from fork()");
821 return 1;
822 } else if (pid == 0) {
823 int err;
824 int i;
825 const char **ppp_args;
826
827 // copy args
828 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
829 ppp_args[0] = "pppd";
830 for (i = 2 ; i < argc ; i++) {
831 //argv[2] and beyond become ppp_args[1] and beyond
832 ppp_args[i - 1] = argv[i];
833 }
834 ppp_args[i-1] = NULL;
835
836 // child side
837
838 dup2(fd, STDIN_FILENO);
839 dup2(fd, STDOUT_FILENO);
840 adb_close(STDERR_FILENO);
841 adb_close(fd);
842
843 err = execvp("pppd", (char * const *)ppp_args);
844
845 if (err < 0) {
846 perror("execing pppd");
847 }
848 exit(-1);
849 } else {
850 // parent side
851
852 adb_close(fd);
853 return 0;
854 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800855#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800856}
857
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700858static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700859 // Was the caller vague about what they'd like us to wait for?
860 // If so, check they weren't more specific in their choice of transport type.
861 if (strcmp(service, "wait-for-device") == 0) {
862 if (t == kTransportUsb) {
863 service = "wait-for-usb";
864 } else if (t == kTransportLocal) {
865 service = "wait-for-local";
866 } else {
867 service = "wait-for-any";
868 }
869 }
870
871 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700872 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700873}
874
David Pursell70ef7b42015-09-30 13:35:42 -0700875// Connects to the device "shell" service with |command| and prints the
876// resulting output.
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700877static int send_shell_command(TransportType transport_type, const char* serial,
David Pursell70ef7b42015-09-30 13:35:42 -0700878 const std::string& command,
879 bool disable_shell_protocol) {
880 // Only use shell protocol if it's supported and the caller doesn't want
881 // to explicitly disable it.
882 bool use_shell_protocol = false;
883 if (!disable_shell_protocol) {
884 FeatureSet features = GetFeatureSet(transport_type, serial);
885 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
886 }
887
888 std::string service_string = ShellServiceString(use_shell_protocol, "",
889 command);
890
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700891 int fd;
892 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700893 std::string error;
David Pursell70ef7b42015-09-30 13:35:42 -0700894 fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700895 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800896 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700897 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898 fprintf(stderr,"- waiting for device -\n");
899 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -0700900 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800901 }
902
David Pursell70ef7b42015-09-30 13:35:42 -0700903 int exit_code = read_and_dump(fd, use_shell_protocol);
David Pursell71c83122015-09-14 15:33:50 -0700904
905 if (adb_close(fd) < 0) {
906 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700907 }
David Pursell71c83122015-09-14 15:33:50 -0700908
909 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800910}
911
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700912static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700913 char* log_tags = getenv("ANDROID_LOG_TAGS");
914 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800915
David Pursell70ef7b42015-09-30 13:35:42 -0700916 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800917
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700918 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700919 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800920 }
921
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700922 --argc;
923 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700924 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700925 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800926 }
927
David Pursell70ef7b42015-09-30 13:35:42 -0700928 // No need for shell protocol with logcat, always disable for simplicity.
929 return send_shell_command(transport, serial, cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800930}
931
Dan Albertbac34742015-02-25 17:51:28 -0800932static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -0700933 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700934
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700935 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700936 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700937 if (!strcmp("-f", argv[i])) {
938 if (i == argc-1) {
939 fprintf(stderr, "adb: -f passed with no filename\n");
940 return usage();
941 }
942 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700943 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700944 argv[i++] = argv[j++];
945 }
946 argc -= 2;
947 argv[argc] = NULL;
948 }
Christopher Tated2f54152011-04-21 12:53:28 -0700949 }
950
Christopher Tatebb86bc52011-08-22 17:12:08 -0700951 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
952 if (argc < 2) return usage();
953
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800954 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700955 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700956 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700957 if (outFd < 0) {
958 fprintf(stderr, "adb: unable to open file %s\n", filename);
959 return -1;
960 }
961
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700962 std::string cmd = "backup:";
963 --argc;
964 ++argv;
965 while (argc-- > 0) {
966 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700967 }
968
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700969 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700970 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700971 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -0700972 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700973 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700974 adb_close(outFd);
975 return -1;
976 }
977
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800978 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700979 copy_to_file(fd, outFd);
980
981 adb_close(fd);
982 adb_close(outFd);
983 return 0;
984}
985
Dan Albertbac34742015-02-25 17:51:28 -0800986static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700987 if (argc != 2) return usage();
988
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700989 const char* filename = argv[1];
990 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -0700991 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700992 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -0700993 return -1;
994 }
995
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700996 std::string error;
997 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -0700998 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700999 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -07001000 adb_close(tarFd);
1001 return -1;
1002 }
1003
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001004 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -07001005 copy_to_file(tarFd, fd);
1006
1007 adb_close(fd);
1008 adb_close(tarFd);
1009 return 0;
1010}
1011
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012/* <hint> may be:
1013 * - A simple product name
1014 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001015 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1016 * e.g., "out/target/product/sooner"
1017 * - An absolute path to the PRODUCT_OUT dir
1018 * e.g., "/src/device/out/target/product/sooner"
1019 *
1020 * Given <hint>, try to construct an absolute path to the
1021 * ANDROID_PRODUCT_OUT dir.
1022 */
Elliott Hughes5c742702015-07-30 17:42:01 -07001023static std::string find_product_out_path(const std::string& hint) {
1024 if (hint.empty()) {
Elliott Hughes58305772015-04-17 13:57:15 -07001025 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001026 }
1027
Elliott Hughes58305772015-04-17 13:57:15 -07001028 // If it's already absolute, don't bother doing any work.
Elliott Hughes5c742702015-07-30 17:42:01 -07001029 if (adb_is_absolute_host_path(hint.c_str())) {
Elliott Hughes58305772015-04-17 13:57:15 -07001030 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001031 }
1032
Elliott Hughes58305772015-04-17 13:57:15 -07001033 // If there are any slashes in it, assume it's a relative path;
1034 // make it absolute.
Elliott Hughes5c742702015-07-30 17:42:01 -07001035 if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001036 std::string cwd;
1037 if (!getcwd(&cwd)) {
1038 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -07001039 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001040 }
Elliott Hughes5c742702015-07-30 17:42:01 -07001041 return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001042 }
1043
Elliott Hughes58305772015-04-17 13:57:15 -07001044 // It's a string without any slashes. Try to do something with it.
1045 //
1046 // Try to find the root of the build tree, and build a PRODUCT_OUT
1047 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -07001048 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -07001049 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001050 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -07001051 return "";
1052 }
Elliott Hughesa7090b92015-04-17 17:03:59 -07001053
1054 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -07001055 path += OS_PATH_SEPARATOR_STR;
1056 path += "out";
1057 path += OS_PATH_SEPARATOR_STR;
1058 path += "target";
1059 path += OS_PATH_SEPARATOR_STR;
1060 path += "product";
1061 path += OS_PATH_SEPARATOR_STR;
1062 path += hint;
1063 if (!directory_exists(path)) {
1064 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
Elliott Hughes5c742702015-07-30 17:42:01 -07001065 "\"%s\" doesn't exist\n", hint.c_str(), path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -07001066 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001067 }
Elliott Hughes58305772015-04-17 13:57:15 -07001068 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001069}
1070
Josh Gao05786772015-10-30 16:57:19 -07001071static void parse_push_pull_args(const char** arg, int narg,
1072 std::vector<const char*>* srcs,
1073 const char** dst, bool* copy_attrs) {
1074 *copy_attrs = false;
Mark Lindner76f2a932014-03-11 17:55:59 -07001075
Josh Gao05786772015-10-30 16:57:19 -07001076 srcs->clear();
1077 bool ignore_flags = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001078 while (narg > 0) {
Josh Gao05786772015-10-30 16:57:19 -07001079 if (ignore_flags || *arg[0] != '-') {
1080 srcs->push_back(*arg);
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001081 } else {
Josh Gao05786772015-10-30 16:57:19 -07001082 if (!strcmp(*arg, "-p")) {
1083 // Silently ignore for backwards compatibility.
1084 } else if (!strcmp(*arg, "-a")) {
1085 *copy_attrs = true;
1086 } else if (!strcmp(*arg, "--")) {
1087 ignore_flags = true;
1088 } else {
1089 fprintf(stderr, "adb: unrecognized option '%s'\n", *arg);
1090 exit(1);
1091 }
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001092 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001093 ++arg;
1094 --narg;
1095 }
1096
Josh Gao05786772015-10-30 16:57:19 -07001097 if (srcs->size() > 1) {
1098 *dst = srcs->back();
1099 srcs->pop_back();
Mark Lindner76f2a932014-03-11 17:55:59 -07001100 }
1101}
1102
Elliott Hughes6452a892015-04-29 12:28:13 -07001103static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001104 std::string error;
1105 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001106 if (fd < 0) {
1107 fprintf(stderr, "error: %s\n", error.c_str());
1108 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001109 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001110 read_and_dump(fd);
1111 adb_close(fd);
1112 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001113}
1114
Elliott Hughes6452a892015-04-29 12:28:13 -07001115static int adb_query_command(const std::string& command) {
1116 std::string result;
1117 std::string error;
1118 if (!adb_query(command, &result, &error)) {
1119 fprintf(stderr, "error: %s\n", error.c_str());
1120 return 1;
1121 }
1122 printf("%s\n", result.c_str());
1123 return 0;
1124}
1125
Spencer Lowa13df302015-09-07 16:20:13 -07001126// Disallow stdin, stdout, and stderr.
1127static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1128#ifdef _WIN32
1129 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1130 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1131 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1132 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1133#else
1134 return ack_reply_fd > 2;
1135#endif
1136}
1137
Elliott Hughesab52c182015-05-01 17:04:38 -07001138int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139 int no_daemon = 0;
1140 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001141 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001142 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001143 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001144 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001145
Elliott Hughes58305772015-04-17 13:57:15 -07001146 // If defined, this should be an absolute path to
1147 // the directory containing all of the various system images
1148 // for a particular product. If not defined, and the adb
1149 // command requires this information, then the user must
1150 // specify the path using "-p".
1151 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1152 if (ANDROID_PRODUCT_OUT != nullptr) {
1153 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001154 }
1155 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1156
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001157 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001158 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001159 int server_port = DEFAULT_ADB_PORT;
1160 if (server_port_str && strlen(server_port_str) > 0) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001161 server_port = strtol(server_port_str, nullptr, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001162 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001163 fprintf(stderr,
Spencer Lowf18fc082015-08-11 17:05:02 -07001164 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65536. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001165 server_port_str);
1166 return usage();
1167 }
1168 }
1169
Elliott Hughes8d28e192015-10-07 14:55:10 -07001170 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1171 const char* serial = nullptr;
1172
Riley Andrews98f58e82014-12-05 17:37:24 -08001173 while (argc > 0) {
1174 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001175 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001176 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001177 no_daemon = 1;
1178 } else if (!strcmp(argv[0], "fork-server")) {
1179 /* this is a special flag used only when the ADB client launches the ADB Server */
1180 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001181 } else if (!strcmp(argv[0], "--reply-fd")) {
1182 if (argc < 2) return usage();
1183 const char* reply_fd_str = argv[1];
1184 argc--;
1185 argv++;
1186 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001187 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001188 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
1189 return usage();
1190 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001191 } else if (!strncmp(argv[0], "-p", 2)) {
Elliott Hughes048b27c2015-07-31 13:18:22 -07001192 const char* product = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001193 if (argv[0][2] == '\0') {
1194 if (argc < 2) return usage();
1195 product = argv[1];
1196 argc--;
1197 argv++;
1198 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001199 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001200 }
Elliott Hughes048b27c2015-07-31 13:18:22 -07001201 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001202 if (gProductOutPath.empty()) {
1203 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001204 return usage();
1205 }
1206 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1207 if (isdigit(argv[0][2])) {
1208 serial = argv[0] + 2;
1209 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001210 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001211 serial = argv[1];
1212 argc--;
1213 argv++;
1214 }
1215 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001216 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001217 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001218 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001219 } else if (!strcmp(argv[0],"-a")) {
1220 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001221 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001222 const char *hostname = NULL;
1223 if (argv[0][2] == '\0') {
1224 if (argc < 2) return usage();
1225 hostname = argv[1];
1226 argc--;
1227 argv++;
1228 } else {
1229 hostname = argv[0] + 2;
1230 }
1231 adb_set_tcp_name(hostname);
1232
Riley Andrews98f58e82014-12-05 17:37:24 -08001233 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001234 if (argv[0][2] == '\0') {
1235 if (argc < 2) return usage();
1236 server_port_str = argv[1];
1237 argc--;
1238 argv++;
1239 } else {
1240 server_port_str = argv[0] + 2;
1241 }
1242 if (strlen(server_port_str) > 0) {
1243 server_port = (int) strtol(server_port_str, NULL, 0);
1244 if (server_port <= 0 || server_port > 65535) {
1245 fprintf(stderr,
1246 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1247 server_port_str);
1248 return usage();
1249 }
1250 } else {
1251 fprintf(stderr,
1252 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1253 return usage();
1254 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001255 } else {
1256 /* out of recognized modifiers and flags */
1257 break;
1258 }
1259 argc--;
1260 argv++;
1261 }
1262
Elliott Hughes8d28e192015-10-07 14:55:10 -07001263 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1264 if (transport_type == kTransportAny && serial == nullptr) {
1265 serial = getenv("ANDROID_SERIAL");
1266 }
1267
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001268 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001269 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001270
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001271 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001272 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001273 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001274 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
1275 return usage();
1276 }
1277 r = adb_main(is_daemon, server_port, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001278 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001279 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001280 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001281 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001282 fprintf(stderr,"* could not start server *\n");
1283 }
1284 return r;
1285 }
1286
Riley Andrews98f58e82014-12-05 17:37:24 -08001287 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001288 return usage();
1289 }
1290
Riley Andrewsc8514c82014-12-05 17:32:46 -08001291 /* handle wait-for-* prefix */
1292 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001293 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001294
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001295 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001296 return 1;
1297 }
1298
Elliott Hughes2b101112015-05-04 19:29:32 -07001299 // Allow a command to be run after wait-for-device,
1300 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001301 if (argc == 1) {
1302 return 0;
1303 }
1304
1305 /* Fall through */
1306 argc--;
1307 argv++;
1308 }
1309
1310 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001311 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001312 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001313 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001314 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001315 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001316 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001317 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001318 fprintf(stderr, "Usage: adb devices [-l]\n");
1319 return 1;
1320 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001321
1322 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1323 printf("List of devices attached\n");
1324 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001325 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001326 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001327 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001328 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001329 return 1;
1330 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001331
1332 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1333 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001334 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001335 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001336 if (argc > 2) {
1337 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1338 return 1;
1339 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001340
1341 std::string query = android::base::StringPrintf("host:disconnect:%s",
1342 (argc == 2) ? argv[1] : "");
1343 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001344 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001345 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001346 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001347 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001348 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001349 char h = (argv[0][0] == 'h');
1350
David Pursell4e2fd362015-09-22 10:43:08 -07001351 FeatureSet features = GetFeatureSet(transport_type, serial);
1352
David Pursell70ef7b42015-09-30 13:35:42 -07001353 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2);
David Pursell4e2fd362015-09-22 10:43:08 -07001354 if (!use_shell_protocol) {
1355 D("shell protocol not supported, using raw data transfer");
1356 } else {
1357 D("using shell protocol");
1358 }
1359
1360 // Parse shell-specific command-line options.
1361 // argv[0] is always "shell".
1362 --argc;
1363 ++argv;
David Pursell08a27092015-10-20 14:19:36 -07001364 int t_arg_count = 0;
David Pursell4e2fd362015-09-22 10:43:08 -07001365 while (argc) {
1366 if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
David Pursell70ef7b42015-09-30 13:35:42 -07001367 if (!CanUseFeature(features, kFeatureShell2)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001368 fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
1369 return 1;
1370 }
David Pursell08a27092015-10-20 14:19:36 -07001371 // Like ssh, -t arguments are cumulative so that multiple -t's
1372 // are needed to force a PTY.
1373 if (argv[0][1] == 't') {
1374 ++t_arg_count;
1375 } else {
1376 t_arg_count = -1;
1377 }
David Pursell70ef7b42015-09-30 13:35:42 -07001378 --argc;
1379 ++argv;
1380 } else if (!strcmp(argv[0], "-x")) {
1381 use_shell_protocol = false;
David Pursell4e2fd362015-09-22 10:43:08 -07001382 --argc;
1383 ++argv;
1384 } else {
1385 break;
1386 }
1387 }
David Pursell4e2fd362015-09-22 10:43:08 -07001388
David Pursell08a27092015-10-20 14:19:36 -07001389 std::string shell_type_arg;
1390 if (CanUseFeature(features, kFeatureShell2)) {
1391 if (t_arg_count < 0) {
1392 shell_type_arg = kShellServiceArgRaw;
1393 } else if (t_arg_count == 0) {
1394 // If stdin isn't a TTY, default to a raw shell; this lets
1395 // things like `adb shell < my_script.sh` work as expected.
1396 // Otherwise leave |shell_type_arg| blank which uses PTY for
1397 // interactive shells and raw for non-interactive.
David Pursellc5b8ad82015-10-28 14:29:51 -07001398 if (!unix_isatty(STDIN_FILENO)) {
David Pursell08a27092015-10-20 14:19:36 -07001399 shell_type_arg = kShellServiceArgRaw;
1400 }
1401 } else if (t_arg_count == 1) {
1402 // A single -t arg isn't enough to override implicit -T.
David Pursellc5b8ad82015-10-28 14:29:51 -07001403 if (!unix_isatty(STDIN_FILENO)) {
David Pursell08a27092015-10-20 14:19:36 -07001404 fprintf(stderr,
1405 "Remote PTY will not be allocated because stdin is not a terminal.\n"
1406 "Use multiple -t options to force remote PTY allocation.\n");
1407 shell_type_arg = kShellServiceArgRaw;
1408 } else {
1409 shell_type_arg = kShellServiceArgPty;
1410 }
1411 } else {
1412 shell_type_arg = kShellServiceArgPty;
1413 }
1414 }
1415
David Pursell1ed57f02015-10-06 15:30:03 -07001416 std::string command;
1417 if (argc) {
1418 // We don't escape here, just like ssh(1). http://b/20564385.
1419 command = android::base::Join(
1420 std::vector<const char*>(argv, argv + argc), ' ');
1421 }
1422
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001423 if (h) {
1424 printf("\x1b[41;33m");
1425 fflush(stdout);
1426 }
1427
David Pursell1ed57f02015-10-06 15:30:03 -07001428 r = RemoteShell(use_shell_protocol, shell_type_arg, command);
1429
1430 if (h) {
1431 printf("\x1b[0m");
1432 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001433 }
1434
David Pursell1ed57f02015-10-06 15:30:03 -07001435 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001436 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001437 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001438 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001439
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001440 std::string cmd = "exec:";
1441 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001442 argc -= 2;
1443 argv += 2;
1444 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001445 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001446 }
1447
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001448 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001449 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001450 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001451 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001452 return -1;
1453 }
1454
1455 if (exec_in) {
1456 copy_to_file(STDIN_FILENO, fd);
1457 } else {
1458 copy_to_file(fd, STDOUT_FILENO);
1459 }
1460
1461 adb_close(fd);
1462 return 0;
1463 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001464 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001465 std::string error;
1466 int fd = _adb_connect("host:kill", &error);
Spencer Lowf18fc082015-08-11 17:05:02 -07001467 if (fd == -2) {
1468 // Failed to make network connection to server. Don't output the
1469 // network error since that is expected.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001470 fprintf(stderr,"* server not running *\n");
Spencer Lowf18fc082015-08-11 17:05:02 -07001471 // Successful exit code because the server is already "killed".
1472 return 0;
1473 } else if (fd == -1) {
1474 // Some other error.
1475 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001476 return 1;
Spencer Lowf18fc082015-08-11 17:05:02 -07001477 } else {
1478 // Successfully connected, kill command sent, okay status came back.
1479 // Server should exit() in a moment, if not already.
Spencer Low351ecd12015-10-14 17:32:44 -07001480 ReadOrderlyShutdown(fd);
Spencer Lowf18fc082015-08-11 17:05:02 -07001481 adb_close(fd);
1482 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001483 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001484 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001485 else if (!strcmp(argv[0], "sideload")) {
1486 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001487 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001488 return 1;
1489 } else {
1490 return 0;
1491 }
1492 }
Elliott Hughes19d80b82015-07-21 16:13:40 -07001493 else if (!strcmp(argv[0], "tcpip") && argc > 1) {
1494 return adb_connect_command(android::base::StringPrintf("tcpip:%s", argv[1]));
1495 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001496 else if (!strcmp(argv[0], "remount") ||
1497 !strcmp(argv[0], "reboot") ||
1498 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001499 !strcmp(argv[0], "usb") ||
1500 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001501 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001502 !strcmp(argv[0], "disable-verity") ||
1503 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001504 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001505 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001506 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001507 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001508 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001509 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001510 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001511 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001512 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001513 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001514 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001515 if (argc != 1) return usage();
David Pursell70ef7b42015-09-30 13:35:42 -07001516 // No need for shell protocol with bugreport, always disable for
1517 // simplicity.
1518 return send_shell_command(transport_type, serial, "bugreport", true);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001519 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001520 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001521 bool reverse = !strcmp(argv[0], "reverse");
1522 ++argv;
1523 --argc;
1524 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001525
1526 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001527 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001528 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001529 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001530 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001531 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001532 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001533 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001534 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001535 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001536 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001537 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001538 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001539 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001540 }
1541
Elliott Hughes424af022015-05-29 17:55:19 -07001542 std::string cmd;
1543 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001544 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001545 return adb_query_command(host_prefix + ":list-forward");
1546 } else if (strcmp(argv[0], "--remove-all") == 0) {
1547 if (argc != 1) return usage();
1548 cmd = host_prefix + ":killforward-all";
1549 } else if (strcmp(argv[0], "--remove") == 0) {
1550 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001551 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001552 cmd = host_prefix + ":killforward:" + argv[1];
1553 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1554 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001555 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001556 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1557 } else {
1558 // forward <local> <remote>
1559 if (argc != 2) return usage();
1560 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001561 }
1562
Elliott Hughes424af022015-05-29 17:55:19 -07001563 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001564 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001565 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001566 else if (!strcmp(argv[0], "ls")) {
1567 if (argc != 2) return usage();
Elliott Hughesaa245492015-08-03 10:38:08 -07001568 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001569 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001570 else if (!strcmp(argv[0], "push")) {
Josh Gao05786772015-10-30 16:57:19 -07001571 bool copy_attrs = false;
1572 std::vector<const char*> srcs;
1573 const char* dst = nullptr;
Mark Lindner76f2a932014-03-11 17:55:59 -07001574
Josh Gao05786772015-10-30 16:57:19 -07001575 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1576 if (srcs.empty() || !dst) return usage();
1577 return do_sync_push(srcs, dst) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001578 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001579 else if (!strcmp(argv[0], "pull")) {
Josh Gao05786772015-10-30 16:57:19 -07001580 bool copy_attrs = false;
1581 std::vector<const char*> srcs;
1582 const char* dst = ".";
Mark Lindner76f2a932014-03-11 17:55:59 -07001583
Josh Gao05786772015-10-30 16:57:19 -07001584 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1585 if (srcs.empty()) return usage();
1586 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001587 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001588 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001589 if (argc < 2) return usage();
Todd Kennedyd0398002015-11-03 16:53:08 -08001590 FeatureSet features = GetFeatureSet(transport_type, serial);
1591 if (CanUseFeature(features, kFeatureCmd)) {
1592 return install_app(transport_type, serial, argc, argv);
1593 }
1594 return install_app_legacy(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001595 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001596 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001597 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001598 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001599 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001600 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001601 if (argc < 2) return usage();
Todd Kennedyd0398002015-11-03 16:53:08 -08001602 FeatureSet features = GetFeatureSet(transport_type, serial);
1603 if (CanUseFeature(features, kFeatureCmd)) {
1604 return uninstall_app(transport_type, serial, argc, argv);
1605 }
1606 return uninstall_app_legacy(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001607 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001608 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001609 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001610 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001611 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001612 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001613 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001614 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001615 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001616 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001617 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001618 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001619 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001620 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001621 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001622 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001623 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624 } else {
1625 return usage();
1626 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001627
Elliott Hughesd236d072015-04-21 10:17:07 -07001628 if (src != "" &&
1629 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001630 return usage();
1631 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001632
Elliott Hughes58305772015-04-17 13:57:15 -07001633 std::string system_src_path = product_file("system");
1634 std::string data_src_path = product_file("data");
1635 std::string vendor_src_path = product_file("vendor");
1636 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001637
Elliott Hughesaa245492015-08-03 10:38:08 -07001638 bool okay = true;
1639 if (okay && (src.empty() || src == "system")) {
1640 okay = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001641 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001642 if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1643 okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001644 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001645 if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1646 okay = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001647 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001648 if (okay && (src.empty() || src == "data")) {
1649 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001650 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001651 return okay ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001652 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001653 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001654 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001655 !strcmp(argv[0],"get-serialno") ||
1656 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001657 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001658 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001659 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001660 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001661 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001662 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001663 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001664 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001665 return ppp(argc, argv);
1666 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001667 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001668 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001669 const int result = adb_connect("host:start-server", &error);
1670 if (result < 0) {
1671 fprintf(stderr, "error: %s\n", error.c_str());
1672 }
1673 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001674 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001675 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001676 return backup(argc, argv);
1677 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001678 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001679 return restore(argc, argv);
1680 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001681 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001682 if (argc < 2) return usage();
Yabin Cuiaed3c612015-09-22 15:52:57 -07001683 // Always print key generation information for keygen command.
1684 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001685 return adb_auth_keygen(argv[1]);
1686 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001687 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001688 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001689 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001691 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001692 help();
1693 return 0;
1694 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001696 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001697 return 0;
1698 }
Dan Albert90d4b732015-05-20 18:58:41 -07001699 else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001700 // Only list the features common to both the adb client and the device.
1701 FeatureSet features = GetFeatureSet(transport_type, serial);
1702 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001703 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001704 printf("%s\n", name.c_str());
1705 }
1706 }
1707 return 0;
Dan Albert90d4b732015-05-20 18:58:41 -07001708 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001709
1710 usage();
1711 return 1;
1712}
1713
Todd Kennedyd0398002015-11-03 16:53:08 -08001714static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
1715 // 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
1716 std::string cmd = "cmd package";
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001717 while (argc-- > 0) {
Todd Kennedyd0398002015-11-03 16:53:08 -08001718 // deny the '-k' option until the remaining data/cache can be removed with adb/UI
1719 if (strcmp(*argv, "-k") == 0) {
1720 printf(
1721 "The -k option uninstalls the application while retaining the data/cache.\n"
1722 "At the moment, there is no way to remove the remaining data.\n"
1723 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1724 "If you truly wish to continue, execute 'adb shell cmd package uninstall -k'.\n");
1725 return EXIT_FAILURE;
1726 }
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001727 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001728 }
1729
David Pursell70ef7b42015-09-30 13:35:42 -07001730 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001731}
1732
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001733static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Todd Kennedyd0398002015-11-03 16:53:08 -08001734 // The last argument must be the APK file
1735 const char* file = argv[argc - 1];
1736 const char* dot = strrchr(file, '.');
1737 bool found_apk = false;
Jeff Sharkey960df972014-06-09 17:30:57 -07001738 struct stat sb;
Todd Kennedyd0398002015-11-03 16:53:08 -08001739 if (dot && !strcasecmp(dot, ".apk")) {
1740 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1741 fprintf(stderr, "Invalid APK file: %s\n", file);
1742 return EXIT_FAILURE;
Kenny Root597ea5b2011-08-05 11:19:45 -07001743 }
Todd Kennedyd0398002015-11-03 16:53:08 -08001744 found_apk = true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001745 }
1746
Todd Kennedyd0398002015-11-03 16:53:08 -08001747 if (!found_apk) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001748 fprintf(stderr, "Missing APK file\n");
Todd Kennedyd0398002015-11-03 16:53:08 -08001749 return EXIT_FAILURE;
Kenny Root597ea5b2011-08-05 11:19:45 -07001750 }
1751
Todd Kennedyd0398002015-11-03 16:53:08 -08001752 int localFd = adb_open(file, O_RDONLY);
1753 if (localFd < 0) {
1754 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
1755 return 1;
1756 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001757
Todd Kennedyd0398002015-11-03 16:53:08 -08001758 std::string error;
1759 std::string cmd = "exec:cmd package";
1760
1761 // don't copy the APK name, but, copy the rest of the arguments as-is
1762 while (argc-- > 1) {
1763 cmd += " " + escape_arg(std::string(*argv++));
1764 }
1765
1766 // add size parameter [required for streaming installs]
1767 // do last to override any user specified value
1768 cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
1769
1770 int remoteFd = adb_connect(cmd, &error);
1771 if (remoteFd < 0) {
1772 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
1773 adb_close(localFd);
1774 return 1;
1775 }
1776
1777 char buf[BUFSIZ];
1778 copy_to_file(localFd, remoteFd);
1779 read_status_line(remoteFd, buf, sizeof(buf));
1780
1781 adb_close(localFd);
1782 adb_close(remoteFd);
1783
1784 if (strncmp("Success", buf, 7)) {
1785 fprintf(stderr, "Failed to write %s\n", file);
1786 fputs(buf, stderr);
1787 return 1;
1788 }
1789 fputs(buf, stderr);
1790 return 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001791}
1792
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001793static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001794 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001795{
Jeff Sharkey960df972014-06-09 17:30:57 -07001796 int i;
1797 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001798 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001799
1800 // Find all APK arguments starting at end.
1801 // All other arguments passed through verbatim.
1802 int first_apk = -1;
1803 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001804 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001805 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001806 if (dot && !strcasecmp(dot, ".apk")) {
1807 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1808 fprintf(stderr, "Invalid APK file: %s\n", file);
Todd Kennedyd0398002015-11-03 16:53:08 -08001809 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001810 }
1811
1812 total_size += sb.st_size;
1813 first_apk = i;
1814 } else {
1815 break;
1816 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001817 }
1818
Jeff Sharkey960df972014-06-09 17:30:57 -07001819 if (first_apk == -1) {
1820 fprintf(stderr, "Missing APK file\n");
1821 return 1;
1822 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001823
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001824 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001825 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001826 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001827 }
1828
1829 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001830 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001831 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001832 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001833 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Todd Kennedyd0398002015-11-03 16:53:08 -08001834 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001835 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001836 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001837 read_status_line(fd, buf, sizeof(buf));
1838 adb_close(fd);
1839
1840 int session_id = -1;
1841 if (!strncmp("Success", buf, 7)) {
1842 char* start = strrchr(buf, '[');
1843 char* end = strrchr(buf, ']');
1844 if (start && end) {
1845 *end = '\0';
1846 session_id = strtol(start + 1, NULL, 10);
1847 }
1848 }
1849 if (session_id < 0) {
1850 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001851 fputs(buf, stderr);
Todd Kennedyd0398002015-11-03 16:53:08 -08001852 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001853 }
1854
1855 // Valid session, now stream the APKs
1856 int success = 1;
1857 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001858 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001859 if (stat(file, &sb) == -1) {
1860 fprintf(stderr, "Failed to stat %s\n", file);
1861 success = 0;
1862 goto finalize_session;
1863 }
1864
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001865 std::string cmd = android::base::StringPrintf(
1866 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
Elliott Hughes5c742702015-07-30 17:42:01 -07001867 static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001868
1869 int localFd = adb_open(file, O_RDONLY);
1870 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001871 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001872 success = 0;
1873 goto finalize_session;
1874 }
1875
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001876 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001877 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001878 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001879 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001880 adb_close(localFd);
1881 success = 0;
1882 goto finalize_session;
1883 }
1884
1885 copy_to_file(localFd, remoteFd);
1886 read_status_line(remoteFd, buf, sizeof(buf));
1887
1888 adb_close(localFd);
1889 adb_close(remoteFd);
1890
1891 if (strncmp("Success", buf, 7)) {
1892 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001893 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001894 success = 0;
1895 goto finalize_session;
1896 }
1897 }
1898
1899finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001900 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001901 std::string service =
1902 android::base::StringPrintf("exec:pm install-%s %d",
1903 success ? "commit" : "abandon", session_id);
1904 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001905 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001906 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Todd Kennedyd0398002015-11-03 16:53:08 -08001907 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001908 }
1909 read_status_line(fd, buf, sizeof(buf));
1910 adb_close(fd);
1911
1912 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001913 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001914 return 0;
1915 } else {
1916 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001917 fputs(buf, stderr);
Todd Kennedyd0398002015-11-03 16:53:08 -08001918 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001919 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001920}
Todd Kennedyd0398002015-11-03 16:53:08 -08001921
1922static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
1923 std::string cmd = "pm";
1924
1925 while (argc-- > 0) {
1926 cmd += " " + escape_arg(*argv++);
1927 }
1928
1929 return send_shell_command(transport, serial, cmd, false);
1930}
1931
1932static int uninstall_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
1933 /* if the user choose the -k option, we refuse to do it until devices are
1934 out with the option to uninstall the remaining data somehow (adb/ui) */
1935 int i;
1936 for (i = 1; i < argc; i++) {
1937 if (!strcmp(argv[i], "-k")) {
1938 printf(
1939 "The -k option uninstalls the application while retaining the data/cache.\n"
1940 "At the moment, there is no way to remove the remaining data.\n"
1941 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1942 "If you truly wish to continue, execute 'adb shell pm uninstall -k'\n.");
1943 return EXIT_FAILURE;
1944 }
1945 }
1946
1947 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1948 return pm_command(transport, serial, argc, argv);
1949}
1950
1951static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
1952 std::string cmd = "rm -f " + escape_arg(filename);
1953 return send_shell_command(transport, serial, cmd, false);
1954}
1955
1956static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
1957 static const char *const DATA_DEST = "/data/local/tmp/%s";
1958 static const char *const SD_DEST = "/sdcard/tmp/%s";
1959 const char* where = DATA_DEST;
1960 int i;
1961 struct stat sb;
1962
1963 for (i = 1; i < argc; i++) {
1964 if (!strcmp(argv[i], "-s")) {
1965 where = SD_DEST;
1966 }
1967 }
1968
1969 // Find last APK argument.
1970 // All other arguments passed through verbatim.
1971 int last_apk = -1;
1972 for (i = argc - 1; i >= 0; i--) {
1973 const char* file = argv[i];
1974 const char* dot = strrchr(file, '.');
1975 if (dot && !strcasecmp(dot, ".apk")) {
1976 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1977 fprintf(stderr, "Invalid APK file: %s\n", file);
1978 return EXIT_FAILURE;
1979 }
1980
1981 last_apk = i;
1982 break;
1983 }
1984 }
1985
1986 if (last_apk == -1) {
1987 fprintf(stderr, "Missing APK file\n");
1988 return EXIT_FAILURE;
1989 }
1990
1991 int result = -1;
1992 std::vector<const char*> apk_file = {argv[last_apk]};
1993 std::string apk_dest = android::base::StringPrintf(
1994 where, adb_basename(argv[last_apk]).c_str());
1995 if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
1996 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
1997 result = pm_command(transport, serial, argc, argv);
1998
1999cleanup_apk:
2000 delete_file(transport, serial, apk_dest);
2001 return result;
2002}