blob: 374a2e50556f09e12a3fd74d0ec105677b903b52 [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{
Elliott Hughes24f165f2015-08-21 20:31:31 -0700744 std::string holder(path);
745
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800746 int ret;
Elliott Hughes24f165f2015-08-21 20:31:31 -0700747 char *x = &holder[1];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800748
749 for(;;) {
750 x = adb_dirstart(x);
751 if(x == 0) return 0;
752 *x = 0;
753 ret = adb_mkdir(path, 0775);
754 *x = OS_PATH_SEPARATOR;
755 if((ret < 0) && (errno != EEXIST)) {
756 return ret;
757 }
758 x++;
759 }
760 return 0;
761}
762
Dan Albertbac34742015-02-25 17:51:28 -0800763static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -0700764 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700765
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700766 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700767 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700768 if (!strcmp("-f", argv[i])) {
769 if (i == argc-1) {
770 fprintf(stderr, "adb: -f passed with no filename\n");
771 return usage();
772 }
773 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700774 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700775 argv[i++] = argv[j++];
776 }
777 argc -= 2;
778 argv[argc] = NULL;
779 }
Christopher Tated2f54152011-04-21 12:53:28 -0700780 }
781
Christopher Tatebb86bc52011-08-22 17:12:08 -0700782 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
783 if (argc < 2) return usage();
784
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800785 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700786 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700787 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700788 if (outFd < 0) {
789 fprintf(stderr, "adb: unable to open file %s\n", filename);
790 return -1;
791 }
792
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700793 std::string cmd = "backup:";
794 --argc;
795 ++argv;
796 while (argc-- > 0) {
797 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700798 }
799
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700800 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
Elliott Hughes71aeb792015-04-29 08:35:59 -0700801 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700802 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -0700803 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700804 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700805 adb_close(outFd);
806 return -1;
807 }
808
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800809 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700810 copy_to_file(fd, outFd);
811
812 adb_close(fd);
813 adb_close(outFd);
814 return 0;
815}
816
Dan Albertbac34742015-02-25 17:51:28 -0800817static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700818 if (argc != 2) return usage();
819
Elliott Hughes71aeb792015-04-29 08:35:59 -0700820 const char* filename = argv[1];
821 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -0700822 if (tarFd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700823 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -0700824 return -1;
825 }
826
Elliott Hughes71aeb792015-04-29 08:35:59 -0700827 std::string error;
828 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -0700829 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700830 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -0700831 adb_close(tarFd);
832 return -1;
833 }
834
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800835 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700836 copy_to_file(tarFd, fd);
837
838 adb_close(fd);
839 adb_close(tarFd);
840 return 0;
841}
842
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800843/* <hint> may be:
844 * - A simple product name
845 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
847 * e.g., "out/target/product/sooner"
848 * - An absolute path to the PRODUCT_OUT dir
849 * e.g., "/src/device/out/target/product/sooner"
850 *
851 * Given <hint>, try to construct an absolute path to the
852 * ANDROID_PRODUCT_OUT dir.
853 */
Elliott Hughes58305772015-04-17 13:57:15 -0700854static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800855 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700856 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800857 }
858
Elliott Hughes58305772015-04-17 13:57:15 -0700859 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800860 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700861 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800862 }
863
Elliott Hughes58305772015-04-17 13:57:15 -0700864 // If there are any slashes in it, assume it's a relative path;
865 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700866 if (adb_dirstart(hint) != nullptr) {
867 std::string cwd;
868 if (!getcwd(&cwd)) {
869 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700870 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800871 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700872 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 -0800873 }
874
Elliott Hughes58305772015-04-17 13:57:15 -0700875 // It's a string without any slashes. Try to do something with it.
876 //
877 // Try to find the root of the build tree, and build a PRODUCT_OUT
878 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700879 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700880 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700881 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700882 return "";
883 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700884
885 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700886 path += OS_PATH_SEPARATOR_STR;
887 path += "out";
888 path += OS_PATH_SEPARATOR_STR;
889 path += "target";
890 path += OS_PATH_SEPARATOR_STR;
891 path += "product";
892 path += OS_PATH_SEPARATOR_STR;
893 path += hint;
894 if (!directory_exists(path)) {
895 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
896 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700897 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898 }
Elliott Hughes58305772015-04-17 13:57:15 -0700899 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800900}
901
Dan Albertbac34742015-02-25 17:51:28 -0800902static void parse_push_pull_args(const char **arg, int narg, char const **path1,
903 char const **path2, int *show_progress,
904 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700905 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700906 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700907
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700908 while (narg > 0) {
909 if (!strcmp(*arg, "-p")) {
910 *show_progress = 1;
911 } else if (!strcmp(*arg, "-a")) {
912 *copy_attrs = 1;
913 } else {
914 break;
915 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700916 ++arg;
917 --narg;
918 }
919
920 if (narg > 0) {
921 *path1 = *arg;
922 ++arg;
923 --narg;
924 }
925
926 if (narg > 0) {
927 *path2 = *arg;
928 }
929}
930
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700931static int adb_connect_command(const std::string& command) {
Elliott Hughes71aeb792015-04-29 08:35:59 -0700932 std::string error;
933 int fd = adb_connect(command, &error);
Elliott Hughes207ddb22015-05-07 23:37:40 -0700934 if (fd < 0) {
935 fprintf(stderr, "error: %s\n", error.c_str());
936 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -0700937 }
Elliott Hughes207ddb22015-05-07 23:37:40 -0700938 read_and_dump(fd);
939 adb_close(fd);
940 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -0700941}
942
Elliott Hughesf1a58f82015-04-29 12:28:13 -0700943static int adb_query_command(const std::string& command) {
944 std::string result;
945 std::string error;
946 if (!adb_query(command, &result, &error)) {
947 fprintf(stderr, "error: %s\n", error.c_str());
948 return 1;
949 }
950 printf("%s\n", result.c_str());
951 return 0;
952}
953
Elliott Hughese1a55002015-05-01 17:04:38 -0700954int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800955 int no_daemon = 0;
956 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100957 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800958 int persist = 0;
959 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800960 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -0800961 const char* serial = NULL;
962 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800963
Elliott Hughes58305772015-04-17 13:57:15 -0700964 // If defined, this should be an absolute path to
965 // the directory containing all of the various system images
966 // for a particular product. If not defined, and the adb
967 // command requires this information, then the user must
968 // specify the path using "-p".
969 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
970 if (ANDROID_PRODUCT_OUT != nullptr) {
971 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800972 }
973 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
974
Nick Pellydb449262009-05-07 12:48:03 -0700975 serial = getenv("ANDROID_SERIAL");
976
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100977 /* Validate and assign the server port */
978 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
979 int server_port = DEFAULT_ADB_PORT;
980 if (server_port_str && strlen(server_port_str) > 0) {
981 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800982 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100983 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800984 "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 +0100985 server_port_str);
986 return usage();
987 }
988 }
989
990 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -0800991 while (argc > 0) {
992 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100993 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800994 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800995 no_daemon = 1;
996 } else if (!strcmp(argv[0], "fork-server")) {
997 /* this is a special flag used only when the ADB client launches the ADB Server */
998 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800999 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001001 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001002 const char *product = NULL;
1003 if (argv[0][2] == '\0') {
1004 if (argc < 2) return usage();
1005 product = argv[1];
1006 argc--;
1007 argv++;
1008 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001009 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001010 }
1011 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001012 if (gProductOutPath.empty()) {
1013 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001014 return usage();
1015 }
1016 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1017 if (isdigit(argv[0][2])) {
1018 serial = argv[0] + 2;
1019 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001020 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001021 serial = argv[1];
1022 argc--;
1023 argv++;
1024 }
1025 } else if (!strcmp(argv[0],"-d")) {
1026 ttype = kTransportUsb;
1027 } else if (!strcmp(argv[0],"-e")) {
1028 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001029 } else if (!strcmp(argv[0],"-a")) {
1030 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001031 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001032 const char *hostname = NULL;
1033 if (argv[0][2] == '\0') {
1034 if (argc < 2) return usage();
1035 hostname = argv[1];
1036 argc--;
1037 argv++;
1038 } else {
1039 hostname = argv[0] + 2;
1040 }
1041 adb_set_tcp_name(hostname);
1042
Riley Andrews98f58e82014-12-05 17:37:24 -08001043 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001044 if (argv[0][2] == '\0') {
1045 if (argc < 2) return usage();
1046 server_port_str = argv[1];
1047 argc--;
1048 argv++;
1049 } else {
1050 server_port_str = argv[0] + 2;
1051 }
1052 if (strlen(server_port_str) > 0) {
1053 server_port = (int) strtol(server_port_str, NULL, 0);
1054 if (server_port <= 0 || server_port > 65535) {
1055 fprintf(stderr,
1056 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1057 server_port_str);
1058 return usage();
1059 }
1060 } else {
1061 fprintf(stderr,
1062 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1063 return usage();
1064 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001065 } else {
1066 /* out of recognized modifiers and flags */
1067 break;
1068 }
1069 argc--;
1070 argv++;
1071 }
1072
1073 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001074 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001075
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001076 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001077 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001078 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001079 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001080 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001081 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001082 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001083 fprintf(stderr,"* could not start server *\n");
1084 }
1085 return r;
1086 }
1087
Riley Andrews98f58e82014-12-05 17:37:24 -08001088 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001089 return usage();
1090 }
1091
Riley Andrewsc8514c82014-12-05 17:32:46 -08001092 /* handle wait-for-* prefix */
1093 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001094 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001095
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001096 if (!wait_for_device(service, ttype, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001097 return 1;
1098 }
1099
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001100 // Allow a command to be run after wait-for-device,
1101 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001102 if (argc == 1) {
1103 return 0;
1104 }
1105
1106 /* Fall through */
1107 argc--;
1108 argv++;
1109 }
1110
1111 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001112 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001113 const char *listopt;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001114 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001115 listopt = "";
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001116 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001117 listopt = argv[1];
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001118 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001119 fprintf(stderr, "Usage: adb devices [-l]\n");
1120 return 1;
1121 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001122
1123 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1124 printf("List of devices attached\n");
1125 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001126 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001127 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001128 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001129 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001130 return 1;
1131 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001132
1133 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1134 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001135 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001136 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001137 if (argc > 2) {
1138 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1139 return 1;
1140 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001141
1142 std::string query = android::base::StringPrintf("host:disconnect:%s",
1143 (argc == 2) ? argv[1] : "");
1144 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001145 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001146 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001147 return adb_send_emulator_command(argc, argv);
1148 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001149 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001150 char h = (argv[0][0] == 'h');
1151
1152 if (h) {
1153 printf("\x1b[41;33m");
1154 fflush(stdout);
1155 }
1156
Riley Andrews98f58e82014-12-05 17:37:24 -08001157 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001158 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001159 r = interactive_shell();
1160 if (h) {
1161 printf("\x1b[0m");
1162 fflush(stdout);
1163 }
1164 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001165 }
1166
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001167 std::string cmd = "shell:";
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001168 --argc;
1169 ++argv;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001170 while (argc-- > 0) {
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001171 // We don't escape here, just like ssh(1). http://b/20564385.
1172 cmd += *argv++;
1173 if (*argv) cmd += " ";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001174 }
1175
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001176 while (true) {
1177 D("interactive shell loop. cmd=%s\n", cmd.c_str());
Elliott Hughes71aeb792015-04-29 08:35:59 -07001178 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001179 int fd = adb_connect(cmd, &error);
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001180 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001181 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001182 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001183 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001184 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001185 adb_close(fd);
1186 r = 0;
1187 } else {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001188 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 r = -1;
1190 }
1191
Riley Andrews98f58e82014-12-05 17:37:24 -08001192 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001193 fprintf(stderr,"\n- waiting for device -\n");
1194 adb_sleep_ms(1000);
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001195 wait_for_device("wait-for-device", ttype, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001196 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001197 if (h) {
1198 printf("\x1b[0m");
1199 fflush(stdout);
1200 }
JP Abgrall408fa572011-03-16 15:57:42 -07001201 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001202 return r;
1203 }
1204 }
1205 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001206 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001207 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001208
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001209 std::string cmd = "exec:";
1210 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001211 argc -= 2;
1212 argv += 2;
1213 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001214 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001215 }
1216
Elliott Hughes71aeb792015-04-29 08:35:59 -07001217 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001218 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001219 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001220 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001221 return -1;
1222 }
1223
1224 if (exec_in) {
1225 copy_to_file(STDIN_FILENO, fd);
1226 } else {
1227 copy_to_file(fd, STDOUT_FILENO);
1228 }
1229
1230 adb_close(fd);
1231 return 0;
1232 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001233 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001234 std::string error;
1235 int fd = _adb_connect("host:kill", &error);
Riley Andrews98f58e82014-12-05 17:37:24 -08001236 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001237 fprintf(stderr,"* server not running *\n");
1238 return 1;
1239 }
1240 return 0;
1241 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001242 else if (!strcmp(argv[0], "sideload")) {
1243 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001244 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001245 return 1;
1246 } else {
1247 return 0;
1248 }
1249 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001250 else if (!strcmp(argv[0], "remount") ||
1251 !strcmp(argv[0], "reboot") ||
1252 !strcmp(argv[0], "reboot-bootloader") ||
1253 !strcmp(argv[0], "tcpip") ||
1254 !strcmp(argv[0], "usb") ||
1255 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001256 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001257 !strcmp(argv[0], "disable-verity") ||
1258 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001259 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001260 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001261 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001262 } else if (argc > 1) {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001263 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001264 } else {
Elliott Hughes207ddb22015-05-07 23:37:40 -07001265 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001266 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001267 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001268 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001269 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001270 if (argc != 1) return usage();
Elliott Hughesaceb9c02015-05-04 19:29:32 -07001271 return send_shell_command(ttype, serial, "shell:bugreport");
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001272 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001273 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001274 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughese1a55002015-05-01 17:04:38 -07001275 std::string cmd;
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001276 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001277 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001278 char remove = 0;
1279 char remove_all = 0;
1280 char list = 0;
1281 char no_rebind = 0;
1282
1283 // Parse options here.
1284 while (argc > 1 && argv[1][0] == '-') {
1285 if (!strcmp(argv[1], "--list"))
1286 list = 1;
1287 else if (!strcmp(argv[1], "--remove"))
1288 remove = 1;
1289 else if (!strcmp(argv[1], "--remove-all"))
1290 remove_all = 1;
1291 else if (!strcmp(argv[1], "--no-rebind"))
1292 no_rebind = 1;
1293 else {
1294 return usage();
1295 }
1296 argc--;
1297 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001298 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001299
1300 // Ensure we can only use one option at a time.
1301 if (list + remove + remove_all + no_rebind > 1) {
1302 return usage();
1303 }
1304
1305 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001306 if (reverse) {
1307 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001308 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001309 if (serial) {
1310 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1311 serial);
1312 } else if (ttype == kTransportUsb) {
1313 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1314 } else if (ttype == kTransportLocal) {
1315 snprintf(host_prefix, sizeof host_prefix, "host-local");
1316 } else {
1317 snprintf(host_prefix, sizeof host_prefix, "host");
1318 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001319 }
1320
1321 // Implement forward --list
1322 if (list) {
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001323 if (argc != 1) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001324 return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001325 }
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001326
1327 std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
1328 return adb_query_command(query);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001329 }
1330
1331 // Implement forward --remove-all
1332 else if (remove_all) {
Elliott Hughese1a55002015-05-01 17:04:38 -07001333 if (argc != 1) return usage();
1334 cmd = android::base::StringPrintf("%s:killforward-all", host_prefix);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001335 }
1336
1337 // Implement forward --remove <local>
1338 else if (remove) {
Elliott Hughese1a55002015-05-01 17:04:38 -07001339 if (argc != 2) return usage();
1340 cmd = android::base::StringPrintf("%s:killforward:%s", host_prefix, argv[1]);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001341 }
1342 // Or implement one of:
1343 // forward <local> <remote>
1344 // forward --no-rebind <local> <remote>
Elliott Hughese1a55002015-05-01 17:04:38 -07001345 else {
1346 if (argc != 3) return usage();
1347 const char* command = no_rebind ? "forward:norebind" : "forward";
1348 cmd = android::base::StringPrintf("%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001349 }
1350
Elliott Hughes71aeb792015-04-29 08:35:59 -07001351 std::string error;
Elliott Hughese1a55002015-05-01 17:04:38 -07001352 if (adb_command(cmd, &error)) {
1353 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001354 return 1;
1355 }
1356 return 0;
1357 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001358 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001359 else if (!strcmp(argv[0], "ls")) {
1360 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001361 return do_sync_ls(argv[1]);
1362 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001363 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001364 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001365 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001366 const char* lpath = NULL, *rpath = NULL;
1367
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001368 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001369
1370 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001371 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001372 }
1373
1374 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001375 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001376 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001377 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001378 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001379 const char* rpath = NULL, *lpath = ".";
1380
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001381 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001382
1383 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001384 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001385 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001386
1387 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001388 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001389 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 if (argc < 2) return usage();
1391 return install_app(ttype, serial, argc, argv);
1392 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001393 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001394 if (argc < 2) return usage();
1395 return install_multiple_app(ttype, serial, argc, argv);
1396 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001397 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001398 if (argc < 2) return usage();
1399 return uninstall_app(ttype, serial, argc, argv);
1400 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001401 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001402 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001403 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001404 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001405 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001406 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001407 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001408 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001409 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001410 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001411 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001412 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001413 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001414 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001415 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001416 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001417 } else {
1418 return usage();
1419 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001420
Elliott Hughesd236d072015-04-21 10:17:07 -07001421 if (src != "" &&
1422 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001423 return usage();
1424 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425
Elliott Hughes58305772015-04-17 13:57:15 -07001426 std::string system_src_path = product_file("system");
1427 std::string data_src_path = product_file("data");
1428 std::string vendor_src_path = product_file("vendor");
1429 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001430
1431 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001432 if (rc == 0 && (src.empty() || src == "system")) {
1433 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001434 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001435 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1436 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001437 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001438 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1439 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001440 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001441 if (rc == 0 && (src.empty() || src == "data")) {
1442 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001443 }
1444 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001445 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001446 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001447 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001448 !strcmp(argv[0],"get-serialno") ||
1449 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001450 {
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001451 return adb_query_command(format_host_command(argv[0], ttype, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001452 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001453 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001454 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001455 return logcat(ttype, serial, argc, argv);
1456 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001457 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001458 return ppp(argc, argv);
1459 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001460 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001461 std::string error;
1462 return adb_connect("host:start-server", &error);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001463 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001464 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001465 return backup(argc, argv);
1466 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001467 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001468 return restore(argc, argv);
1469 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001470 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001471 if (argc < 2) return usage();
1472 return adb_auth_keygen(argv[1]);
1473 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001474 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001475 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001476 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001478 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001479 help();
1480 return 0;
1481 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001482 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001483 version(stdout);
1484 return 0;
1485 }
1486
1487 usage();
1488 return 1;
1489}
1490
Dan Albertbac34742015-02-25 17:51:28 -08001491static int pm_command(transport_type transport, const char* serial,
1492 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001493{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001494 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001495
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001496 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001497 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001498 }
1499
Elliott Hughes15551472015-04-21 17:58:55 -07001500 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001501}
1502
Elliott Hughes58305772015-04-17 13:57:15 -07001503static int uninstall_app(transport_type transport, const char* serial, int argc,
1504 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001505{
1506 /* if the user choose the -k option, we refuse to do it until devices are
1507 out with the option to uninstall the remaining data somehow (adb/ui) */
1508 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1509 {
1510 printf(
1511 "The -k option uninstalls the application while retaining the data/cache.\n"
1512 "At the moment, there is no way to remove the remaining data.\n"
1513 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1514 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1515 return -1;
1516 }
1517
1518 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1519 return pm_command(transport, serial, argc, argv);
1520}
1521
Dan Albertbac34742015-02-25 17:51:28 -08001522static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001523{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001524 std::string cmd = "shell:rm -f " + escape_arg(filename);
Elliott Hughes15551472015-04-21 17:58:55 -07001525 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001526}
1527
Kenny Root597ea5b2011-08-05 11:19:45 -07001528static const char* get_basename(const char* filename)
1529{
1530 const char* basename = adb_dirstop(filename);
1531 if (basename) {
1532 basename++;
1533 return basename;
1534 } else {
1535 return filename;
1536 }
1537}
1538
Elliott Hughes58305772015-04-17 13:57:15 -07001539static int install_app(transport_type transport, const char* serial, int argc,
1540 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001541{
1542 static const char *const DATA_DEST = "/data/local/tmp/%s";
1543 static const char *const SD_DEST = "/sdcard/tmp/%s";
1544 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001545 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001546 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001547
1548 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001549 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001550 where = SD_DEST;
1551 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001552 }
1553
Jeff Sharkey960df972014-06-09 17:30:57 -07001554 // Find last APK argument.
1555 // All other arguments passed through verbatim.
1556 int last_apk = -1;
1557 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001558 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001559 char* dot = strrchr(file, '.');
1560 if (dot && !strcasecmp(dot, ".apk")) {
1561 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1562 fprintf(stderr, "Invalid APK file: %s\n", file);
1563 return -1;
1564 }
1565
1566 last_apk = i;
1567 break;
1568 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001569 }
1570
Jeff Sharkey960df972014-06-09 17:30:57 -07001571 if (last_apk == -1) {
1572 fprintf(stderr, "Missing APK file\n");
1573 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001574 }
1575
Dan Albertbac34742015-02-25 17:51:28 -08001576 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001577 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001578 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001579 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001580 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001581 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001582 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001583 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001584 }
1585
Elliott Hughes15551472015-04-21 17:58:55 -07001586 err = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001587
Kenny Root60733e92012-03-26 16:14:02 -07001588cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001589 delete_file(transport, serial, apk_dest);
1590 return err;
1591}
1592
Elliott Hughes58305772015-04-17 13:57:15 -07001593static int install_multiple_app(transport_type transport, const char* serial, int argc,
1594 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001595{
Jeff Sharkey960df972014-06-09 17:30:57 -07001596 int i;
1597 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001598 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001599
1600 // Find all APK arguments starting at end.
1601 // All other arguments passed through verbatim.
1602 int first_apk = -1;
1603 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001604 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001605 char* dot = strrchr(file, '.');
1606 if (dot && !strcasecmp(dot, ".apk")) {
1607 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1608 fprintf(stderr, "Invalid APK file: %s\n", file);
1609 return -1;
1610 }
1611
1612 total_size += sb.st_size;
1613 first_apk = i;
1614 } else {
1615 break;
1616 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001617 }
1618
Jeff Sharkey960df972014-06-09 17:30:57 -07001619 if (first_apk == -1) {
1620 fprintf(stderr, "Missing APK file\n");
1621 return 1;
1622 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001623
Elliott Hughes53daee62015-04-19 13:17:01 -07001624#if defined(_WIN32) // Remove when we're using clang for Win32.
1625 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
1626#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001627 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Elliott Hughes53daee62015-04-19 13:17:01 -07001628#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001629 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001630 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001631 }
1632
1633 // Create install session
Elliott Hughes71aeb792015-04-29 08:35:59 -07001634 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001635 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001636 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001637 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001638 return -1;
1639 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001640 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001641 read_status_line(fd, buf, sizeof(buf));
1642 adb_close(fd);
1643
1644 int session_id = -1;
1645 if (!strncmp("Success", buf, 7)) {
1646 char* start = strrchr(buf, '[');
1647 char* end = strrchr(buf, ']');
1648 if (start && end) {
1649 *end = '\0';
1650 session_id = strtol(start + 1, NULL, 10);
1651 }
1652 }
1653 if (session_id < 0) {
1654 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001655 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001656 return -1;
1657 }
1658
1659 // Valid session, now stream the APKs
1660 int success = 1;
1661 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001662 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001663 if (stat(file, &sb) == -1) {
1664 fprintf(stderr, "Failed to stat %s\n", file);
1665 success = 0;
1666 goto finalize_session;
1667 }
1668
Elliott Hughes53daee62015-04-19 13:17:01 -07001669#if defined(_WIN32) // Remove when we're using clang for Win32.
1670 std::string cmd = android::base::StringPrintf(
1671 "exec:pm install-write -S %u %d %d_%s -",
1672 (unsigned) sb.st_size, session_id, i, get_basename(file));
1673#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001674 std::string cmd = android::base::StringPrintf(
1675 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1676 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Elliott Hughes53daee62015-04-19 13:17:01 -07001677#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001678
1679 int localFd = adb_open(file, O_RDONLY);
1680 if (localFd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001681 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001682 success = 0;
1683 goto finalize_session;
1684 }
1685
Elliott Hughes71aeb792015-04-29 08:35:59 -07001686 std::string error;
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001687 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001688 if (remoteFd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001689 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001690 adb_close(localFd);
1691 success = 0;
1692 goto finalize_session;
1693 }
1694
1695 copy_to_file(localFd, remoteFd);
1696 read_status_line(remoteFd, buf, sizeof(buf));
1697
1698 adb_close(localFd);
1699 adb_close(remoteFd);
1700
1701 if (strncmp("Success", buf, 7)) {
1702 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001703 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001704 success = 0;
1705 goto finalize_session;
1706 }
1707 }
1708
1709finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001710 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughesf1a58f82015-04-29 12:28:13 -07001711 std::string service =
1712 android::base::StringPrintf("exec:pm install-%s %d",
1713 success ? "commit" : "abandon", session_id);
1714 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001715 if (fd < 0) {
Elliott Hughes71aeb792015-04-29 08:35:59 -07001716 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001717 return -1;
1718 }
1719 read_status_line(fd, buf, sizeof(buf));
1720 adb_close(fd);
1721
1722 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001723 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001724 return 0;
1725 } else {
1726 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001727 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001728 return -1;
1729 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001730}