blob: 7fbca3155915071005a8504d36fb048fec7688c3 [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
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
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
Elliott Hughes2baae3a2015-04-17 10:59:34 -070034#include <string>
35
36#include <base/stringprintf.h>
37
Yabin Cuid325e862014-11-17 14:48:25 -080038#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080040#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#endif
42
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080044#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080045#include "adb_client.h"
46#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070047#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048#include "file_sync_service.h"
49
Elliott Hughes3bd73c12015-05-05 13:10:43 -070050static int install_app(TransportType t, const char* serial, int argc, const char** argv);
51static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
52static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080053
Elliott Hughes58305772015-04-17 13:57:15 -070054static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080055extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056
Elliott Hughes58305772015-04-17 13:57:15 -070057static std::string product_file(const char *extra) {
58 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080059 fprintf(stderr, "adb: Product directory not specified; "
60 "use -p or define ANDROID_PRODUCT_OUT\n");
61 exit(1);
62 }
63
Elliott Hughes58305772015-04-17 13:57:15 -070064 return android::base::StringPrintf("%s%s%s",
65 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066}
67
Elliott Hughes58305772015-04-17 13:57:15 -070068static void version(FILE* out) {
Elliott Hughesf3bbfa62015-05-07 21:56:31 -070069 fprintf(out, "Android Debug Bridge version %d.%d.%d\nRevision %s\n",
70 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_REVISION);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
72
Elliott Hughes58305772015-04-17 13:57:15 -070073static void help() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 version(stderr);
75
76 fprintf(stderr,
77 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080078 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 " -d - directs command to the only connected USB device\n"
80 " returns an error if more than one USB device is present.\n"
81 " -e - directs command to the only running emulator.\n"
82 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070083 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070084 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070085 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080086 " -p <product name or path> - simple product name like 'sooner', or\n"
87 " a relative/absolute path to a product\n"
88 " out directory like 'out/target/product/sooner'.\n"
89 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
90 " environment variable is used, which must\n"
91 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080092 " -H - Name of adb server host (default: localhost)\n"
93 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070094 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070095 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040096 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
97 " Port 5555 is used by default if no port number is specified.\n"
98 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
99 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200100 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400101 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 "\n"
103 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700104 " adb push [-p] <local> <remote>\n"
105 " - copy file/dir to device\n"
106 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700107 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700108 " - copy file/dir from device\n"
109 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700110 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600112 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 " (see 'adb help all')\n"
114 " adb shell - run remote shell interactively\n"
115 " adb shell <command> - run remote shell command\n"
116 " adb emu <command> - run emulator console command\n"
117 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100118 " adb forward --list - list all forward socket connections.\n"
119 " the format is a list of lines with the following format:\n"
120 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 " adb forward <local> <remote> - forward socket connections\n"
122 " forward specs are one of: \n"
123 " tcp:<port>\n"
124 " localabstract:<unix domain socket name>\n"
125 " localreserved:<unix domain socket name>\n"
126 " localfilesystem:<unix domain socket name>\n"
127 " dev:<character device name>\n"
128 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100129 " adb forward --no-rebind <local> <remote>\n"
130 " - same as 'adb forward <local> <remote>' but fails\n"
131 " if <local> is already forwarded\n"
132 " adb forward --remove <local> - remove a specific forward socket connection\n"
133 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100134 " adb reverse --list - list all reverse socket connections from device\n"
135 " adb reverse <remote> <local> - reverse socket connections\n"
136 " reverse specs are one of:\n"
137 " tcp:<port>\n"
138 " localabstract:<unix domain socket name>\n"
139 " localreserved:<unix domain socket name>\n"
140 " localfilesystem:<unix domain socket name>\n"
141 " adb reverse --norebind <remote> <local>\n"
142 " - same as 'adb reverse <remote> <local>' but fails\n"
143 " if <remote> is already reversed.\n"
144 " adb reverse --remove <remote>\n"
145 " - remove a specific reversed socket connection\n"
146 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800147 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700148 " adb install [-lrtsd] <file>\n"
149 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700150 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700151 " (-l: forward lock application)\n"
152 " (-r: replace existing application)\n"
153 " (-t: allow test packages)\n"
154 " (-s: install application on sdcard)\n"
155 " (-d: allow version code downgrade)\n"
156 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157 " adb uninstall [-k] <package> - remove this app package from the device\n"
158 " ('-k' means keep the data and cache directories)\n"
159 " adb bugreport - return all information from the device\n"
160 " that should be included in a bug report.\n"
161 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800162 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700163 " - write an archive of the device's data to <file>.\n"
164 " If no -f option is supplied then the data is written\n"
165 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700166 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700167 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800168 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
169 " (aka .obb) files associated with each application; the default\n"
170 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700171 " (-shared|-noshared enable/disable backup of the device's\n"
172 " shared storage / SD card contents; the default is noshared.)\n"
173 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700174 " (-system|-nosystem toggles whether -all automatically includes\n"
175 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (<packages...> is the list of applications to be backed up. If\n"
177 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700178 " list is optional. Applications explicitly given on the\n"
179 " command line will be included even if -nosystem would\n"
180 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700182 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700183 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800184 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
185 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800186 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
187 " and the public key is stored in <file>.pub. Any existing files\n"
188 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189 " adb help - show this help message\n"
190 " adb version - show version num\n"
191 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800192 "scripting:\n"
193 " adb wait-for-device - block until device is online\n"
194 " adb start-server - ensure that there is a server running\n"
195 " adb kill-server - kill the server if it is running\n"
196 " adb get-state - prints: offline | bootloader | device\n"
197 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700198 " adb get-devpath - prints: <device-path>\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000199 " 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 -0700200 " adb reboot [bootloader|recovery]\n"
201 " - reboots the device, optionally into the bootloader or recovery program.\n"
202 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
203 " adb reboot sideload-auto-reboot\n"
204 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800205 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700206 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500207 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800208 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000209 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210 "networking:\n"
211 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500212 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800213 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
214 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
215 "\n"
216 "adb sync notes: adb sync [ <directory> ]\n"
217 " <localdir> can be interpreted in several ways:\n"
218 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000219 " - 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 -0800220 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000221 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800222 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000223 "\n"
224 "environmental variables:\n"
225 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
226 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
227 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
228 " 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 -0800229 );
230}
231
Elliott Hughes58305772015-04-17 13:57:15 -0700232static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233 help();
234 return 1;
235}
236
Yabin Cuid325e862014-11-17 14:48:25 -0800237#if defined(_WIN32)
238
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700239// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800240void stdin_raw_init(int fd);
241void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800242
243#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100244static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100246static void stdin_raw_init(int fd) {
247 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100249 termios tio;
250 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100252 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100254 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255 tio.c_cc[VTIME] = 0;
256 tio.c_cc[VMIN] = 1;
257
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100258 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259}
260
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100261static void stdin_raw_restore(int fd) {
262 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263}
264#endif
265
Elliott Hughes5677c232015-05-07 23:37:40 -0700266static void read_and_dump(int fd) {
267 while (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700268 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
Elliott Hughes5677c232015-05-07 23:37:40 -0700269 char buf[BUFSIZ];
270 int len = adb_read(fd, buf, sizeof(buf));
JP Abgrall408fa572011-03-16 15:57:42 -0700271 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
Elliott Hughes5677c232015-05-07 23:37:40 -0700272 if (len <= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273 break;
274 }
275
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400276 fwrite(buf, 1, len, stdout);
277 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278 }
279}
280
Jeff Sharkey960df972014-06-09 17:30:57 -0700281static void read_status_line(int fd, char* buf, size_t count)
282{
283 count--;
284 while (count > 0) {
285 int len = adb_read(fd, buf, count);
286 if (len == 0) {
287 break;
288 } else if (len < 0) {
289 if (errno == EINTR) continue;
290 break;
291 }
292
293 buf += len;
294 count -= len;
295 }
296 *buf = '\0';
297}
298
Christopher Tated2f54152011-04-21 12:53:28 -0700299static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700300 const size_t BUFSIZE = 32 * 1024;
301 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700302 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700303 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700304 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700305
306 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800307
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700308 if (inFd == STDIN_FILENO) {
309 stdin_raw_init(STDIN_FILENO);
310 }
Yabin Cuid325e862014-11-17 14:48:25 -0800311
Elliott Hughesa7090b92015-04-17 17:03:59 -0700312 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700313 if (inFd == STDIN_FILENO) {
314 len = unix_read(inFd, buf, BUFSIZE);
315 } else {
316 len = adb_read(inFd, buf, BUFSIZE);
317 }
Christopher Tated2f54152011-04-21 12:53:28 -0700318 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700319 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700320 break;
321 }
322 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700323 if (errno == EINTR) {
324 D("copy_to_file() : EINTR, retrying\n");
325 continue;
326 }
Christopher Tated2f54152011-04-21 12:53:28 -0700327 D("copy_to_file() : error %d\n", errno);
328 break;
329 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700330 if (outFd == STDOUT_FILENO) {
331 fwrite(buf, 1, len, stdout);
332 fflush(stdout);
333 } else {
334 adb_write(outFd, buf, len);
335 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700336 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700337 }
Yabin Cuid325e862014-11-17 14:48:25 -0800338
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700339 if (inFd == STDIN_FILENO) {
340 stdin_raw_restore(STDIN_FILENO);
341 }
Yabin Cuid325e862014-11-17 14:48:25 -0800342
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700343 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700344 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700345}
346
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800347static void *stdin_read_thread(void *x)
348{
349 int fd, fdi;
350 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800351 int r, n;
352 int state = 0;
353
354 int *fds = (int*) x;
355 fd = fds[0];
356 fdi = fds[1];
357 free(fds);
358
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359 for(;;) {
360 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700361 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800362 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700363 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800364 if(r == 0) break;
365 if(r < 0) {
366 if(errno == EINTR) continue;
367 break;
368 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400369 for(n = 0; n < r; n++){
370 switch(buf[n]) {
371 case '\n':
372 state = 1;
373 break;
374 case '\r':
375 state = 1;
376 break;
377 case '~':
378 if(state == 1) state++;
379 break;
380 case '.':
381 if(state == 2) {
382 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400383 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400384 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400386 default:
387 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800388 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800389 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800390 r = adb_write(fd, buf, r);
391 if(r <= 0) {
392 break;
393 }
394 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800395 return 0;
396}
397
Elliott Hughes58305772015-04-17 13:57:15 -0700398static int interactive_shell() {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700399 int fdi;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700401 std::string error;
402 int fd = adb_connect("shell:", &error);
403 if (fd < 0) {
404 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800405 return 1;
406 }
407 fdi = 0; //dup(0);
408
Dan Albertbac34742015-02-25 17:51:28 -0800409 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700410 if (fds == nullptr) {
411 fprintf(stderr, "couldn't allocate fds array: %s\n", strerror(errno));
412 return 1;
413 }
414
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800415 fds[0] = fd;
416 fds[1] = fdi;
417
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800418 stdin_raw_init(fdi);
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700419
420 adb_thread_create(stdin_read_thread, fds);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800421 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800422 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423 return 0;
424}
425
426
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700427static std::string format_host_command(const char* command, TransportType type, const char* serial) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 if (serial) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700429 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700431
432 const char* prefix = "host";
433 if (type == kTransportUsb) {
434 prefix = "host-usb";
435 } else if (type == kTransportLocal) {
436 prefix = "host-local";
437 }
438 return android::base::StringPrintf("%s:%s", prefix, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439}
440
Elliott Hughes6452a892015-04-29 12:28:13 -0700441static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700442 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800443{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700444 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700445 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700446 if (fd < 0) {
447 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800448 return -1;
449 }
450
451 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800452 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800453
Elliott Hughes6452a892015-04-29 12:28:13 -0700454 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800455 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800456
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700457 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800458 char *x = strrchr(service, ':');
459 if(x) service = x + 1;
460 }
461
Elliott Hughes6452a892015-04-29 12:28:13 -0700462 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800463 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700464 if (!WriteFdExactly(fd, ptr, xfer)) {
465 std::string error;
466 adb_status(fd, &error);
467 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800468 return -1;
469 }
470 sz -= xfer;
471 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700472 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100473 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800474 fflush(stdout);
475 }
476 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700477 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800478 printf("\n");
479 }
480
Elliott Hughese67f1f82015-04-30 17:32:03 -0700481 if (!adb_status(fd, &error)) {
482 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800483 return -1;
484 }
485
486 adb_close(fd);
487 return 0;
488}
489
Doug Zongker71fe5842014-06-26 15:35:36 -0700490#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
491
492/*
493 * The sideload-host protocol serves the data in a file (given on the
494 * command line) to the client, using a simple protocol:
495 *
496 * - The connect message includes the total number of bytes in the
497 * file and a block size chosen by us.
498 *
499 * - The other side sends the desired block number as eight decimal
500 * digits (eg "00000023" for block 23). Blocks are numbered from
501 * zero.
502 *
503 * - We send back the data of the requested block. The last block is
504 * likely to be partial; when the last block is requested we only
505 * send the part of the block that exists, it's not padded up to the
506 * block size.
507 *
508 * - When the other side sends "DONEDONE" instead of a block number,
509 * we hang up.
510 */
Elliott Hughes58305772015-04-17 13:57:15 -0700511static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700512 unsigned sz;
513 size_t xfer = 0;
514 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800515 int last_percent = -1;
516 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700517
518 printf("loading: '%s'", fn);
519 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800520 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700521 if (data == 0) {
522 printf("\n");
523 fprintf(stderr, "* cannot read '%s' *\n", fn);
524 return -1;
525 }
526
Elliott Hughes6452a892015-04-29 12:28:13 -0700527 std::string service =
528 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700529 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700530 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700531 if (fd < 0) {
532 // Try falling back to the older sideload method. Maybe this
533 // is an older device that doesn't support sideload-host.
534 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700535 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700536 goto done;
537 }
538
Spencer Lowf055c192015-01-25 14:40:16 -0800539 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700540
Elliott Hughesa7090b92015-04-17 17:03:59 -0700541 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700542 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800543 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700544 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700545 status = -1;
546 goto done;
547 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700548 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700549
Elliott Hughes6452a892015-04-29 12:28:13 -0700550 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700551 status = 0;
552 break;
553 }
554
Doug Zongker71fe5842014-06-26 15:35:36 -0700555 int block = strtol(buf, NULL, 10);
556
557 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
558 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700559 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700560 status = -1;
561 goto done;
562 }
563 uint8_t* start = data + offset;
564 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
565 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
566 if (offset_end > sz) {
567 to_write = sz - offset;
568 }
569
Dan Albertcc731cc2015-02-24 21:26:58 -0800570 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700571 adb_status(fd, &error);
572 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700573 status = -1;
574 goto done;
575 }
576 xfer += to_write;
577
578 // For normal OTA packages, we expect to transfer every byte
579 // twice, plus a bit of overhead (one read during
580 // verification, one read of each byte for installation, plus
581 // extra access to things like the zip central directory).
582 // This estimate of the completion becomes 100% when we've
583 // transferred ~2.13 (=100/47) times the package size.
584 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
585 if (percent != last_percent) {
586 printf("\rserving: '%s' (~%d%%) ", fn, percent);
587 fflush(stdout);
588 last_percent = percent;
589 }
590 }
591
Colin Cross6d6a8982014-07-07 14:12:41 -0700592 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700593
594 done:
595 if (fd >= 0) adb_close(fd);
596 free(data);
597 return status;
598}
599
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800600/**
601 * Run ppp in "notty" mode against a resource listed as the first parameter
602 * eg:
603 *
604 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
605 *
606 */
Elliott Hughes58305772015-04-17 13:57:15 -0700607static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800608#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800609 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
610 return -1;
611#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800612 if (argc < 2) {
613 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
614 argv[0]);
615
616 return 1;
617 }
618
Dan Albertbac34742015-02-25 17:51:28 -0800619 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700620 std::string error;
621 int fd = adb_connect(adb_service_name, &error);
622 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800623 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700624 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800625 return 1;
626 }
627
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700628 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800629
630 if (pid < 0) {
631 perror("from fork()");
632 return 1;
633 } else if (pid == 0) {
634 int err;
635 int i;
636 const char **ppp_args;
637
638 // copy args
639 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
640 ppp_args[0] = "pppd";
641 for (i = 2 ; i < argc ; i++) {
642 //argv[2] and beyond become ppp_args[1] and beyond
643 ppp_args[i - 1] = argv[i];
644 }
645 ppp_args[i-1] = NULL;
646
647 // child side
648
649 dup2(fd, STDIN_FILENO);
650 dup2(fd, STDOUT_FILENO);
651 adb_close(STDERR_FILENO);
652 adb_close(fd);
653
654 err = execvp("pppd", (char * const *)ppp_args);
655
656 if (err < 0) {
657 perror("execing pppd");
658 }
659 exit(-1);
660 } else {
661 // parent side
662
663 adb_close(fd);
664 return 0;
665 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800666#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800667}
668
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700669static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700670 // Was the caller vague about what they'd like us to wait for?
671 // If so, check they weren't more specific in their choice of transport type.
672 if (strcmp(service, "wait-for-device") == 0) {
673 if (t == kTransportUsb) {
674 service = "wait-for-usb";
675 } else if (t == kTransportLocal) {
676 service = "wait-for-local";
677 } else {
678 service = "wait-for-any";
679 }
680 }
681
682 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700683 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700684}
685
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700686static int send_shell_command(TransportType transport_type, const char* serial,
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700687 const std::string& command) {
688 int fd;
689 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700690 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700691 fd = adb_connect(command, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700692 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700694 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800695 fprintf(stderr,"- waiting for device -\n");
696 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -0700697 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800698 }
699
700 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700701 int rc = adb_close(fd);
702 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700704 }
705 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706}
707
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700708static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700709 char* log_tags = getenv("ANDROID_LOG_TAGS");
710 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800711
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700712 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700714 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700715 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800716 }
717
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700718 --argc;
719 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700720 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700721 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800722 }
723
Elliott Hughes15551472015-04-21 17:58:55 -0700724 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725}
726
Mark Salyzyn60299df2014-04-30 09:10:31 -0700727static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800728{
729 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700730 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800731
732 for(;;) {
733 x = adb_dirstart(x);
734 if(x == 0) return 0;
735 *x = 0;
736 ret = adb_mkdir(path, 0775);
737 *x = OS_PATH_SEPARATOR;
738 if((ret < 0) && (errno != EEXIST)) {
739 return ret;
740 }
741 x++;
742 }
743 return 0;
744}
745
Dan Albertbac34742015-02-25 17:51:28 -0800746static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700747 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700748
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700749 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700750 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700751 if (!strcmp("-f", argv[i])) {
752 if (i == argc-1) {
753 fprintf(stderr, "adb: -f passed with no filename\n");
754 return usage();
755 }
756 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700757 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700758 argv[i++] = argv[j++];
759 }
760 argc -= 2;
761 argv[argc] = NULL;
762 }
Christopher Tated2f54152011-04-21 12:53:28 -0700763 }
764
Christopher Tatebb86bc52011-08-22 17:12:08 -0700765 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
766 if (argc < 2) return usage();
767
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800768 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700769 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700770 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700771 if (outFd < 0) {
772 fprintf(stderr, "adb: unable to open file %s\n", filename);
773 return -1;
774 }
775
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700776 std::string cmd = "backup:";
777 --argc;
778 ++argv;
779 while (argc-- > 0) {
780 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700781 }
782
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700783 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700784 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700785 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -0700786 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700787 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700788 adb_close(outFd);
789 return -1;
790 }
791
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800792 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700793 copy_to_file(fd, outFd);
794
795 adb_close(fd);
796 adb_close(outFd);
797 return 0;
798}
799
Dan Albertbac34742015-02-25 17:51:28 -0800800static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700801 if (argc != 2) return usage();
802
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700803 const char* filename = argv[1];
804 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -0700805 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700806 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -0700807 return -1;
808 }
809
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700810 std::string error;
811 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -0700812 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700813 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -0700814 adb_close(tarFd);
815 return -1;
816 }
817
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800818 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700819 copy_to_file(tarFd, fd);
820
821 adb_close(fd);
822 adb_close(tarFd);
823 return 0;
824}
825
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800826/* <hint> may be:
827 * - A simple product name
828 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800829 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
830 * e.g., "out/target/product/sooner"
831 * - An absolute path to the PRODUCT_OUT dir
832 * e.g., "/src/device/out/target/product/sooner"
833 *
834 * Given <hint>, try to construct an absolute path to the
835 * ANDROID_PRODUCT_OUT dir.
836 */
Elliott Hughes58305772015-04-17 13:57:15 -0700837static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800838 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700839 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800840 }
841
Elliott Hughes58305772015-04-17 13:57:15 -0700842 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800843 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700844 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800845 }
846
Elliott Hughes58305772015-04-17 13:57:15 -0700847 // If there are any slashes in it, assume it's a relative path;
848 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700849 if (adb_dirstart(hint) != nullptr) {
850 std::string cwd;
851 if (!getcwd(&cwd)) {
852 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700853 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800854 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700855 return android::base::StringPrintf("%s%s%s", cwd.c_str(), OS_PATH_SEPARATOR_STR, hint);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800856 }
857
Elliott Hughes58305772015-04-17 13:57:15 -0700858 // It's a string without any slashes. Try to do something with it.
859 //
860 // Try to find the root of the build tree, and build a PRODUCT_OUT
861 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700862 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700863 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700864 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700865 return "";
866 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700867
868 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700869 path += OS_PATH_SEPARATOR_STR;
870 path += "out";
871 path += OS_PATH_SEPARATOR_STR;
872 path += "target";
873 path += OS_PATH_SEPARATOR_STR;
874 path += "product";
875 path += OS_PATH_SEPARATOR_STR;
876 path += hint;
877 if (!directory_exists(path)) {
878 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
879 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700880 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800881 }
Elliott Hughes58305772015-04-17 13:57:15 -0700882 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800883}
884
Dan Albertbac34742015-02-25 17:51:28 -0800885static void parse_push_pull_args(const char **arg, int narg, char const **path1,
886 char const **path2, int *show_progress,
887 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700888 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700889 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700890
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700891 while (narg > 0) {
892 if (!strcmp(*arg, "-p")) {
893 *show_progress = 1;
894 } else if (!strcmp(*arg, "-a")) {
895 *copy_attrs = 1;
896 } else {
897 break;
898 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700899 ++arg;
900 --narg;
901 }
902
903 if (narg > 0) {
904 *path1 = *arg;
905 ++arg;
906 --narg;
907 }
908
909 if (narg > 0) {
910 *path2 = *arg;
911 }
912}
913
Elliott Hughes6452a892015-04-29 12:28:13 -0700914static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700915 std::string error;
916 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -0700917 if (fd < 0) {
918 fprintf(stderr, "error: %s\n", error.c_str());
919 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -0700920 }
Elliott Hughes5677c232015-05-07 23:37:40 -0700921 read_and_dump(fd);
922 adb_close(fd);
923 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -0700924}
925
Elliott Hughes6452a892015-04-29 12:28:13 -0700926static int adb_query_command(const std::string& command) {
927 std::string result;
928 std::string error;
929 if (!adb_query(command, &result, &error)) {
930 fprintf(stderr, "error: %s\n", error.c_str());
931 return 1;
932 }
933 printf("%s\n", result.c_str());
934 return 0;
935}
936
Elliott Hughesab52c182015-05-01 17:04:38 -0700937int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800938 int no_daemon = 0;
939 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100940 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800941 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700942 TransportType transport_type = kTransportAny;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800943
Elliott Hughes58305772015-04-17 13:57:15 -0700944 // If defined, this should be an absolute path to
945 // the directory containing all of the various system images
946 // for a particular product. If not defined, and the adb
947 // command requires this information, then the user must
948 // specify the path using "-p".
949 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
950 if (ANDROID_PRODUCT_OUT != nullptr) {
951 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800952 }
953 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
954
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700955 const char* serial = getenv("ANDROID_SERIAL");
Nick Pellydb449262009-05-07 12:48:03 -0700956
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100957 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700958 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100959 int server_port = DEFAULT_ADB_PORT;
960 if (server_port_str && strlen(server_port_str) > 0) {
961 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800962 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100963 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800964 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100965 server_port_str);
966 return usage();
967 }
968 }
969
970 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -0800971 while (argc > 0) {
972 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100973 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800974 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800975 no_daemon = 1;
976 } else if (!strcmp(argv[0], "fork-server")) {
977 /* this is a special flag used only when the ADB client launches the ADB Server */
978 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800979 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800980 const char *product = NULL;
981 if (argv[0][2] == '\0') {
982 if (argc < 2) return usage();
983 product = argv[1];
984 argc--;
985 argv++;
986 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -0700987 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800988 }
989 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -0700990 if (gProductOutPath.empty()) {
991 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992 return usage();
993 }
994 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
995 if (isdigit(argv[0][2])) {
996 serial = argv[0] + 2;
997 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -0800998 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800999 serial = argv[1];
1000 argc--;
1001 argv++;
1002 }
1003 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001004 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001005 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001006 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001007 } else if (!strcmp(argv[0],"-a")) {
1008 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001009 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001010 const char *hostname = NULL;
1011 if (argv[0][2] == '\0') {
1012 if (argc < 2) return usage();
1013 hostname = argv[1];
1014 argc--;
1015 argv++;
1016 } else {
1017 hostname = argv[0] + 2;
1018 }
1019 adb_set_tcp_name(hostname);
1020
Riley Andrews98f58e82014-12-05 17:37:24 -08001021 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001022 if (argv[0][2] == '\0') {
1023 if (argc < 2) return usage();
1024 server_port_str = argv[1];
1025 argc--;
1026 argv++;
1027 } else {
1028 server_port_str = argv[0] + 2;
1029 }
1030 if (strlen(server_port_str) > 0) {
1031 server_port = (int) strtol(server_port_str, NULL, 0);
1032 if (server_port <= 0 || server_port > 65535) {
1033 fprintf(stderr,
1034 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1035 server_port_str);
1036 return usage();
1037 }
1038 } else {
1039 fprintf(stderr,
1040 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1041 return usage();
1042 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001043 } else {
1044 /* out of recognized modifiers and flags */
1045 break;
1046 }
1047 argc--;
1048 argv++;
1049 }
1050
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001051 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001052 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001053
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001054 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001055 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001056 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001057 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001058 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001059 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001060 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001061 fprintf(stderr,"* could not start server *\n");
1062 }
1063 return r;
1064 }
1065
Riley Andrews98f58e82014-12-05 17:37:24 -08001066 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001067 return usage();
1068 }
1069
Riley Andrewsc8514c82014-12-05 17:32:46 -08001070 /* handle wait-for-* prefix */
1071 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001072 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001073
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001074 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001075 return 1;
1076 }
1077
Elliott Hughes2b101112015-05-04 19:29:32 -07001078 // Allow a command to be run after wait-for-device,
1079 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001080 if (argc == 1) {
1081 return 0;
1082 }
1083
1084 /* Fall through */
1085 argc--;
1086 argv++;
1087 }
1088
1089 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001090 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001091 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001092 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001093 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001094 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001095 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001096 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001097 fprintf(stderr, "Usage: adb devices [-l]\n");
1098 return 1;
1099 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001100
1101 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1102 printf("List of devices attached\n");
1103 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001105 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001106 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001107 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001108 return 1;
1109 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001110
1111 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1112 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001113 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001114 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001115 if (argc > 2) {
1116 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1117 return 1;
1118 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001119
1120 std::string query = android::base::StringPrintf("host:disconnect:%s",
1121 (argc == 2) ? argv[1] : "");
1122 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001123 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001124 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001125 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001126 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001127 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001128 char h = (argv[0][0] == 'h');
1129
1130 if (h) {
1131 printf("\x1b[41;33m");
1132 fflush(stdout);
1133 }
1134
Riley Andrews98f58e82014-12-05 17:37:24 -08001135 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001136 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001137 r = interactive_shell();
1138 if (h) {
1139 printf("\x1b[0m");
1140 fflush(stdout);
1141 }
1142 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001143 }
1144
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001145 std::string cmd = "shell:";
Elliott Hughes2b101112015-05-04 19:29:32 -07001146 --argc;
1147 ++argv;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001148 while (argc-- > 0) {
Elliott Hughes2b101112015-05-04 19:29:32 -07001149 // We don't escape here, just like ssh(1). http://b/20564385.
1150 cmd += *argv++;
1151 if (*argv) cmd += " ";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001152 }
1153
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001154 while (true) {
1155 D("interactive shell loop. cmd=%s\n", cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001156 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001157 int fd = adb_connect(cmd, &error);
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001158 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001159 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001160 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001161 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001162 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 adb_close(fd);
1164 r = 0;
1165 } else {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001166 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001167 r = -1;
1168 }
1169
Elliott Hughes32687be2015-05-05 12:50:26 -07001170 if (h) {
1171 printf("\x1b[0m");
1172 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001173 }
Elliott Hughes32687be2015-05-05 12:50:26 -07001174 D("interactive shell loop. return r=%d\n", r);
1175 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001176 }
1177 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001178 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001179 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001180
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001181 std::string cmd = "exec:";
1182 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001183 argc -= 2;
1184 argv += 2;
1185 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001186 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001187 }
1188
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001189 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001190 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001191 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001192 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001193 return -1;
1194 }
1195
1196 if (exec_in) {
1197 copy_to_file(STDIN_FILENO, fd);
1198 } else {
1199 copy_to_file(fd, STDOUT_FILENO);
1200 }
1201
1202 adb_close(fd);
1203 return 0;
1204 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001205 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001206 std::string error;
1207 int fd = _adb_connect("host:kill", &error);
Riley Andrews98f58e82014-12-05 17:37:24 -08001208 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001209 fprintf(stderr,"* server not running *\n");
1210 return 1;
1211 }
1212 return 0;
1213 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001214 else if (!strcmp(argv[0], "sideload")) {
1215 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001216 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001217 return 1;
1218 } else {
1219 return 0;
1220 }
1221 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001222 else if (!strcmp(argv[0], "remount") ||
1223 !strcmp(argv[0], "reboot") ||
1224 !strcmp(argv[0], "reboot-bootloader") ||
1225 !strcmp(argv[0], "tcpip") ||
1226 !strcmp(argv[0], "usb") ||
1227 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001228 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001229 !strcmp(argv[0], "disable-verity") ||
1230 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001231 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001232 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001233 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001234 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001235 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001236 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001237 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001238 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001239 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001240 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001241 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001242 if (argc != 1) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001243 return send_shell_command(transport_type, serial, "shell:bugreport");
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001244 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001245 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001246 bool reverse = !strcmp(argv[0], "reverse");
1247 ++argv;
1248 --argc;
1249 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001250
1251 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001252 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001253 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001254 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001255 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001256 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001257 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001258 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001259 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001260 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001261 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001262 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001263 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001264 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001265 }
1266
Elliott Hughes424af022015-05-29 17:55:19 -07001267 std::string cmd;
1268 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001269 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001270 return adb_query_command(host_prefix + ":list-forward");
1271 } else if (strcmp(argv[0], "--remove-all") == 0) {
1272 if (argc != 1) return usage();
1273 cmd = host_prefix + ":killforward-all";
1274 } else if (strcmp(argv[0], "--remove") == 0) {
1275 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001276 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001277 cmd = host_prefix + ":killforward:" + argv[1];
1278 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1279 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001280 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001281 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1282 } else {
1283 // forward <local> <remote>
1284 if (argc != 2) return usage();
1285 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001286 }
1287
Elliott Hughes424af022015-05-29 17:55:19 -07001288 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001289 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001290 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001291 else if (!strcmp(argv[0], "ls")) {
1292 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001293 return do_sync_ls(argv[1]);
1294 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001295 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001296 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001297 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001298 const char* lpath = NULL, *rpath = NULL;
1299
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001300 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001301
1302 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001303 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001304 }
1305
1306 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001307 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001308 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001309 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001310 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001311 const char* rpath = NULL, *lpath = ".";
1312
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001313 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001314
1315 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001316 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001317 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001318
1319 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001321 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001322 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001323 return install_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001324 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001325 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001326 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001327 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001328 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001329 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001331 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001332 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001333 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001334 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001335 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001336 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001337 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001338 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001339 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001340 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001341 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001342 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001343 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001344 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001345 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001346 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001347 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001348 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001349 } else {
1350 return usage();
1351 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001352
Elliott Hughesd236d072015-04-21 10:17:07 -07001353 if (src != "" &&
1354 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001355 return usage();
1356 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001357
Elliott Hughes58305772015-04-17 13:57:15 -07001358 std::string system_src_path = product_file("system");
1359 std::string data_src_path = product_file("data");
1360 std::string vendor_src_path = product_file("vendor");
1361 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001362
1363 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001364 if (rc == 0 && (src.empty() || src == "system")) {
1365 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001366 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001367 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1368 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001369 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001370 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1371 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001372 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001373 if (rc == 0 && (src.empty() || src == "data")) {
1374 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001375 }
1376 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001377 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001378 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001379 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001380 !strcmp(argv[0],"get-serialno") ||
1381 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001382 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001383 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001384 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001386 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001387 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001388 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001389 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 return ppp(argc, argv);
1391 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001392 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001393 std::string error;
1394 return adb_connect("host:start-server", &error);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001395 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001396 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001397 return backup(argc, argv);
1398 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001399 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001400 return restore(argc, argv);
1401 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001402 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001403 if (argc < 2) return usage();
1404 return adb_auth_keygen(argv[1]);
1405 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001406 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001407 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001408 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001409 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001410 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411 help();
1412 return 0;
1413 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001414 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001415 version(stdout);
1416 return 0;
1417 }
1418
1419 usage();
1420 return 1;
1421}
1422
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001423static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001424 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001426 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001427 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001428 }
1429
Elliott Hughes15551472015-04-21 17:58:55 -07001430 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001431}
1432
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001433static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001434 /* if the user choose the -k option, we refuse to do it until devices are
1435 out with the option to uninstall the remaining data somehow (adb/ui) */
1436 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1437 {
1438 printf(
1439 "The -k option uninstalls the application while retaining the data/cache.\n"
1440 "At the moment, there is no way to remove the remaining data.\n"
1441 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1442 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1443 return -1;
1444 }
1445
1446 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1447 return pm_command(transport, serial, argc, argv);
1448}
1449
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001450static int delete_file(TransportType transport, const char* serial, char* filename) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001451 std::string cmd = "shell:rm -f " + escape_arg(filename);
Elliott Hughes15551472015-04-21 17:58:55 -07001452 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001453}
1454
Kenny Root597ea5b2011-08-05 11:19:45 -07001455static const char* get_basename(const char* filename)
1456{
1457 const char* basename = adb_dirstop(filename);
1458 if (basename) {
1459 basename++;
1460 return basename;
1461 } else {
1462 return filename;
1463 }
1464}
1465
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001466static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001467 static const char *const DATA_DEST = "/data/local/tmp/%s";
1468 static const char *const SD_DEST = "/sdcard/tmp/%s";
1469 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001470 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001471 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001472
1473 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001474 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001475 where = SD_DEST;
1476 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477 }
1478
Jeff Sharkey960df972014-06-09 17:30:57 -07001479 // Find last APK argument.
1480 // All other arguments passed through verbatim.
1481 int last_apk = -1;
1482 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001483 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001484 char* dot = strrchr(file, '.');
1485 if (dot && !strcasecmp(dot, ".apk")) {
1486 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1487 fprintf(stderr, "Invalid APK file: %s\n", file);
1488 return -1;
1489 }
1490
1491 last_apk = i;
1492 break;
1493 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001494 }
1495
Jeff Sharkey960df972014-06-09 17:30:57 -07001496 if (last_apk == -1) {
1497 fprintf(stderr, "Missing APK file\n");
1498 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001499 }
1500
Dan Albertbac34742015-02-25 17:51:28 -08001501 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001502 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001503 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001504 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001505 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001506 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001507 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001508 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001509 }
1510
Elliott Hughes15551472015-04-21 17:58:55 -07001511 err = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001512
Kenny Root60733e92012-03-26 16:14:02 -07001513cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001514 delete_file(transport, serial, apk_dest);
1515 return err;
1516}
1517
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001518static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001519 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001520{
Jeff Sharkey960df972014-06-09 17:30:57 -07001521 int i;
1522 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001523 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001524
1525 // Find all APK arguments starting at end.
1526 // All other arguments passed through verbatim.
1527 int first_apk = -1;
1528 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001529 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001530 char* dot = strrchr(file, '.');
1531 if (dot && !strcasecmp(dot, ".apk")) {
1532 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1533 fprintf(stderr, "Invalid APK file: %s\n", file);
1534 return -1;
1535 }
1536
1537 total_size += sb.st_size;
1538 first_apk = i;
1539 } else {
1540 break;
1541 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001542 }
1543
Jeff Sharkey960df972014-06-09 17:30:57 -07001544 if (first_apk == -1) {
1545 fprintf(stderr, "Missing APK file\n");
1546 return 1;
1547 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001548
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001549 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001550 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001551 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001552 }
1553
1554 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001555 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001556 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001557 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001558 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001559 return -1;
1560 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001561 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001562 read_status_line(fd, buf, sizeof(buf));
1563 adb_close(fd);
1564
1565 int session_id = -1;
1566 if (!strncmp("Success", buf, 7)) {
1567 char* start = strrchr(buf, '[');
1568 char* end = strrchr(buf, ']');
1569 if (start && end) {
1570 *end = '\0';
1571 session_id = strtol(start + 1, NULL, 10);
1572 }
1573 }
1574 if (session_id < 0) {
1575 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001576 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001577 return -1;
1578 }
1579
1580 // Valid session, now stream the APKs
1581 int success = 1;
1582 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001583 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001584 if (stat(file, &sb) == -1) {
1585 fprintf(stderr, "Failed to stat %s\n", file);
1586 success = 0;
1587 goto finalize_session;
1588 }
1589
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001590 std::string cmd = android::base::StringPrintf(
1591 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1592 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001593
1594 int localFd = adb_open(file, O_RDONLY);
1595 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001596 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001597 success = 0;
1598 goto finalize_session;
1599 }
1600
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001601 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001602 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001603 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001604 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001605 adb_close(localFd);
1606 success = 0;
1607 goto finalize_session;
1608 }
1609
1610 copy_to_file(localFd, remoteFd);
1611 read_status_line(remoteFd, buf, sizeof(buf));
1612
1613 adb_close(localFd);
1614 adb_close(remoteFd);
1615
1616 if (strncmp("Success", buf, 7)) {
1617 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001618 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001619 success = 0;
1620 goto finalize_session;
1621 }
1622 }
1623
1624finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001625 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001626 std::string service =
1627 android::base::StringPrintf("exec:pm install-%s %d",
1628 success ? "commit" : "abandon", session_id);
1629 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001630 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001631 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001632 return -1;
1633 }
1634 read_status_line(fd, buf, sizeof(buf));
1635 adb_close(fd);
1636
1637 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001638 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001639 return 0;
1640 } else {
1641 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001642 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001643 return -1;
1644 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001645}