blob: fd9953ca6fb1356698063777caee1899b47924c4 [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 Hughesaceb9c02015-05-04 19:29:32 -070050static int install_app(transport_type t, const char* serial, int argc, const char** argv);
51static int install_multiple_app(transport_type t, const char* serial, int argc, const char** argv);
52static int uninstall_app(transport_type 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 Hughes02418b32015-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"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900148 " adb install [-lrtsdg] <file>\n"
Svetoslav23d84072015-06-01 16:02:50 -0700149 " - push this package file to the device and install it\n"
150 " (-l: forward lock application)\n"
151 " (-r: replace existing application)\n"
152 " (-t: allow test packages)\n"
153 " (-s: install application on sdcard)\n"
154 " (-d: allow version code downgrade)\n"
155 " (-g: grant all runtime permissions)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900156 " adb install-multiple [-lrtsdpg] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700157 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700158 " (-l: forward lock application)\n"
159 " (-r: replace existing application)\n"
160 " (-t: allow test packages)\n"
161 " (-s: install application on sdcard)\n"
162 " (-d: allow version code downgrade)\n"
163 " (-p: partial application install)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900164 " (-g: grant all runtime permissions)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165 " adb uninstall [-k] <package> - remove this app package from the device\n"
166 " ('-k' means keep the data and cache directories)\n"
167 " adb bugreport - return all information from the device\n"
168 " that should be included in a bug report.\n"
169 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800170 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700171 " - write an archive of the device's data to <file>.\n"
172 " If no -f option is supplied then the data is written\n"
173 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700174 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700175 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800176 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
177 " (aka .obb) files associated with each application; the default\n"
178 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700179 " (-shared|-noshared enable/disable backup of the device's\n"
180 " shared storage / SD card contents; the default is noshared.)\n"
181 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700182 " (-system|-nosystem toggles whether -all automatically includes\n"
183 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700184 " (<packages...> is the list of applications to be backed up. If\n"
185 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700186 " list is optional. Applications explicitly given on the\n"
187 " command line will be included even if -nosystem would\n"
188 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700189 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700190 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700191 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800192 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
193 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800194 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
195 " and the public key is stored in <file>.pub. Any existing files\n"
196 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 " adb help - show this help message\n"
198 " adb version - show version num\n"
199 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 "scripting:\n"
201 " adb wait-for-device - block until device is online\n"
202 " adb start-server - ensure that there is a server running\n"
203 " adb kill-server - kill the server if it is running\n"
204 " adb get-state - prints: offline | bootloader | device\n"
205 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700206 " adb get-devpath - prints: <device-path>\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000207 " 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 -0700208 " adb reboot [bootloader|recovery]\n"
209 " - reboots the device, optionally into the bootloader or recovery program.\n"
210 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
211 " adb reboot sideload-auto-reboot\n"
212 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800213 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700214 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500215 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800216 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000217 " 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 -0800218 "networking:\n"
219 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500220 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
222 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
223 "\n"
224 "adb sync notes: adb sync [ <directory> ]\n"
225 " <localdir> can be interpreted in several ways:\n"
226 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000227 " - 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 -0800228 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000229 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000231 "\n"
232 "environmental variables:\n"
233 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
234 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
235 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
236 " 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 -0800237 );
238}
239
Elliott Hughes58305772015-04-17 13:57:15 -0700240static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 help();
242 return 1;
243}
244
Yabin Cuid325e862014-11-17 14:48:25 -0800245#if defined(_WIN32)
246
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700247// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800248void stdin_raw_init(int fd);
249void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800250
251#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100252static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100254static void stdin_raw_init(int fd) {
255 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100257 termios tio;
258 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100262 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263 tio.c_cc[VTIME] = 0;
264 tio.c_cc[VMIN] = 1;
265
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100266 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267}
268
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100269static void stdin_raw_restore(int fd) {
270 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800271}
272#endif
273
Elliott Hughes207ddb22015-05-07 23:37:40 -0700274static void read_and_dump(int fd) {
275 while (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700276 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
Elliott Hughes207ddb22015-05-07 23:37:40 -0700277 char buf[BUFSIZ];
278 int len = adb_read(fd, buf, sizeof(buf));
JP Abgrall408fa572011-03-16 15:57:42 -0700279 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
Elliott Hughes207ddb22015-05-07 23:37:40 -0700280 if (len <= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 break;
282 }
283
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400284 fwrite(buf, 1, len, stdout);
285 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800286 }
287}
288
Jeff Sharkey960df972014-06-09 17:30:57 -0700289static void read_status_line(int fd, char* buf, size_t count)
290{
291 count--;
292 while (count > 0) {
293 int len = adb_read(fd, buf, count);
294 if (len == 0) {
295 break;
296 } else if (len < 0) {
297 if (errno == EINTR) continue;
298 break;
299 }
300
301 buf += len;
302 count -= len;
303 }
304 *buf = '\0';
305}
306
Christopher Tated2f54152011-04-21 12:53:28 -0700307static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700308 const size_t BUFSIZE = 32 * 1024;
309 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700310 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700311 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700312 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700313
314 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800315
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700316 if (inFd == STDIN_FILENO) {
317 stdin_raw_init(STDIN_FILENO);
318 }
Yabin Cuid325e862014-11-17 14:48:25 -0800319
Elliott Hughesa7090b92015-04-17 17:03:59 -0700320 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700321 if (inFd == STDIN_FILENO) {
322 len = unix_read(inFd, buf, BUFSIZE);
323 } else {
324 len = adb_read(inFd, buf, BUFSIZE);
325 }
Christopher Tated2f54152011-04-21 12:53:28 -0700326 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700327 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700328 break;
329 }
330 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700331 if (errno == EINTR) {
332 D("copy_to_file() : EINTR, retrying\n");
333 continue;
334 }
Christopher Tated2f54152011-04-21 12:53:28 -0700335 D("copy_to_file() : error %d\n", errno);
336 break;
337 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700338 if (outFd == STDOUT_FILENO) {
339 fwrite(buf, 1, len, stdout);
340 fflush(stdout);
341 } else {
342 adb_write(outFd, buf, len);
343 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700344 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700345 }
Yabin Cuid325e862014-11-17 14:48:25 -0800346
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700347 if (inFd == STDIN_FILENO) {
348 stdin_raw_restore(STDIN_FILENO);
349 }
Yabin Cuid325e862014-11-17 14:48:25 -0800350
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700351 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700352 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700353}
354
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800355static void *stdin_read_thread(void *x)
356{
357 int fd, fdi;
358 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359 int r, n;
360 int state = 0;
361
362 int *fds = (int*) x;
363 fd = fds[0];
364 fdi = fds[1];
365 free(fds);
366
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367 for(;;) {
368 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700369 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700371 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 if(r == 0) break;
373 if(r < 0) {
374 if(errno == EINTR) continue;
375 break;
376 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400377 for(n = 0; n < r; n++){
378 switch(buf[n]) {
379 case '\n':
380 state = 1;
381 break;
382 case '\r':
383 state = 1;
384 break;
385 case '~':
386 if(state == 1) state++;
387 break;
388 case '.':
389 if(state == 2) {
390 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400391 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400392 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800393 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400394 default:
395 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800398 r = adb_write(fd, buf, r);
399 if(r <= 0) {
400 break;
401 }
402 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800403 return 0;
404}
405
Elliott Hughes58305772015-04-17 13:57:15 -0700406static int interactive_shell() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 adb_thread_t thr;
Elliott Hughes71aeb792015-04-29 08:35:59 -0700408 int fdi;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409
Elliott Hughes71aeb792015-04-29 08:35:59 -0700410 std::string error;
411 int fd = adb_connect("shell:", &error);
412 if (fd < 0) {
413 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 return 1;
415 }
416 fdi = 0; //dup(0);
417
Dan Albertbac34742015-02-25 17:51:28 -0800418 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700419 if (fds == nullptr) {
420 fprintf(stderr, "couldn't allocate fds array: %s\n", strerror(errno));
421 return 1;
422 }
423
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800424 fds[0] = fd;
425 fds[1] = fdi;
426
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800427 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 adb_thread_create(&thr, stdin_read_thread, fds);
429 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431 return 0;
432}
433
434
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700435static std::string format_host_command(const char* command, transport_type type, const char* serial) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 if (serial) {
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700437 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700439
440 const char* prefix = "host";
441 if (type == kTransportUsb) {
442 prefix = "host-usb";
443 } else if (type == kTransportLocal) {
444 prefix = "host-local";
445 }
446 return android::base::StringPrintf("%s:%s", prefix, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800447}
448
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700449static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes71aeb792015-04-29 08:35:59 -0700450 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800451{
Elliott Hughes71aeb792015-04-29 08:35:59 -0700452 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700453 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes71aeb792015-04-29 08:35:59 -0700454 if (fd < 0) {
455 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800456 return -1;
457 }
458
459 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800460 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800461
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700462 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800463 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800464
Elliott Hughes71aeb792015-04-29 08:35:59 -0700465 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800466 char *x = strrchr(service, ':');
467 if(x) service = x + 1;
468 }
469
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700470 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800471 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes71aeb792015-04-29 08:35:59 -0700472 if (!WriteFdExactly(fd, ptr, xfer)) {
473 std::string error;
474 adb_status(fd, &error);
475 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800476 return -1;
477 }
478 sz -= xfer;
479 ptr += xfer;
Elliott Hughes71aeb792015-04-29 08:35:59 -0700480 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100481 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800482 fflush(stdout);
483 }
484 }
Elliott Hughes71aeb792015-04-29 08:35:59 -0700485 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800486 printf("\n");
487 }
488
Elliott Hughes92af7332015-04-30 17:32:03 -0700489 if (!adb_status(fd, &error)) {
490 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800491 return -1;
492 }
493
494 adb_close(fd);
495 return 0;
496}
497
Doug Zongker71fe5842014-06-26 15:35:36 -0700498#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
499
500/*
501 * The sideload-host protocol serves the data in a file (given on the
502 * command line) to the client, using a simple protocol:
503 *
504 * - The connect message includes the total number of bytes in the
505 * file and a block size chosen by us.
506 *
507 * - The other side sends the desired block number as eight decimal
508 * digits (eg "00000023" for block 23). Blocks are numbered from
509 * zero.
510 *
511 * - We send back the data of the requested block. The last block is
512 * likely to be partial; when the last block is requested we only
513 * send the part of the block that exists, it's not padded up to the
514 * block size.
515 *
516 * - When the other side sends "DONEDONE" instead of a block number,
517 * we hang up.
518 */
Elliott Hughes58305772015-04-17 13:57:15 -0700519static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700520 unsigned sz;
521 size_t xfer = 0;
522 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800523 int last_percent = -1;
524 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700525
526 printf("loading: '%s'", fn);
527 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800528 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700529 if (data == 0) {
530 printf("\n");
531 fprintf(stderr, "* cannot read '%s' *\n", fn);
532 return -1;
533 }
534
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700535 std::string service =
536 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes71aeb792015-04-29 08:35:59 -0700537 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700538 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700539 if (fd < 0) {
540 // Try falling back to the older sideload method. Maybe this
541 // is an older device that doesn't support sideload-host.
542 printf("\n");
Elliott Hughes71aeb792015-04-29 08:35:59 -0700543 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700544 goto done;
545 }
546
Spencer Lowf055c192015-01-25 14:40:16 -0800547 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700548
Elliott Hughesa7090b92015-04-17 17:03:59 -0700549 while (true) {
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700550 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800551 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700552 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700553 status = -1;
554 goto done;
555 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700556 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700557
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700558 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700559 status = 0;
560 break;
561 }
562
Doug Zongker71fe5842014-06-26 15:35:36 -0700563 int block = strtol(buf, NULL, 10);
564
565 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
566 if (offset >= sz) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700567 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700568 status = -1;
569 goto done;
570 }
571 uint8_t* start = data + offset;
572 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
573 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
574 if (offset_end > sz) {
575 to_write = sz - offset;
576 }
577
Dan Albertcc731cc2015-02-24 21:26:58 -0800578 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700579 adb_status(fd, &error);
580 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700581 status = -1;
582 goto done;
583 }
584 xfer += to_write;
585
586 // For normal OTA packages, we expect to transfer every byte
587 // twice, plus a bit of overhead (one read during
588 // verification, one read of each byte for installation, plus
589 // extra access to things like the zip central directory).
590 // This estimate of the completion becomes 100% when we've
591 // transferred ~2.13 (=100/47) times the package size.
592 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
593 if (percent != last_percent) {
594 printf("\rserving: '%s' (~%d%%) ", fn, percent);
595 fflush(stdout);
596 last_percent = percent;
597 }
598 }
599
Colin Cross6d6a8982014-07-07 14:12:41 -0700600 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700601
602 done:
603 if (fd >= 0) adb_close(fd);
604 free(data);
605 return status;
606}
607
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800608/**
609 * Run ppp in "notty" mode against a resource listed as the first parameter
610 * eg:
611 *
612 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
613 *
614 */
Elliott Hughes58305772015-04-17 13:57:15 -0700615static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800616#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800617 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
618 return -1;
619#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800620 if (argc < 2) {
621 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
622 argv[0]);
623
624 return 1;
625 }
626
Dan Albertbac34742015-02-25 17:51:28 -0800627 const char* adb_service_name = argv[1];
Elliott Hughes71aeb792015-04-29 08:35:59 -0700628 std::string error;
629 int fd = adb_connect(adb_service_name, &error);
630 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800631 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes71aeb792015-04-29 08:35:59 -0700632 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800633 return 1;
634 }
635
Elliott Hughes71aeb792015-04-29 08:35:59 -0700636 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637
638 if (pid < 0) {
639 perror("from fork()");
640 return 1;
641 } else if (pid == 0) {
642 int err;
643 int i;
644 const char **ppp_args;
645
646 // copy args
647 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
648 ppp_args[0] = "pppd";
649 for (i = 2 ; i < argc ; i++) {
650 //argv[2] and beyond become ppp_args[1] and beyond
651 ppp_args[i - 1] = argv[i];
652 }
653 ppp_args[i-1] = NULL;
654
655 // child side
656
657 dup2(fd, STDIN_FILENO);
658 dup2(fd, STDOUT_FILENO);
659 adb_close(STDERR_FILENO);
660 adb_close(fd);
661
662 err = execvp("pppd", (char * const *)ppp_args);
663
664 if (err < 0) {
665 perror("execing pppd");
666 }
667 exit(-1);
668 } else {
669 // parent side
670
671 adb_close(fd);
672 return 0;
673 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800674#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800675}
676
Elliott Hughesaceb9c02015-05-04 19:29:32 -0700677static bool wait_for_device(const char* service, transport_type t, const char* serial) {
678 // Was the caller vague about what they'd like us to wait for?
679 // If so, check they weren't more specific in their choice of transport type.
680 if (strcmp(service, "wait-for-device") == 0) {
681 if (t == kTransportUsb) {
682 service = "wait-for-usb";
683 } else if (t == kTransportLocal) {
684 service = "wait-for-local";
685 } else {
686 service = "wait-for-any";
687 }
688 }
689
690 std::string cmd = format_host_command(service, t, serial);
691 std::string error;
692 if (adb_command(cmd, &error)) {
693 D("failure: %s *\n", error.c_str());
694 fprintf(stderr,"error: %s\n", error.c_str());
695 return false;
696 }
697
698 return true;
699}
700
701static int send_shell_command(transport_type transport_type, const char* serial,
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700702 const std::string& command) {
703 int fd;
704 while (true) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700705 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700706 fd = adb_connect(command, &error);
Elliott Hughes71aeb792015-04-29 08:35:59 -0700707 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800708 break;
Elliott Hughes71aeb792015-04-29 08:35:59 -0700709 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800710 fprintf(stderr,"- waiting for device -\n");
711 adb_sleep_ms(1000);
Elliott Hughesaceb9c02015-05-04 19:29:32 -0700712 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713 }
714
715 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700716 int rc = adb_close(fd);
717 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800718 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700719 }
720 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721}
722
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700723static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
724 char* log_tags = getenv("ANDROID_LOG_TAGS");
725 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800726
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700727 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800728
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700729 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700730 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800731 }
732
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700733 --argc;
734 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700735 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700736 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800737 }
738
Elliott Hughes15551472015-04-21 17:58:55 -0700739 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800740}
741
Mark Salyzyn60299df2014-04-30 09:10:31 -0700742static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800743{
744 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700745 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800746
747 for(;;) {
748 x = adb_dirstart(x);
749 if(x == 0) return 0;
750 *x = 0;
751 ret = adb_mkdir(path, 0775);
752 *x = OS_PATH_SEPARATOR;
753 if((ret < 0) && (errno != EEXIST)) {
754 return ret;
755 }
756 x++;
757 }
758 return 0;
759}
760
Dan Albertbac34742015-02-25 17:51:28 -0800761static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700762 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700763
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700764 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700765 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700766 if (!strcmp("-f", argv[i])) {
767 if (i == argc-1) {
768 fprintf(stderr, "adb: -f passed with no filename\n");
769 return usage();
770 }
771 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700772 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700773 argv[i++] = argv[j++];
774 }
775 argc -= 2;
776 argv[argc] = NULL;
777 }
Christopher Tated2f54152011-04-21 12:53:28 -0700778 }
779
Christopher Tatebb86bc52011-08-22 17:12:08 -0700780 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
781 if (argc < 2) return usage();
782
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800783 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700784 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700785 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700786 if (outFd < 0) {
787 fprintf(stderr, "adb: unable to open file %s\n", filename);
788 return -1;
789 }
790
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700791 std::string cmd = "backup:";
792 --argc;
793 ++argv;
794 while (argc-- > 0) {
795 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700796 }
797
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700798 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
Elliott Hughes71aeb792015-04-29 08:35:59 -0700799 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700800 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -0700801 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700802 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700803 adb_close(outFd);
804 return -1;
805 }
806
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800807 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700808 copy_to_file(fd, outFd);
809
810 adb_close(fd);
811 adb_close(outFd);
812 return 0;
813}
814
Dan Albertbac34742015-02-25 17:51:28 -0800815static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700816 if (argc != 2) return usage();
817
Elliott Hughes71aeb792015-04-29 08:35:59 -0700818 const char* filename = argv[1];
819 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -0700820 if (tarFd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700821 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -0700822 return -1;
823 }
824
Elliott Hughes71aeb792015-04-29 08:35:59 -0700825 std::string error;
826 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -0700827 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700828 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -0700829 adb_close(tarFd);
830 return -1;
831 }
832
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800833 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700834 copy_to_file(tarFd, fd);
835
836 adb_close(fd);
837 adb_close(tarFd);
838 return 0;
839}
840
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841/* <hint> may be:
842 * - A simple product name
843 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800844 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
845 * e.g., "out/target/product/sooner"
846 * - An absolute path to the PRODUCT_OUT dir
847 * e.g., "/src/device/out/target/product/sooner"
848 *
849 * Given <hint>, try to construct an absolute path to the
850 * ANDROID_PRODUCT_OUT dir.
851 */
Elliott Hughes58305772015-04-17 13:57:15 -0700852static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700854 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800855 }
856
Elliott Hughes58305772015-04-17 13:57:15 -0700857 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800858 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700859 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800860 }
861
Elliott Hughes58305772015-04-17 13:57:15 -0700862 // If there are any slashes in it, assume it's a relative path;
863 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700864 if (adb_dirstart(hint) != nullptr) {
865 std::string cwd;
866 if (!getcwd(&cwd)) {
867 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700868 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800869 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700870 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 -0800871 }
872
Elliott Hughes58305772015-04-17 13:57:15 -0700873 // It's a string without any slashes. Try to do something with it.
874 //
875 // Try to find the root of the build tree, and build a PRODUCT_OUT
876 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700877 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700878 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700879 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700880 return "";
881 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700882
883 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700884 path += OS_PATH_SEPARATOR_STR;
885 path += "out";
886 path += OS_PATH_SEPARATOR_STR;
887 path += "target";
888 path += OS_PATH_SEPARATOR_STR;
889 path += "product";
890 path += OS_PATH_SEPARATOR_STR;
891 path += hint;
892 if (!directory_exists(path)) {
893 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
894 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700895 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800896 }
Elliott Hughes58305772015-04-17 13:57:15 -0700897 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898}
899
Dan Albertbac34742015-02-25 17:51:28 -0800900static void parse_push_pull_args(const char **arg, int narg, char const **path1,
901 char const **path2, int *show_progress,
902 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700903 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700904 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700905
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700906 while (narg > 0) {
907 if (!strcmp(*arg, "-p")) {
908 *show_progress = 1;
909 } else if (!strcmp(*arg, "-a")) {
910 *copy_attrs = 1;
911 } else {
912 break;
913 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700914 ++arg;
915 --narg;
916 }
917
918 if (narg > 0) {
919 *path1 = *arg;
920 ++arg;
921 --narg;
922 }
923
924 if (narg > 0) {
925 *path2 = *arg;
926 }
927}
928
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700929static int adb_connect_command(const std::string& command) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700930 std::string error;
931 int fd = adb_connect(command, &error);
Elliott Hughes207ddb22015-05-07 23:37:40 -0700932 if (fd < 0) {
933 fprintf(stderr, "error: %s\n", error.c_str());
934 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -0700935 }
Elliott Hughes207ddb22015-05-07 23:37:40 -0700936 read_and_dump(fd);
937 adb_close(fd);
938 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -0700939}
940
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700941static int adb_query_command(const std::string& command) {
942 std::string result;
943 std::string error;
944 if (!adb_query(command, &result, &error)) {
945 fprintf(stderr, "error: %s\n", error.c_str());
946 return 1;
947 }
948 printf("%s\n", result.c_str());
949 return 0;
950}
951
Elliott Hughese1a55002015-05-01 17:04:38 -0700952int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800953 int no_daemon = 0;
954 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100955 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800956 int persist = 0;
957 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800958 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -0800959 const char* serial = NULL;
960 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800961
Elliott Hughes58305772015-04-17 13:57:15 -0700962 // If defined, this should be an absolute path to
963 // the directory containing all of the various system images
964 // for a particular product. If not defined, and the adb
965 // command requires this information, then the user must
966 // specify the path using "-p".
967 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
968 if (ANDROID_PRODUCT_OUT != nullptr) {
969 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800970 }
971 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
972
Nick Pellydb449262009-05-07 12:48:03 -0700973 serial = getenv("ANDROID_SERIAL");
974
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100975 /* Validate and assign the server port */
976 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
977 int server_port = DEFAULT_ADB_PORT;
978 if (server_port_str && strlen(server_port_str) > 0) {
979 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800980 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100981 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800982 "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 +0100983 server_port_str);
984 return usage();
985 }
986 }
987
988 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -0800989 while (argc > 0) {
990 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100991 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800992 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800993 no_daemon = 1;
994 } else if (!strcmp(argv[0], "fork-server")) {
995 /* this is a special flag used only when the ADB client launches the ADB Server */
996 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800997 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800998 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800999 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000 const char *product = NULL;
1001 if (argv[0][2] == '\0') {
1002 if (argc < 2) return usage();
1003 product = argv[1];
1004 argc--;
1005 argv++;
1006 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001007 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001008 }
1009 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001010 if (gProductOutPath.empty()) {
1011 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 return usage();
1013 }
1014 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1015 if (isdigit(argv[0][2])) {
1016 serial = argv[0] + 2;
1017 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001018 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001019 serial = argv[1];
1020 argc--;
1021 argv++;
1022 }
1023 } else if (!strcmp(argv[0],"-d")) {
1024 ttype = kTransportUsb;
1025 } else if (!strcmp(argv[0],"-e")) {
1026 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001027 } else if (!strcmp(argv[0],"-a")) {
1028 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001029 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001030 const char *hostname = NULL;
1031 if (argv[0][2] == '\0') {
1032 if (argc < 2) return usage();
1033 hostname = argv[1];
1034 argc--;
1035 argv++;
1036 } else {
1037 hostname = argv[0] + 2;
1038 }
1039 adb_set_tcp_name(hostname);
1040
Riley Andrews98f58e82014-12-05 17:37:24 -08001041 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001042 if (argv[0][2] == '\0') {
1043 if (argc < 2) return usage();
1044 server_port_str = argv[1];
1045 argc--;
1046 argv++;
1047 } else {
1048 server_port_str = argv[0] + 2;
1049 }
1050 if (strlen(server_port_str) > 0) {
1051 server_port = (int) strtol(server_port_str, NULL, 0);
1052 if (server_port <= 0 || server_port > 65535) {
1053 fprintf(stderr,
1054 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1055 server_port_str);
1056 return usage();
1057 }
1058 } else {
1059 fprintf(stderr,
1060 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1061 return usage();
1062 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001063 } else {
1064 /* out of recognized modifiers and flags */
1065 break;
1066 }
1067 argc--;
1068 argv++;
1069 }
1070
1071 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001072 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001073
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001074 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001075 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001076 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001077 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001078 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001079 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001080 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001081 fprintf(stderr,"* could not start server *\n");
1082 }
1083 return r;
1084 }
1085
Riley Andrews98f58e82014-12-05 17:37:24 -08001086 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001087 return usage();
1088 }
1089
Riley Andrewsc8514c82014-12-05 17:32:46 -08001090 /* handle wait-for-* prefix */
1091 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001092 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001093
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001094 if (!wait_for_device(service, ttype, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001095 return 1;
1096 }
1097
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001098 // Allow a command to be run after wait-for-device,
1099 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001100 if (argc == 1) {
1101 return 0;
1102 }
1103
1104 /* Fall through */
1105 argc--;
1106 argv++;
1107 }
1108
1109 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001110 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001111 const char *listopt;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001112 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001113 listopt = "";
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001114 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001115 listopt = argv[1];
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001116 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001117 fprintf(stderr, "Usage: adb devices [-l]\n");
1118 return 1;
1119 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001120
1121 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1122 printf("List of devices attached\n");
1123 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001124 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001125 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001126 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001127 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001128 return 1;
1129 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001130
1131 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1132 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001133 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001134 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001135 if (argc > 2) {
1136 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1137 return 1;
1138 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001139
1140 std::string query = android::base::StringPrintf("host:disconnect:%s",
1141 (argc == 2) ? argv[1] : "");
1142 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001143 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001144 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001145 return adb_send_emulator_command(argc, argv);
1146 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001147 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001148 char h = (argv[0][0] == 'h');
1149
1150 if (h) {
1151 printf("\x1b[41;33m");
1152 fflush(stdout);
1153 }
1154
Riley Andrews98f58e82014-12-05 17:37:24 -08001155 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001156 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001157 r = interactive_shell();
1158 if (h) {
1159 printf("\x1b[0m");
1160 fflush(stdout);
1161 }
1162 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 }
1164
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001165 std::string cmd = "shell:";
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001166 --argc;
1167 ++argv;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001168 while (argc-- > 0) {
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001169 // We don't escape here, just like ssh(1). http://b/20564385.
1170 cmd += *argv++;
1171 if (*argv) cmd += " ";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001172 }
1173
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001174 while (true) {
1175 D("interactive shell loop. cmd=%s\n", cmd.c_str());
Elliott Hughes71aeb792015-04-29 08:35:59 -07001176 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001177 int fd = adb_connect(cmd, &error);
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001178 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001179 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001180 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001181 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001182 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001183 adb_close(fd);
1184 r = 0;
1185 } else {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001186 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001187 r = -1;
1188 }
1189
Riley Andrews98f58e82014-12-05 17:37:24 -08001190 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191 fprintf(stderr,"\n- waiting for device -\n");
1192 adb_sleep_ms(1000);
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001193 wait_for_device("wait-for-device", ttype, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001194 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001195 if (h) {
1196 printf("\x1b[0m");
1197 fflush(stdout);
1198 }
JP Abgrall408fa572011-03-16 15:57:42 -07001199 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001200 return r;
1201 }
1202 }
1203 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001204 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001205 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001206
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001207 std::string cmd = "exec:";
1208 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001209 argc -= 2;
1210 argv += 2;
1211 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001212 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001213 }
1214
Elliott Hughes71aeb792015-04-29 08:35:59 -07001215 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001216 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001217 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001218 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001219 return -1;
1220 }
1221
1222 if (exec_in) {
1223 copy_to_file(STDIN_FILENO, fd);
1224 } else {
1225 copy_to_file(fd, STDOUT_FILENO);
1226 }
1227
1228 adb_close(fd);
1229 return 0;
1230 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001231 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001232 std::string error;
1233 int fd = _adb_connect("host:kill", &error);
Riley Andrews98f58e82014-12-05 17:37:24 -08001234 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001235 fprintf(stderr,"* server not running *\n");
1236 return 1;
1237 }
1238 return 0;
1239 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001240 else if (!strcmp(argv[0], "sideload")) {
1241 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001242 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001243 return 1;
1244 } else {
1245 return 0;
1246 }
1247 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001248 else if (!strcmp(argv[0], "remount") ||
1249 !strcmp(argv[0], "reboot") ||
1250 !strcmp(argv[0], "reboot-bootloader") ||
1251 !strcmp(argv[0], "tcpip") ||
1252 !strcmp(argv[0], "usb") ||
1253 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001254 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001255 !strcmp(argv[0], "disable-verity") ||
1256 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001257 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001258 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001259 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001260 } else if (argc > 1) {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001261 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001262 } else {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001263 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001264 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001265 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001266 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001267 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001268 if (argc != 1) return usage();
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001269 return send_shell_command(ttype, serial, "shell:bugreport");
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001270 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001271 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001272 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughese1a55002015-05-01 17:04:38 -07001273 std::string cmd;
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001274 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001275 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001276 char remove = 0;
1277 char remove_all = 0;
1278 char list = 0;
1279 char no_rebind = 0;
1280
1281 // Parse options here.
1282 while (argc > 1 && argv[1][0] == '-') {
1283 if (!strcmp(argv[1], "--list"))
1284 list = 1;
1285 else if (!strcmp(argv[1], "--remove"))
1286 remove = 1;
1287 else if (!strcmp(argv[1], "--remove-all"))
1288 remove_all = 1;
1289 else if (!strcmp(argv[1], "--no-rebind"))
1290 no_rebind = 1;
1291 else {
1292 return usage();
1293 }
1294 argc--;
1295 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001296 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001297
1298 // Ensure we can only use one option at a time.
1299 if (list + remove + remove_all + no_rebind > 1) {
1300 return usage();
1301 }
1302
1303 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001304 if (reverse) {
1305 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001306 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001307 if (serial) {
1308 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1309 serial);
1310 } else if (ttype == kTransportUsb) {
1311 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1312 } else if (ttype == kTransportLocal) {
1313 snprintf(host_prefix, sizeof host_prefix, "host-local");
1314 } else {
1315 snprintf(host_prefix, sizeof host_prefix, "host");
1316 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001317 }
1318
1319 // Implement forward --list
1320 if (list) {
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001321 if (argc != 1) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001322 return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001323 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001324
1325 std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
1326 return adb_query_command(query);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001327 }
1328
1329 // Implement forward --remove-all
1330 else if (remove_all) {
Elliott Hughese1a55002015-05-01 17:04:38 -07001331 if (argc != 1) return usage();
1332 cmd = android::base::StringPrintf("%s:killforward-all", host_prefix);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001333 }
1334
1335 // Implement forward --remove <local>
1336 else if (remove) {
Elliott Hughese1a55002015-05-01 17:04:38 -07001337 if (argc != 2) return usage();
1338 cmd = android::base::StringPrintf("%s:killforward:%s", host_prefix, argv[1]);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001339 }
1340 // Or implement one of:
1341 // forward <local> <remote>
1342 // forward --no-rebind <local> <remote>
Elliott Hughese1a55002015-05-01 17:04:38 -07001343 else {
1344 if (argc != 3) return usage();
1345 const char* command = no_rebind ? "forward:norebind" : "forward";
1346 cmd = android::base::StringPrintf("%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001347 }
1348
Elliott Hughes71aeb792015-04-29 08:35:59 -07001349 std::string error;
Elliott Hughese1a55002015-05-01 17:04:38 -07001350 if (adb_command(cmd, &error)) {
1351 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001352 return 1;
1353 }
1354 return 0;
1355 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001356 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001357 else if (!strcmp(argv[0], "ls")) {
1358 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001359 return do_sync_ls(argv[1]);
1360 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001361 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001362 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001363 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001364 const char* lpath = NULL, *rpath = NULL;
1365
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001366 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001367
1368 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001369 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001370 }
1371
1372 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001373 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001374 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001375 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001376 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001377 const char* rpath = NULL, *lpath = ".";
1378
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001379 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001380
1381 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001382 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001383 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001384
1385 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001386 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001387 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001388 if (argc < 2) return usage();
1389 return install_app(ttype, serial, argc, argv);
1390 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001391 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001392 if (argc < 2) return usage();
1393 return install_multiple_app(ttype, serial, argc, argv);
1394 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001395 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 if (argc < 2) return usage();
1397 return uninstall_app(ttype, serial, argc, argv);
1398 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001399 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001400 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001401 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001402 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001403 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001404 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001405 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001406 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001407 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001408 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001409 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001410 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001411 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001412 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001413 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001414 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001415 } else {
1416 return usage();
1417 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418
Elliott Hughesd236d072015-04-21 10:17:07 -07001419 if (src != "" &&
1420 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001421 return usage();
1422 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423
Elliott Hughes58305772015-04-17 13:57:15 -07001424 std::string system_src_path = product_file("system");
1425 std::string data_src_path = product_file("data");
1426 std::string vendor_src_path = product_file("vendor");
1427 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001428
1429 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001430 if (rc == 0 && (src.empty() || src == "system")) {
1431 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001432 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001433 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1434 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001435 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001436 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1437 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001438 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001439 if (rc == 0 && (src.empty() || src == "data")) {
1440 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001441 }
1442 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001443 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001444 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001445 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001446 !strcmp(argv[0],"get-serialno") ||
1447 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001448 {
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001449 return adb_query_command(format_host_command(argv[0], ttype, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001450 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001451 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001452 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001453 return logcat(ttype, serial, argc, argv);
1454 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001455 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001456 return ppp(argc, argv);
1457 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001458 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001459 std::string error;
1460 return adb_connect("host:start-server", &error);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001461 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001462 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001463 return backup(argc, argv);
1464 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001465 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001466 return restore(argc, argv);
1467 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001468 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001469 if (argc < 2) return usage();
1470 return adb_auth_keygen(argv[1]);
1471 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001472 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001473 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001474 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001475 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001476 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477 help();
1478 return 0;
1479 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001480 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001481 version(stdout);
1482 return 0;
1483 }
1484
1485 usage();
1486 return 1;
1487}
1488
Dan Albertbac34742015-02-25 17:51:28 -08001489static int pm_command(transport_type transport, const char* serial,
1490 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001491{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001492 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001493
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001494 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001495 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001496 }
1497
Elliott Hughes15551472015-04-21 17:58:55 -07001498 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001499}
1500
Elliott Hughes58305772015-04-17 13:57:15 -07001501static int uninstall_app(transport_type transport, const char* serial, int argc,
1502 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503{
1504 /* if the user choose the -k option, we refuse to do it until devices are
1505 out with the option to uninstall the remaining data somehow (adb/ui) */
1506 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1507 {
1508 printf(
1509 "The -k option uninstalls the application while retaining the data/cache.\n"
1510 "At the moment, there is no way to remove the remaining data.\n"
1511 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1512 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1513 return -1;
1514 }
1515
1516 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1517 return pm_command(transport, serial, argc, argv);
1518}
1519
Dan Albertbac34742015-02-25 17:51:28 -08001520static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001521{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001522 std::string cmd = "shell:rm -f " + escape_arg(filename);
Elliott Hughes15551472015-04-21 17:58:55 -07001523 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001524}
1525
Kenny Root597ea5b2011-08-05 11:19:45 -07001526static const char* get_basename(const char* filename)
1527{
1528 const char* basename = adb_dirstop(filename);
1529 if (basename) {
1530 basename++;
1531 return basename;
1532 } else {
1533 return filename;
1534 }
1535}
1536
Elliott Hughes58305772015-04-17 13:57:15 -07001537static int install_app(transport_type transport, const char* serial, int argc,
1538 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001539{
1540 static const char *const DATA_DEST = "/data/local/tmp/%s";
1541 static const char *const SD_DEST = "/sdcard/tmp/%s";
1542 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001543 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001544 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001545
1546 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001547 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001548 where = SD_DEST;
1549 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001550 }
1551
Jeff Sharkey960df972014-06-09 17:30:57 -07001552 // Find last APK argument.
1553 // All other arguments passed through verbatim.
1554 int last_apk = -1;
1555 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001556 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001557 char* dot = strrchr(file, '.');
1558 if (dot && !strcasecmp(dot, ".apk")) {
1559 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1560 fprintf(stderr, "Invalid APK file: %s\n", file);
1561 return -1;
1562 }
1563
1564 last_apk = i;
1565 break;
1566 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001567 }
1568
Jeff Sharkey960df972014-06-09 17:30:57 -07001569 if (last_apk == -1) {
1570 fprintf(stderr, "Missing APK file\n");
1571 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001572 }
1573
Dan Albertbac34742015-02-25 17:51:28 -08001574 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001575 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001576 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001577 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001578 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001579 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001580 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001581 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001582 }
1583
Elliott Hughes15551472015-04-21 17:58:55 -07001584 err = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001585
Kenny Root60733e92012-03-26 16:14:02 -07001586cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001587 delete_file(transport, serial, apk_dest);
1588 return err;
1589}
1590
Elliott Hughes58305772015-04-17 13:57:15 -07001591static int install_multiple_app(transport_type transport, const char* serial, int argc,
1592 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001593{
Jeff Sharkey960df972014-06-09 17:30:57 -07001594 int i;
1595 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001596 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001597
1598 // Find all APK arguments starting at end.
1599 // All other arguments passed through verbatim.
1600 int first_apk = -1;
1601 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001602 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001603 char* dot = strrchr(file, '.');
1604 if (dot && !strcasecmp(dot, ".apk")) {
1605 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1606 fprintf(stderr, "Invalid APK file: %s\n", file);
1607 return -1;
1608 }
1609
1610 total_size += sb.st_size;
1611 first_apk = i;
1612 } else {
1613 break;
1614 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001615 }
1616
Jeff Sharkey960df972014-06-09 17:30:57 -07001617 if (first_apk == -1) {
1618 fprintf(stderr, "Missing APK file\n");
1619 return 1;
1620 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001621
Elliott Hughes53daee62015-04-19 13:17:01 -07001622#if defined(_WIN32) // Remove when we're using clang for Win32.
1623 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
1624#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001625 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Elliott Hughes53daee62015-04-19 13:17:01 -07001626#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001627 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001628 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001629 }
1630
1631 // Create install session
Elliott Hughes71aeb792015-04-29 08:35:59 -07001632 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001633 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001634 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001635 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001636 return -1;
1637 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001638 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001639 read_status_line(fd, buf, sizeof(buf));
1640 adb_close(fd);
1641
1642 int session_id = -1;
1643 if (!strncmp("Success", buf, 7)) {
1644 char* start = strrchr(buf, '[');
1645 char* end = strrchr(buf, ']');
1646 if (start && end) {
1647 *end = '\0';
1648 session_id = strtol(start + 1, NULL, 10);
1649 }
1650 }
1651 if (session_id < 0) {
1652 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001653 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001654 return -1;
1655 }
1656
1657 // Valid session, now stream the APKs
1658 int success = 1;
1659 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001660 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001661 if (stat(file, &sb) == -1) {
1662 fprintf(stderr, "Failed to stat %s\n", file);
1663 success = 0;
1664 goto finalize_session;
1665 }
1666
Elliott Hughes53daee62015-04-19 13:17:01 -07001667#if defined(_WIN32) // Remove when we're using clang for Win32.
1668 std::string cmd = android::base::StringPrintf(
1669 "exec:pm install-write -S %u %d %d_%s -",
1670 (unsigned) sb.st_size, session_id, i, get_basename(file));
1671#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001672 std::string cmd = android::base::StringPrintf(
1673 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1674 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Elliott Hughes53daee62015-04-19 13:17:01 -07001675#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001676
1677 int localFd = adb_open(file, O_RDONLY);
1678 if (localFd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001679 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001680 success = 0;
1681 goto finalize_session;
1682 }
1683
Elliott Hughes71aeb792015-04-29 08:35:59 -07001684 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001685 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001686 if (remoteFd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001687 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001688 adb_close(localFd);
1689 success = 0;
1690 goto finalize_session;
1691 }
1692
1693 copy_to_file(localFd, remoteFd);
1694 read_status_line(remoteFd, buf, sizeof(buf));
1695
1696 adb_close(localFd);
1697 adb_close(remoteFd);
1698
1699 if (strncmp("Success", buf, 7)) {
1700 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001701 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001702 success = 0;
1703 goto finalize_session;
1704 }
1705 }
1706
1707finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001708 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001709 std::string service =
1710 android::base::StringPrintf("exec:pm install-%s %d",
1711 success ? "commit" : "abandon", session_id);
1712 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001713 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001714 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001715 return -1;
1716 }
1717 read_status_line(fd, buf, sizeof(buf));
1718 adb_close(fd);
1719
1720 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001721 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001722 return 0;
1723 } else {
1724 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001725 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001726 return -1;
1727 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001728}