blob: 603ea094610e05c46f6b98d7ba4cb2a905d4e756 [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
Dan Albertbac34742015-02-25 17:51:28 -080050static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080051
Elliott Hughes58305772015-04-17 13:57:15 -070052static int install_app(transport_type transport, const char* serial, int argc,
53 const char** argv);
54static int install_multiple_app(transport_type transport, const char* serial, int argc,
55 const char** argv);
56static int uninstall_app(transport_type transport, const char* serial, int argc,
Dan Albertbac34742015-02-25 17:51:28 -080057 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Elliott Hughes58305772015-04-17 13:57:15 -070059static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080060extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080061
Elliott Hughes58305772015-04-17 13:57:15 -070062static std::string product_file(const char *extra) {
63 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080064 fprintf(stderr, "adb: Product directory not specified; "
65 "use -p or define ANDROID_PRODUCT_OUT\n");
66 exit(1);
67 }
68
Elliott Hughes58305772015-04-17 13:57:15 -070069 return android::base::StringPrintf("%s%s%s",
70 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
72
Elliott Hughes58305772015-04-17 13:57:15 -070073static void version(FILE* out) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
Elliott Hughes58305772015-04-17 13:57:15 -070075 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080076}
77
Elliott Hughes58305772015-04-17 13:57:15 -070078static void help() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 version(stderr);
80
81 fprintf(stderr,
82 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080083 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080084 " -d - directs command to the only connected USB device\n"
85 " returns an error if more than one USB device is present.\n"
86 " -e - directs command to the only running emulator.\n"
87 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070088 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070089 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070090 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080091 " -p <product name or path> - simple product name like 'sooner', or\n"
92 " a relative/absolute path to a product\n"
93 " out directory like 'out/target/product/sooner'.\n"
94 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
95 " environment variable is used, which must\n"
96 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080097 " -H - Name of adb server host (default: localhost)\n"
98 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070099 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700100 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400101 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
102 " Port 5555 is used by default if no port number is specified.\n"
103 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
104 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200105 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400106 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107 "\n"
108 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700109 " adb push [-p] <local> <remote>\n"
110 " - copy file/dir to device\n"
111 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700112 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700113 " - copy file/dir from device\n"
114 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700115 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800116 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600117 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 " (see 'adb help all')\n"
119 " adb shell - run remote shell interactively\n"
120 " adb shell <command> - run remote shell command\n"
121 " adb emu <command> - run emulator console command\n"
122 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100123 " adb forward --list - list all forward socket connections.\n"
124 " the format is a list of lines with the following format:\n"
125 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 " adb forward <local> <remote> - forward socket connections\n"
127 " forward specs are one of: \n"
128 " tcp:<port>\n"
129 " localabstract:<unix domain socket name>\n"
130 " localreserved:<unix domain socket name>\n"
131 " localfilesystem:<unix domain socket name>\n"
132 " dev:<character device name>\n"
133 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100134 " adb forward --no-rebind <local> <remote>\n"
135 " - same as 'adb forward <local> <remote>' but fails\n"
136 " if <local> is already forwarded\n"
137 " adb forward --remove <local> - remove a specific forward socket connection\n"
138 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100139 " adb reverse --list - list all reverse socket connections from device\n"
140 " adb reverse <remote> <local> - reverse socket connections\n"
141 " reverse specs are one of:\n"
142 " tcp:<port>\n"
143 " localabstract:<unix domain socket name>\n"
144 " localreserved:<unix domain socket name>\n"
145 " localfilesystem:<unix domain socket name>\n"
146 " adb reverse --norebind <remote> <local>\n"
147 " - same as 'adb reverse <remote> <local>' but fails\n"
148 " if <remote> is already reversed.\n"
149 " adb reverse --remove <remote>\n"
150 " - remove a specific reversed socket connection\n"
151 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800152 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700153 " adb install [-lrtsd] <file>\n"
154 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700155 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700156 " (-l: forward lock application)\n"
157 " (-r: replace existing application)\n"
158 " (-t: allow test packages)\n"
159 " (-s: install application on sdcard)\n"
160 " (-d: allow version code downgrade)\n"
161 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 " adb uninstall [-k] <package> - remove this app package from the device\n"
163 " ('-k' means keep the data and cache directories)\n"
164 " adb bugreport - return all information from the device\n"
165 " that should be included in a bug report.\n"
166 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800167 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700168 " - write an archive of the device's data to <file>.\n"
169 " If no -f option is supplied then the data is written\n"
170 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700171 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700172 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800173 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
174 " (aka .obb) files associated with each application; the default\n"
175 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (-shared|-noshared enable/disable backup of the device's\n"
177 " shared storage / SD card contents; the default is noshared.)\n"
178 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700179 " (-system|-nosystem toggles whether -all automatically includes\n"
180 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (<packages...> is the list of applications to be backed up. If\n"
182 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700183 " list is optional. Applications explicitly given on the\n"
184 " command line will be included even if -nosystem would\n"
185 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700187 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700188 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800189 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
190 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800191 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
192 " and the public key is stored in <file>.pub. Any existing files\n"
193 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800194 " adb help - show this help message\n"
195 " adb version - show version num\n"
196 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 "scripting:\n"
198 " adb wait-for-device - block until device is online\n"
199 " adb start-server - ensure that there is a server running\n"
200 " adb kill-server - kill the server if it is running\n"
201 " adb get-state - prints: offline | bootloader | device\n"
202 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700203 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000205 " 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 -0700206 " adb reboot [bootloader|recovery]\n"
207 " - reboots the device, optionally into the bootloader or recovery program.\n"
208 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
209 " adb reboot sideload-auto-reboot\n"
210 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800211 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700212 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500213 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800214 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000215 " 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 -0800216 "networking:\n"
217 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500218 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800219 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
220 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
221 "\n"
222 "adb sync notes: adb sync [ <directory> ]\n"
223 " <localdir> can be interpreted in several ways:\n"
224 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000225 " - 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 -0800226 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000227 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000229 "\n"
230 "environmental variables:\n"
231 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
232 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
233 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
234 " 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 -0800235 );
236}
237
Elliott Hughes58305772015-04-17 13:57:15 -0700238static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 help();
240 return 1;
241}
242
Yabin Cuid325e862014-11-17 14:48:25 -0800243#if defined(_WIN32)
244
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700245// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800246void stdin_raw_init(int fd);
247void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800248
249#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100250static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100252static void stdin_raw_init(int fd) {
253 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800254
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100255 termios tio;
256 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100258 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261 tio.c_cc[VTIME] = 0;
262 tio.c_cc[VMIN] = 1;
263
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100264 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265}
266
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100267static void stdin_raw_restore(int fd) {
268 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269}
270#endif
271
272static void read_and_dump(int fd)
273{
274 char buf[4096];
275 int len;
276
277 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700278 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800279 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700280 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 if(len == 0) {
282 break;
283 }
284
285 if(len < 0) {
286 if(errno == EINTR) continue;
287 break;
288 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400289 fwrite(buf, 1, len, stdout);
290 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 }
292}
293
Jeff Sharkey960df972014-06-09 17:30:57 -0700294static void read_status_line(int fd, char* buf, size_t count)
295{
296 count--;
297 while (count > 0) {
298 int len = adb_read(fd, buf, count);
299 if (len == 0) {
300 break;
301 } else if (len < 0) {
302 if (errno == EINTR) continue;
303 break;
304 }
305
306 buf += len;
307 count -= len;
308 }
309 *buf = '\0';
310}
311
Christopher Tated2f54152011-04-21 12:53:28 -0700312static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700313 const size_t BUFSIZE = 32 * 1024;
314 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700315 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700316 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700317
318 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800319
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700320 if (inFd == STDIN_FILENO) {
321 stdin_raw_init(STDIN_FILENO);
322 }
Yabin Cuid325e862014-11-17 14:48:25 -0800323
Christopher Tated2f54152011-04-21 12:53:28 -0700324 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700325 if (inFd == STDIN_FILENO) {
326 len = unix_read(inFd, buf, BUFSIZE);
327 } else {
328 len = adb_read(inFd, buf, BUFSIZE);
329 }
Christopher Tated2f54152011-04-21 12:53:28 -0700330 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700331 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700332 break;
333 }
334 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700335 if (errno == EINTR) {
336 D("copy_to_file() : EINTR, retrying\n");
337 continue;
338 }
Christopher Tated2f54152011-04-21 12:53:28 -0700339 D("copy_to_file() : error %d\n", errno);
340 break;
341 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700342 if (outFd == STDOUT_FILENO) {
343 fwrite(buf, 1, len, stdout);
344 fflush(stdout);
345 } else {
346 adb_write(outFd, buf, len);
347 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700348 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700349 }
Yabin Cuid325e862014-11-17 14:48:25 -0800350
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700351 if (inFd == STDIN_FILENO) {
352 stdin_raw_restore(STDIN_FILENO);
353 }
Yabin Cuid325e862014-11-17 14:48:25 -0800354
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700355 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700356 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700357}
358
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359static void *stdin_read_thread(void *x)
360{
361 int fd, fdi;
362 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800363 int r, n;
364 int state = 0;
365
366 int *fds = (int*) x;
367 fd = fds[0];
368 fdi = fds[1];
369 free(fds);
370
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371 for(;;) {
372 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700373 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700375 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800376 if(r == 0) break;
377 if(r < 0) {
378 if(errno == EINTR) continue;
379 break;
380 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400381 for(n = 0; n < r; n++){
382 switch(buf[n]) {
383 case '\n':
384 state = 1;
385 break;
386 case '\r':
387 state = 1;
388 break;
389 case '~':
390 if(state == 1) state++;
391 break;
392 case '.':
393 if(state == 2) {
394 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400395 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400396 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400398 default:
399 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402 r = adb_write(fd, buf, r);
403 if(r <= 0) {
404 break;
405 }
406 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 return 0;
408}
409
Elliott Hughes58305772015-04-17 13:57:15 -0700410static int interactive_shell() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 adb_thread_t thr;
412 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413
414 fd = adb_connect("shell:");
415 if(fd < 0) {
416 fprintf(stderr,"error: %s\n", adb_error());
417 return 1;
418 }
419 fdi = 0; //dup(0);
420
Dan Albertbac34742015-02-25 17:51:28 -0800421 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800422 fds[0] = fd;
423 fds[1] = fdi;
424
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426 adb_thread_create(&thr, stdin_read_thread, fds);
427 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800429 return 0;
430}
431
432
433static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
434{
435 if (serial) {
436 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
437 } else {
438 const char* prefix = "host";
439 if (ttype == kTransportUsb)
440 prefix = "host-usb";
441 else if (ttype == kTransportLocal)
442 prefix = "host-local";
443
444 snprintf(buffer, buflen, "%s:%s", prefix, command);
445 }
446}
447
Elliott Hughes58305772015-04-17 13:57:15 -0700448static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
449 unsigned progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800450{
451 char buf[4096];
452 unsigned total;
453 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800454
455 sprintf(buf,"%s:%d", service, sz);
456 fd = adb_connect(buf);
457 if(fd < 0) {
458 fprintf(stderr,"error: %s\n", adb_error());
459 return -1;
460 }
461
462 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800463 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800464
465 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800466 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800467
468 if(progress) {
469 char *x = strrchr(service, ':');
470 if(x) service = x + 1;
471 }
472
473 while(sz > 0) {
474 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800475 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800476 adb_status(fd);
477 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
478 return -1;
479 }
480 sz -= xfer;
481 ptr += xfer;
482 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100483 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800484 fflush(stdout);
485 }
486 }
487 if(progress) {
488 printf("\n");
489 }
490
Dan Albertcc731cc2015-02-24 21:26:58 -0800491 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800492 fprintf(stderr,"* error reading response *\n");
493 adb_close(fd);
494 return -1;
495 }
496 if(memcmp(buf, "OKAY", 4)) {
497 buf[4] = 0;
498 fprintf(stderr,"* error response '%s' *\n", buf);
499 adb_close(fd);
500 return -1;
501 }
502
503 adb_close(fd);
504 return 0;
505}
506
Doug Zongker71fe5842014-06-26 15:35:36 -0700507#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
508
509/*
510 * The sideload-host protocol serves the data in a file (given on the
511 * command line) to the client, using a simple protocol:
512 *
513 * - The connect message includes the total number of bytes in the
514 * file and a block size chosen by us.
515 *
516 * - The other side sends the desired block number as eight decimal
517 * digits (eg "00000023" for block 23). Blocks are numbered from
518 * zero.
519 *
520 * - We send back the data of the requested block. The last block is
521 * likely to be partial; when the last block is requested we only
522 * send the part of the block that exists, it's not padded up to the
523 * block size.
524 *
525 * - When the other side sends "DONEDONE" instead of a block number,
526 * we hang up.
527 */
Elliott Hughes58305772015-04-17 13:57:15 -0700528static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700529 unsigned sz;
530 size_t xfer = 0;
531 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800532 int last_percent = -1;
533 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700534
535 printf("loading: '%s'", fn);
536 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800537 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700538 if (data == 0) {
539 printf("\n");
540 fprintf(stderr, "* cannot read '%s' *\n", fn);
541 return -1;
542 }
543
544 char buf[100];
545 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
546 int fd = adb_connect(buf);
547 if (fd < 0) {
548 // Try falling back to the older sideload method. Maybe this
549 // is an older device that doesn't support sideload-host.
550 printf("\n");
551 status = adb_download_buffer("sideload", fn, data, sz, 1);
552 goto done;
553 }
554
Spencer Lowf055c192015-01-25 14:40:16 -0800555 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700556
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700557 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800558 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700559 fprintf(stderr, "* failed to read command: %s\n", adb_error());
560 status = -1;
561 goto done;
562 }
563
564 if (strncmp("DONEDONE", buf, 8) == 0) {
565 status = 0;
566 break;
567 }
568
569 buf[8] = '\0';
570 int block = strtol(buf, NULL, 10);
571
572 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
573 if (offset >= sz) {
574 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
575 status = -1;
576 goto done;
577 }
578 uint8_t* start = data + offset;
579 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
580 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
581 if (offset_end > sz) {
582 to_write = sz - offset;
583 }
584
Dan Albertcc731cc2015-02-24 21:26:58 -0800585 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700586 adb_status(fd);
587 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
588 status = -1;
589 goto done;
590 }
591 xfer += to_write;
592
593 // For normal OTA packages, we expect to transfer every byte
594 // twice, plus a bit of overhead (one read during
595 // verification, one read of each byte for installation, plus
596 // extra access to things like the zip central directory).
597 // This estimate of the completion becomes 100% when we've
598 // transferred ~2.13 (=100/47) times the package size.
599 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
600 if (percent != last_percent) {
601 printf("\rserving: '%s' (~%d%%) ", fn, percent);
602 fflush(stdout);
603 last_percent = percent;
604 }
605 }
606
Colin Cross6d6a8982014-07-07 14:12:41 -0700607 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700608
609 done:
610 if (fd >= 0) adb_close(fd);
611 free(data);
612 return status;
613}
614
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800615static void status_window(transport_type ttype, const char* serial)
616{
617 char command[4096];
618 char *state = 0;
619 char *laststate = 0;
620
621 /* silence stderr */
622#ifdef _WIN32
623 /* XXX: TODO */
624#else
625 int fd;
626 fd = unix_open("/dev/null", O_WRONLY);
627 dup2(fd, 2);
628 adb_close(fd);
629#endif
630
631 format_host_command(command, sizeof command, "get-state", ttype, serial);
632
633 for(;;) {
634 adb_sleep_ms(250);
635
636 if(state) {
637 free(state);
638 state = 0;
639 }
640
641 state = adb_query(command);
642
643 if(state) {
644 if(laststate && !strcmp(state,laststate)){
645 continue;
646 } else {
647 if(laststate) free(laststate);
648 laststate = strdup(state);
649 }
650 }
651
652 printf("%c[2J%c[2H", 27, 27);
653 printf("Android Debug Bridge\n");
654 printf("State: %s\n", state ? state : "offline");
655 fflush(stdout);
656 }
657}
658
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800659/**
660 * Run ppp in "notty" mode against a resource listed as the first parameter
661 * eg:
662 *
663 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
664 *
665 */
Elliott Hughes58305772015-04-17 13:57:15 -0700666static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800667#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800668 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
669 return -1;
670#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800671 pid_t pid;
672 int fd;
673
674 if (argc < 2) {
675 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
676 argv[0]);
677
678 return 1;
679 }
680
Dan Albertbac34742015-02-25 17:51:28 -0800681 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 fd = adb_connect(adb_service_name);
683
684 if(fd < 0) {
685 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
686 adb_service_name, adb_error());
687 return 1;
688 }
689
690 pid = fork();
691
692 if (pid < 0) {
693 perror("from fork()");
694 return 1;
695 } else if (pid == 0) {
696 int err;
697 int i;
698 const char **ppp_args;
699
700 // copy args
701 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
702 ppp_args[0] = "pppd";
703 for (i = 2 ; i < argc ; i++) {
704 //argv[2] and beyond become ppp_args[1] and beyond
705 ppp_args[i - 1] = argv[i];
706 }
707 ppp_args[i-1] = NULL;
708
709 // child side
710
711 dup2(fd, STDIN_FILENO);
712 dup2(fd, STDOUT_FILENO);
713 adb_close(STDERR_FILENO);
714 adb_close(fd);
715
716 err = execvp("pppd", (char * const *)ppp_args);
717
718 if (err < 0) {
719 perror("execing pppd");
720 }
721 exit(-1);
722 } else {
723 // parent side
724
725 adb_close(fd);
726 return 0;
727 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800728#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800729}
730
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700731static int send_shell_command(transport_type transport, const char* serial,
732 const std::string& command) {
733 int fd;
734 while (true) {
735 fd = adb_connect(command.c_str());
736 if (fd >= 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800737 break;
738 fprintf(stderr,"- waiting for device -\n");
739 adb_sleep_ms(1000);
740 do_cmd(transport, serial, "wait-for-device", 0);
741 }
742
743 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700744 int rc = adb_close(fd);
745 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800746 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700747 }
748 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749}
750
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700751static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
752 char* log_tags = getenv("ANDROID_LOG_TAGS");
753 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800754
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700755 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800756
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700757 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700758 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800759 }
760
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800761 argc -= 1;
762 argv += 1;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700763 while (argc-- > 0) {
764 cmd += " ";
765 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800766 }
767
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700768 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800769 return 0;
770}
771
Mark Salyzyn60299df2014-04-30 09:10:31 -0700772static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800773{
774 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700775 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800776
777 for(;;) {
778 x = adb_dirstart(x);
779 if(x == 0) return 0;
780 *x = 0;
781 ret = adb_mkdir(path, 0775);
782 *x = OS_PATH_SEPARATOR;
783 if((ret < 0) && (errno != EEXIST)) {
784 return ret;
785 }
786 x++;
787 }
788 return 0;
789}
790
Dan Albertbac34742015-02-25 17:51:28 -0800791static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700792 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800793 char default_name[32];
794 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700795 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700796 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700797
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700798 /* find, extract, and use any -f argument */
799 for (i = 1; i < argc; i++) {
800 if (!strcmp("-f", argv[i])) {
801 if (i == argc-1) {
802 fprintf(stderr, "adb: -f passed with no filename\n");
803 return usage();
804 }
805 filename = argv[i+1];
806 for (j = i+2; j <= argc; ) {
807 argv[i++] = argv[j++];
808 }
809 argc -= 2;
810 argv[argc] = NULL;
811 }
Christopher Tated2f54152011-04-21 12:53:28 -0700812 }
813
Christopher Tatebb86bc52011-08-22 17:12:08 -0700814 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
815 if (argc < 2) return usage();
816
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800817 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700818 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800819 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700820 if (outFd < 0) {
821 fprintf(stderr, "adb: unable to open file %s\n", filename);
822 return -1;
823 }
824
825 snprintf(buf, sizeof(buf), "backup");
826 for (argc--, argv++; argc; argc--, argv++) {
827 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
828 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
829 }
830
831 D("backup. filename=%s buf=%s\n", filename, buf);
832 fd = adb_connect(buf);
833 if (fd < 0) {
834 fprintf(stderr, "adb: unable to connect for backup\n");
835 adb_close(outFd);
836 return -1;
837 }
838
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800839 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700840 copy_to_file(fd, outFd);
841
842 adb_close(fd);
843 adb_close(outFd);
844 return 0;
845}
846
Dan Albertbac34742015-02-25 17:51:28 -0800847static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700848 const char* filename;
849 int fd, tarFd;
850
851 if (argc != 2) return usage();
852
853 filename = argv[1];
854 tarFd = adb_open(filename, O_RDONLY);
855 if (tarFd < 0) {
856 fprintf(stderr, "adb: unable to open file %s\n", filename);
857 return -1;
858 }
859
860 fd = adb_connect("restore:");
861 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700862 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700863 adb_close(tarFd);
864 return -1;
865 }
866
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800867 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700868 copy_to_file(tarFd, fd);
869
870 adb_close(fd);
871 adb_close(tarFd);
872 return 0;
873}
874
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800875#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
876static int top_works(const char *top)
877{
878 if (top != NULL && adb_is_absolute_host_path(top)) {
879 char path_buf[PATH_MAX];
880 snprintf(path_buf, sizeof(path_buf),
881 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
882 return access(path_buf, F_OK) == 0;
883 }
884 return 0;
885}
886
887static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
888{
889 strcpy(path_buf, indir);
890 while (1) {
891 if (top_works(path_buf)) {
892 return path_buf;
893 }
894 char *s = adb_dirstop(path_buf);
895 if (s != NULL) {
896 *s = '\0';
897 } else {
898 path_buf[0] = '\0';
899 return NULL;
900 }
901 }
902}
903
904static char *find_top(char path_buf[PATH_MAX])
905{
906 char *top = getenv("ANDROID_BUILD_TOP");
907 if (top != NULL && top[0] != '\0') {
908 if (!top_works(top)) {
909 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
910 return NULL;
911 }
912 } else {
913 top = getenv("TOP");
914 if (top != NULL && top[0] != '\0') {
915 if (!top_works(top)) {
916 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
917 return NULL;
918 }
919 } else {
920 top = NULL;
921 }
922 }
923
924 if (top != NULL) {
925 /* The environment pointed to a top directory that works.
926 */
927 strcpy(path_buf, top);
928 return path_buf;
929 }
930
931 /* The environment didn't help. Walk up the tree from the CWD
932 * to see if we can find the top.
933 */
934 char dir[PATH_MAX];
935 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
936 if (top == NULL) {
937 /* If the CWD isn't under a good-looking top, see if the
938 * executable is.
939 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100940 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800941 top = find_top_from(dir, path_buf);
942 }
943 return top;
944}
945
946/* <hint> may be:
947 * - A simple product name
948 * e.g., "sooner"
949TODO: debug? sooner-debug, sooner:debug?
950 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
951 * e.g., "out/target/product/sooner"
952 * - An absolute path to the PRODUCT_OUT dir
953 * e.g., "/src/device/out/target/product/sooner"
954 *
955 * Given <hint>, try to construct an absolute path to the
956 * ANDROID_PRODUCT_OUT dir.
957 */
Elliott Hughes58305772015-04-17 13:57:15 -0700958static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800959 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700960 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800961 }
962
Elliott Hughes58305772015-04-17 13:57:15 -0700963 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700965 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800966 }
967
Elliott Hughes58305772015-04-17 13:57:15 -0700968 // If there are any slashes in it, assume it's a relative path;
969 // make it absolute.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800970 if (adb_dirstart(hint) != NULL) {
Elliott Hughes58305772015-04-17 13:57:15 -0700971 char cwd[PATH_MAX];
972 if (getcwd(cwd, sizeof(cwd)) == NULL) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800973 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700974 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800975 }
Elliott Hughes58305772015-04-17 13:57:15 -0700976 return android::base::StringPrintf("%s%s%s", cwd, OS_PATH_SEPARATOR_STR, hint);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800977 }
978
Elliott Hughes58305772015-04-17 13:57:15 -0700979 // It's a string without any slashes. Try to do something with it.
980 //
981 // Try to find the root of the build tree, and build a PRODUCT_OUT
982 // path from there.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800983 char top_buf[PATH_MAX];
Elliott Hughes58305772015-04-17 13:57:15 -0700984 const char* top = find_top(top_buf);
985 if (top == nullptr) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800986 fprintf(stderr, "adb: Couldn't find top of build tree\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700987 return "";
988 }
989 std::string path = top_buf;
990 path += OS_PATH_SEPARATOR_STR;
991 path += "out";
992 path += OS_PATH_SEPARATOR_STR;
993 path += "target";
994 path += OS_PATH_SEPARATOR_STR;
995 path += "product";
996 path += OS_PATH_SEPARATOR_STR;
997 path += hint;
998 if (!directory_exists(path)) {
999 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
1000 "\"%s\" doesn't exist\n", hint, path.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001001 return NULL;
1002 }
Elliott Hughes58305772015-04-17 13:57:15 -07001003 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001004}
1005
Dan Albertbac34742015-02-25 17:51:28 -08001006static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1007 char const **path2, int *show_progress,
1008 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001009 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001010 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001011
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001012 while (narg > 0) {
1013 if (!strcmp(*arg, "-p")) {
1014 *show_progress = 1;
1015 } else if (!strcmp(*arg, "-a")) {
1016 *copy_attrs = 1;
1017 } else {
1018 break;
1019 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001020 ++arg;
1021 --narg;
1022 }
1023
1024 if (narg > 0) {
1025 *path1 = *arg;
1026 ++arg;
1027 --narg;
1028 }
1029
1030 if (narg > 0) {
1031 *path2 = *arg;
1032 }
1033}
1034
Tao Bao175b7bb2015-03-29 11:22:34 -07001035static int adb_connect_command(const char* command) {
1036 int fd = adb_connect(command);
1037 if (fd != -1) {
1038 read_and_dump(fd);
1039 adb_close(fd);
1040 return 0;
1041 }
1042 fprintf(stderr, "Error: %s\n", adb_error());
1043 return 1;
1044}
1045
Dan Albertbac34742015-02-25 17:51:28 -08001046int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001047{
1048 char buf[4096];
1049 int no_daemon = 0;
1050 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001051 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001052 int persist = 0;
1053 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001054 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001055 const char* serial = NULL;
1056 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001057
Elliott Hughes58305772015-04-17 13:57:15 -07001058 // If defined, this should be an absolute path to
1059 // the directory containing all of the various system images
1060 // for a particular product. If not defined, and the adb
1061 // command requires this information, then the user must
1062 // specify the path using "-p".
1063 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1064 if (ANDROID_PRODUCT_OUT != nullptr) {
1065 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001066 }
1067 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1068
Nick Pellydb449262009-05-07 12:48:03 -07001069 serial = getenv("ANDROID_SERIAL");
1070
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001071 /* Validate and assign the server port */
1072 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1073 int server_port = DEFAULT_ADB_PORT;
1074 if (server_port_str && strlen(server_port_str) > 0) {
1075 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001076 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001077 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001078 "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 +01001079 server_port_str);
1080 return usage();
1081 }
1082 }
1083
1084 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001085 while (argc > 0) {
1086 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001087 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001088 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001089 no_daemon = 1;
1090 } else if (!strcmp(argv[0], "fork-server")) {
1091 /* this is a special flag used only when the ADB client launches the ADB Server */
1092 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001093 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001094 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001095 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001096 const char *product = NULL;
1097 if (argv[0][2] == '\0') {
1098 if (argc < 2) return usage();
1099 product = argv[1];
1100 argc--;
1101 argv++;
1102 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001103 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001104 }
1105 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001106 if (gProductOutPath.empty()) {
1107 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001108 return usage();
1109 }
1110 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1111 if (isdigit(argv[0][2])) {
1112 serial = argv[0] + 2;
1113 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001114 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001115 serial = argv[1];
1116 argc--;
1117 argv++;
1118 }
1119 } else if (!strcmp(argv[0],"-d")) {
1120 ttype = kTransportUsb;
1121 } else if (!strcmp(argv[0],"-e")) {
1122 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001123 } else if (!strcmp(argv[0],"-a")) {
1124 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001125 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001126 const char *hostname = NULL;
1127 if (argv[0][2] == '\0') {
1128 if (argc < 2) return usage();
1129 hostname = argv[1];
1130 argc--;
1131 argv++;
1132 } else {
1133 hostname = argv[0] + 2;
1134 }
1135 adb_set_tcp_name(hostname);
1136
Riley Andrews98f58e82014-12-05 17:37:24 -08001137 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001138 if (argv[0][2] == '\0') {
1139 if (argc < 2) return usage();
1140 server_port_str = argv[1];
1141 argc--;
1142 argv++;
1143 } else {
1144 server_port_str = argv[0] + 2;
1145 }
1146 if (strlen(server_port_str) > 0) {
1147 server_port = (int) strtol(server_port_str, NULL, 0);
1148 if (server_port <= 0 || server_port > 65535) {
1149 fprintf(stderr,
1150 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1151 server_port_str);
1152 return usage();
1153 }
1154 } else {
1155 fprintf(stderr,
1156 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1157 return usage();
1158 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001159 } else {
1160 /* out of recognized modifiers and flags */
1161 break;
1162 }
1163 argc--;
1164 argv++;
1165 }
1166
1167 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001168 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001169
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001170 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001171 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001172 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001173 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001174 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001176 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001177 fprintf(stderr,"* could not start server *\n");
1178 }
1179 return r;
1180 }
1181
Riley Andrews98f58e82014-12-05 17:37:24 -08001182 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001183 return usage();
1184 }
1185
Riley Andrewsc8514c82014-12-05 17:32:46 -08001186 /* handle wait-for-* prefix */
1187 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001188 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001189 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1190 if (ttype == kTransportUsb) {
1191 service = "wait-for-usb";
1192 } else if (ttype == kTransportLocal) {
1193 service = "wait-for-local";
1194 } else {
1195 service = "wait-for-any";
1196 }
1197 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001198
Riley Andrewsc8514c82014-12-05 17:32:46 -08001199 format_host_command(buf, sizeof buf, service, ttype, serial);
1200
1201 if (adb_command(buf)) {
1202 D("failure: %s *\n",adb_error());
1203 fprintf(stderr,"error: %s\n", adb_error());
1204 return 1;
1205 }
1206
1207 /* Allow a command to be run after wait-for-device,
1208 * e.g. 'adb wait-for-device shell'.
1209 */
1210 if (argc == 1) {
1211 return 0;
1212 }
1213
1214 /* Fall through */
1215 argc--;
1216 argv++;
1217 }
1218
1219 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001220 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001221 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001222 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001223 if (argc < 2)
1224 listopt = "";
1225 else if (argc == 2 && !strcmp(argv[1], "-l"))
1226 listopt = argv[1];
1227 else {
1228 fprintf(stderr, "Usage: adb devices [-l]\n");
1229 return 1;
1230 }
1231 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001232 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001233 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001234 printf("List of devices attached \n");
1235 printf("%s\n", tmp);
1236 return 0;
1237 } else {
1238 return 1;
1239 }
1240 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001241 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001242 char *tmp;
1243 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001244 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001245 return 1;
1246 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001247 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1248 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001249 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001250 printf("%s\n", tmp);
1251 return 0;
1252 } else {
1253 return 1;
1254 }
1255 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001256 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001257 char *tmp;
1258 if (argc > 2) {
1259 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1260 return 1;
1261 }
1262 if (argc == 2) {
1263 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1264 } else {
1265 snprintf(buf, sizeof buf, "host:disconnect:");
1266 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001267 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001268 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001269 printf("%s\n", tmp);
1270 return 0;
1271 } else {
1272 return 1;
1273 }
1274 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001275 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001276 return adb_send_emulator_command(argc, argv);
1277 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001278 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001279 char h = (argv[0][0] == 'h');
1280
1281 if (h) {
1282 printf("\x1b[41;33m");
1283 fflush(stdout);
1284 }
1285
Riley Andrews98f58e82014-12-05 17:37:24 -08001286 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001287 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001288 r = interactive_shell();
1289 if (h) {
1290 printf("\x1b[0m");
1291 fflush(stdout);
1292 }
1293 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001294 }
1295
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001296 std::string cmd = "shell:";
1297 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001298 argc -= 2;
1299 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001300 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001301 cmd += " ";
1302 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001303 }
1304
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001305 while (true) {
1306 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1307 int fd = adb_connect(cmd.c_str());
1308 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001309 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001310 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001311 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001312 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001313 adb_close(fd);
1314 r = 0;
1315 } else {
1316 fprintf(stderr,"error: %s\n", adb_error());
1317 r = -1;
1318 }
1319
Riley Andrews98f58e82014-12-05 17:37:24 -08001320 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001321 fprintf(stderr,"\n- waiting for device -\n");
1322 adb_sleep_ms(1000);
1323 do_cmd(ttype, serial, "wait-for-device", 0);
1324 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001325 if (h) {
1326 printf("\x1b[0m");
1327 fflush(stdout);
1328 }
JP Abgrall408fa572011-03-16 15:57:42 -07001329 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 return r;
1331 }
1332 }
1333 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001334 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001335 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001336
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001337 std::string cmd = "exec:";
1338 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001339 argc -= 2;
1340 argv += 2;
1341 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001342 cmd += " ";
1343 cmd += escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001344 }
1345
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001346 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001347 if (fd < 0) {
1348 fprintf(stderr, "error: %s\n", adb_error());
1349 return -1;
1350 }
1351
1352 if (exec_in) {
1353 copy_to_file(STDIN_FILENO, fd);
1354 } else {
1355 copy_to_file(fd, STDOUT_FILENO);
1356 }
1357
1358 adb_close(fd);
1359 return 0;
1360 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001361 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001362 int fd;
1363 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001364 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001365 fprintf(stderr,"* server not running *\n");
1366 return 1;
1367 }
1368 return 0;
1369 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001370 else if (!strcmp(argv[0], "sideload")) {
1371 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001372 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001373 return 1;
1374 } else {
1375 return 0;
1376 }
1377 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001378 else if (!strcmp(argv[0], "remount") ||
1379 !strcmp(argv[0], "reboot") ||
1380 !strcmp(argv[0], "reboot-bootloader") ||
1381 !strcmp(argv[0], "tcpip") ||
1382 !strcmp(argv[0], "usb") ||
1383 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001384 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001385 !strcmp(argv[0], "disable-verity") ||
1386 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001387 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001388 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001389 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001390 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001391 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001392 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001393 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001394 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001395 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001396 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001397 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001398 if (argc != 1) return usage();
1399 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001400 return 0;
1401 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001403 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001404 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001405 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001406 char remove = 0;
1407 char remove_all = 0;
1408 char list = 0;
1409 char no_rebind = 0;
1410
1411 // Parse options here.
1412 while (argc > 1 && argv[1][0] == '-') {
1413 if (!strcmp(argv[1], "--list"))
1414 list = 1;
1415 else if (!strcmp(argv[1], "--remove"))
1416 remove = 1;
1417 else if (!strcmp(argv[1], "--remove-all"))
1418 remove_all = 1;
1419 else if (!strcmp(argv[1], "--no-rebind"))
1420 no_rebind = 1;
1421 else {
1422 return usage();
1423 }
1424 argc--;
1425 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001426 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001427
1428 // Ensure we can only use one option at a time.
1429 if (list + remove + remove_all + no_rebind > 1) {
1430 return usage();
1431 }
1432
1433 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001434 if (reverse) {
1435 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001436 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001437 if (serial) {
1438 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1439 serial);
1440 } else if (ttype == kTransportUsb) {
1441 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1442 } else if (ttype == kTransportLocal) {
1443 snprintf(host_prefix, sizeof host_prefix, "host-local");
1444 } else {
1445 snprintf(host_prefix, sizeof host_prefix, "host");
1446 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001447 }
1448
1449 // Implement forward --list
1450 if (list) {
1451 if (argc != 1)
1452 return usage();
1453 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1454 char* forwards = adb_query(buf);
1455 if (forwards == NULL) {
1456 fprintf(stderr, "error: %s\n", adb_error());
1457 return 1;
1458 }
1459 printf("%s", forwards);
1460 free(forwards);
1461 return 0;
1462 }
1463
1464 // Implement forward --remove-all
1465 else if (remove_all) {
1466 if (argc != 1)
1467 return usage();
1468 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1469 }
1470
1471 // Implement forward --remove <local>
1472 else if (remove) {
1473 if (argc != 2)
1474 return usage();
1475 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1476 }
1477 // Or implement one of:
1478 // forward <local> <remote>
1479 // forward --no-rebind <local> <remote>
1480 else
1481 {
1482 if (argc != 3)
1483 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001484 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001485 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1486 }
1487
Riley Andrews98f58e82014-12-05 17:37:24 -08001488 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001489 fprintf(stderr,"error: %s\n", adb_error());
1490 return 1;
1491 }
1492 return 0;
1493 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001494 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001495 else if (!strcmp(argv[0], "ls")) {
1496 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001497 return do_sync_ls(argv[1]);
1498 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001499 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001500 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001501 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001502 const char* lpath = NULL, *rpath = NULL;
1503
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001504 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001505
1506 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001507 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001508 }
1509
1510 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001511 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001512 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001513 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001514 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001515 const char* rpath = NULL, *lpath = ".";
1516
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001517 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001518
1519 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001520 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001521 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001522
1523 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001524 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001525 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001526 if (argc < 2) return usage();
1527 return install_app(ttype, serial, argc, argv);
1528 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001529 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001530 if (argc < 2) return usage();
1531 return install_multiple_app(ttype, serial, argc, argv);
1532 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001533 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001534 if (argc < 2) return usage();
1535 return uninstall_app(ttype, serial, argc, argv);
1536 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001537 else if (!strcmp(argv[0], "sync")) {
Elliott Hughes58305772015-04-17 13:57:15 -07001538 std::string src_arg;
1539 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001540 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001541 // No local path was specified.
1542 src_arg = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001543 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughes58305772015-04-17 13:57:15 -07001544 list_only = 1;
Anthony Newnam705c9442010-02-22 08:36:49 -06001545 if (argc == 3) {
Elliott Hughes58305772015-04-17 13:57:15 -07001546 src_arg = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001547 } else {
Elliott Hughes58305772015-04-17 13:57:15 -07001548 src_arg = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001549 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001550 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001551 // A local path or "android"/"data" arg was specified.
1552 src_arg = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001553 } else {
1554 return usage();
1555 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001556
Elliott Hughes58305772015-04-17 13:57:15 -07001557 if (src_arg != "" &&
1558 src_arg != "system" && src_arg != "data" && src_arg != "vendor" && src_arg != "oem") {
1559 return usage();
1560 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001561
Elliott Hughes58305772015-04-17 13:57:15 -07001562 std::string system_src_path = product_file("system");
1563 std::string data_src_path = product_file("data");
1564 std::string vendor_src_path = product_file("vendor");
1565 std::string oem_src_path = product_file("oem");
1566 if (!directory_exists(vendor_src_path)) {
1567 vendor_src_path = "";
1568 }
1569 if (!directory_exists(oem_src_path)) {
1570 oem_src_path = "";
1571 }
1572
1573 int rc = 0;
1574 if (rc == 0 && (src_arg.empty() || src_arg == "system")) {
1575 rc = do_sync_sync(system_src_path.c_str(), "/system", list_only);
1576 }
1577 if (rc == 0 && (src_arg.empty() || src_arg == "vendor")) {
1578 rc = do_sync_sync(vendor_src_path.c_str(), "/vendor", list_only);
1579 }
1580 if(rc == 0 && (src_arg.empty() || src_arg == "oem")) {
1581 rc = do_sync_sync(oem_src_path.c_str(), "/oem", list_only);
1582 }
1583 if (rc == 0 && (src_arg.empty() || src_arg == "data")) {
1584 rc = do_sync_sync(data_src_path.c_str(), "/data", list_only);
1585 }
1586 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001587 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001588 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001589 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001590 !strcmp(argv[0],"get-serialno") ||
1591 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001592 {
1593 char *tmp;
1594
1595 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1596 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001597 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001598 printf("%s\n", tmp);
1599 return 0;
1600 } else {
1601 return 1;
1602 }
1603 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001604 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001605 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001606 status_window(ttype, serial);
1607 return 0;
1608 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001609 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001610 return logcat(ttype, serial, argc, argv);
1611 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001612 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001613 return ppp(argc, argv);
1614 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001615 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001616 return adb_connect("host:start-server");
1617 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001618 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001619 return backup(argc, argv);
1620 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001621 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001622 return restore(argc, argv);
1623 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001624 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001625 if (argc < 2) return usage();
1626 return adb_auth_keygen(argv[1]);
1627 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001628 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001629 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001630 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001631 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001632 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 help();
1634 return 0;
1635 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001636 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637 version(stdout);
1638 return 0;
1639 }
1640
1641 usage();
1642 return 1;
1643}
1644
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001645#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001646static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001647{
Dan Albertbac34742015-02-25 17:51:28 -08001648 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001649 int argc;
1650 va_list ap;
1651
1652 va_start(ap, cmd);
1653 argc = 0;
1654
1655 if (serial) {
1656 argv[argc++] = "-s";
1657 argv[argc++] = serial;
1658 } else if (ttype == kTransportUsb) {
1659 argv[argc++] = "-d";
1660 } else if (ttype == kTransportLocal) {
1661 argv[argc++] = "-e";
1662 }
1663
1664 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001665 while(argc < MAX_ARGV_LENGTH &&
1666 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1667 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001668 va_end(ap);
1669
1670#if 0
1671 int n;
1672 fprintf(stderr,"argc = %d\n",argc);
1673 for(n = 0; n < argc; n++) {
1674 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1675 }
1676#endif
1677
1678 return adb_commandline(argc, argv);
1679}
1680
Dan Albertbac34742015-02-25 17:51:28 -08001681static int pm_command(transport_type transport, const char* serial,
1682 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001683{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001684 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001685
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001686 while (argc-- > 0) {
1687 cmd += " ";
1688 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001689 }
1690
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001691 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001692 return 0;
1693}
1694
Elliott Hughes58305772015-04-17 13:57:15 -07001695static int uninstall_app(transport_type transport, const char* serial, int argc,
1696 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001697{
1698 /* if the user choose the -k option, we refuse to do it until devices are
1699 out with the option to uninstall the remaining data somehow (adb/ui) */
1700 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1701 {
1702 printf(
1703 "The -k option uninstalls the application while retaining the data/cache.\n"
1704 "At the moment, there is no way to remove the remaining data.\n"
1705 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1706 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1707 return -1;
1708 }
1709
1710 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1711 return pm_command(transport, serial, argc, argv);
1712}
1713
Dan Albertbac34742015-02-25 17:51:28 -08001714static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001715{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001716 std::string cmd = "shell:rm -f " + escape_arg(filename);
1717 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001718 return 0;
1719}
1720
Kenny Root597ea5b2011-08-05 11:19:45 -07001721static const char* get_basename(const char* filename)
1722{
1723 const char* basename = adb_dirstop(filename);
1724 if (basename) {
1725 basename++;
1726 return basename;
1727 } else {
1728 return filename;
1729 }
1730}
1731
Elliott Hughes58305772015-04-17 13:57:15 -07001732static int install_app(transport_type transport, const char* serial, int argc,
1733 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001734{
1735 static const char *const DATA_DEST = "/data/local/tmp/%s";
1736 static const char *const SD_DEST = "/sdcard/tmp/%s";
1737 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001738 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001739 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001740
1741 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001742 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001743 where = SD_DEST;
1744 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001745 }
1746
Jeff Sharkey960df972014-06-09 17:30:57 -07001747 // Find last APK argument.
1748 // All other arguments passed through verbatim.
1749 int last_apk = -1;
1750 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001751 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001752 char* dot = strrchr(file, '.');
1753 if (dot && !strcasecmp(dot, ".apk")) {
1754 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1755 fprintf(stderr, "Invalid APK file: %s\n", file);
1756 return -1;
1757 }
1758
1759 last_apk = i;
1760 break;
1761 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001762 }
1763
Jeff Sharkey960df972014-06-09 17:30:57 -07001764 if (last_apk == -1) {
1765 fprintf(stderr, "Missing APK file\n");
1766 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001767 }
1768
Dan Albertbac34742015-02-25 17:51:28 -08001769 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001770 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001771 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001772 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001773 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001774 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001775 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001776 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001777 }
1778
1779 pm_command(transport, serial, argc, argv);
1780
Kenny Root60733e92012-03-26 16:14:02 -07001781cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001782 delete_file(transport, serial, apk_dest);
1783 return err;
1784}
1785
Elliott Hughes58305772015-04-17 13:57:15 -07001786static int install_multiple_app(transport_type transport, const char* serial, int argc,
1787 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001788{
Jeff Sharkey960df972014-06-09 17:30:57 -07001789 int i;
1790 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001791 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001792
1793 // Find all APK arguments starting at end.
1794 // All other arguments passed through verbatim.
1795 int first_apk = -1;
1796 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001797 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001798 char* dot = strrchr(file, '.');
1799 if (dot && !strcasecmp(dot, ".apk")) {
1800 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1801 fprintf(stderr, "Invalid APK file: %s\n", file);
1802 return -1;
1803 }
1804
1805 total_size += sb.st_size;
1806 first_apk = i;
1807 } else {
1808 break;
1809 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001810 }
1811
Jeff Sharkey960df972014-06-09 17:30:57 -07001812 if (first_apk == -1) {
1813 fprintf(stderr, "Missing APK file\n");
1814 return 1;
1815 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001816
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001817 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001818 for (i = 1; i < first_apk; i++) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001819 cmd += " ";
1820 cmd += escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001821 }
1822
1823 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001824 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001825 if (fd < 0) {
1826 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1827 return -1;
1828 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001829 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001830 read_status_line(fd, buf, sizeof(buf));
1831 adb_close(fd);
1832
1833 int session_id = -1;
1834 if (!strncmp("Success", buf, 7)) {
1835 char* start = strrchr(buf, '[');
1836 char* end = strrchr(buf, ']');
1837 if (start && end) {
1838 *end = '\0';
1839 session_id = strtol(start + 1, NULL, 10);
1840 }
1841 }
1842 if (session_id < 0) {
1843 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001844 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001845 return -1;
1846 }
1847
1848 // Valid session, now stream the APKs
1849 int success = 1;
1850 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001851 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001852 if (stat(file, &sb) == -1) {
1853 fprintf(stderr, "Failed to stat %s\n", file);
1854 success = 0;
1855 goto finalize_session;
1856 }
1857
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001858 std::string cmd = android::base::StringPrintf(
1859 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1860 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001861
1862 int localFd = adb_open(file, O_RDONLY);
1863 if (localFd < 0) {
1864 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1865 success = 0;
1866 goto finalize_session;
1867 }
1868
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001869 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001870 if (remoteFd < 0) {
1871 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1872 adb_close(localFd);
1873 success = 0;
1874 goto finalize_session;
1875 }
1876
1877 copy_to_file(localFd, remoteFd);
1878 read_status_line(remoteFd, buf, sizeof(buf));
1879
1880 adb_close(localFd);
1881 adb_close(remoteFd);
1882
1883 if (strncmp("Success", buf, 7)) {
1884 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001885 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001886 success = 0;
1887 goto finalize_session;
1888 }
1889 }
1890
1891finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001892 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07001893 if (success) {
1894 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
1895 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001896 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07001897 }
1898
1899 fd = adb_connect(buf);
1900 if (fd < 0) {
1901 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
1902 return -1;
1903 }
1904 read_status_line(fd, buf, sizeof(buf));
1905 adb_close(fd);
1906
1907 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001908 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001909 return 0;
1910 } else {
1911 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001912 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001913 return -1;
1914 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001915}