blob: ddb52e2917de78ddef27dd7a29f01ff22039377e [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"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047#include "file_sync_service.h"
48
Dan Albertbac34742015-02-25 17:51:28 -080049static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080051int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +000052 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
53 char **oem_srcdir_out);
Dan Albertbac34742015-02-25 17:51:28 -080054int install_app(transport_type transport, const char* serial, int argc,
55 const char** argv);
56int install_multiple_app(transport_type transport, const char* serial, int argc,
57 const char** argv);
58int uninstall_app(transport_type transport, const char* serial, int argc,
59 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
61static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080062extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080063
64static char *product_file(const char *extra)
65{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066 if (gProductOutPath == NULL) {
67 fprintf(stderr, "adb: Product directory not specified; "
68 "use -p or define ANDROID_PRODUCT_OUT\n");
69 exit(1);
70 }
71
Dan Albertbac34742015-02-25 17:51:28 -080072 int n = strlen(gProductOutPath) + strlen(extra) + 2;
73 char* x = reinterpret_cast<char*>(malloc(n));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 if (x == 0) {
75 fprintf(stderr, "adb: Out of memory (product_file())\n");
76 exit(1);
77 }
78
79 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
80 return x;
81}
82
83void version(FILE * out) {
84 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
85 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
86}
87
88void help()
89{
90 version(stderr);
91
92 fprintf(stderr,
93 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080094 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 " -d - directs command to the only connected USB device\n"
96 " returns an error if more than one USB device is present.\n"
97 " -e - directs command to the only running emulator.\n"
98 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070099 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700100 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -0700101 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 " -p <product name or path> - simple product name like 'sooner', or\n"
103 " a relative/absolute path to a product\n"
104 " out directory like 'out/target/product/sooner'.\n"
105 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
106 " environment variable is used, which must\n"
107 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800108 " -H - Name of adb server host (default: localhost)\n"
109 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700110 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700111 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -0400112 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
113 " Port 5555 is used by default if no port number is specified.\n"
114 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
115 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200116 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -0400117 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 "\n"
119 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700120 " adb push [-p] <local> <remote>\n"
121 " - copy file/dir to device\n"
122 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700123 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700124 " - copy file/dir from device\n"
125 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700126 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800127 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600128 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129 " (see 'adb help all')\n"
130 " adb shell - run remote shell interactively\n"
131 " adb shell <command> - run remote shell command\n"
132 " adb emu <command> - run emulator console command\n"
133 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100134 " adb forward --list - list all forward socket connections.\n"
135 " the format is a list of lines with the following format:\n"
136 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800137 " adb forward <local> <remote> - forward socket connections\n"
138 " forward specs are one of: \n"
139 " tcp:<port>\n"
140 " localabstract:<unix domain socket name>\n"
141 " localreserved:<unix domain socket name>\n"
142 " localfilesystem:<unix domain socket name>\n"
143 " dev:<character device name>\n"
144 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100145 " adb forward --no-rebind <local> <remote>\n"
146 " - same as 'adb forward <local> <remote>' but fails\n"
147 " if <local> is already forwarded\n"
148 " adb forward --remove <local> - remove a specific forward socket connection\n"
149 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100150 " adb reverse --list - list all reverse socket connections from device\n"
151 " adb reverse <remote> <local> - reverse socket connections\n"
152 " reverse specs are one of:\n"
153 " tcp:<port>\n"
154 " localabstract:<unix domain socket name>\n"
155 " localreserved:<unix domain socket name>\n"
156 " localfilesystem:<unix domain socket name>\n"
157 " adb reverse --norebind <remote> <local>\n"
158 " - same as 'adb reverse <remote> <local>' but fails\n"
159 " if <remote> is already reversed.\n"
160 " adb reverse --remove <remote>\n"
161 " - remove a specific reversed socket connection\n"
162 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800163 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700164 " adb install [-lrtsd] <file>\n"
165 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700166 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700167 " (-l: forward lock application)\n"
168 " (-r: replace existing application)\n"
169 " (-t: allow test packages)\n"
170 " (-s: install application on sdcard)\n"
171 " (-d: allow version code downgrade)\n"
172 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800173 " adb uninstall [-k] <package> - remove this app package from the device\n"
174 " ('-k' means keep the data and cache directories)\n"
175 " adb bugreport - return all information from the device\n"
176 " that should be included in a bug report.\n"
177 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800178 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700179 " - write an archive of the device's data to <file>.\n"
180 " If no -f option is supplied then the data is written\n"
181 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700182 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700183 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800184 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
185 " (aka .obb) files associated with each application; the default\n"
186 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700187 " (-shared|-noshared enable/disable backup of the device's\n"
188 " shared storage / SD card contents; the default is noshared.)\n"
189 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700190 " (-system|-nosystem toggles whether -all automatically includes\n"
191 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700192 " (<packages...> is the list of applications to be backed up. If\n"
193 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700194 " list is optional. Applications explicitly given on the\n"
195 " command line will be included even if -nosystem would\n"
196 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700197 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700198 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700199 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800200 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
201 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800202 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
203 " and the public key is stored in <file>.pub. Any existing files\n"
204 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800205 " adb help - show this help message\n"
206 " adb version - show version num\n"
207 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 "scripting:\n"
209 " adb wait-for-device - block until device is online\n"
210 " adb start-server - ensure that there is a server running\n"
211 " adb kill-server - kill the server if it is running\n"
212 " adb get-state - prints: offline | bootloader | device\n"
213 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700214 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800215 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000216 " 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 -0700217 " adb reboot [bootloader|recovery]\n"
218 " - reboots the device, optionally into the bootloader or recovery program.\n"
219 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
220 " adb reboot sideload-auto-reboot\n"
221 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800222 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700223 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500224 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800225 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000226 " 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 -0800227 "networking:\n"
228 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500229 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
231 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
232 "\n"
233 "adb sync notes: adb sync [ <directory> ]\n"
234 " <localdir> can be interpreted in several ways:\n"
235 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000236 " - 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 -0800237 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000238 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000240 "\n"
241 "environmental variables:\n"
242 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
243 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
244 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
245 " 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 -0800246 );
247}
248
249int usage()
250{
251 help();
252 return 1;
253}
254
Yabin Cuid325e862014-11-17 14:48:25 -0800255#if defined(_WIN32)
256
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700257// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800258void stdin_raw_init(int fd);
259void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800260
261#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100262static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100264static void stdin_raw_init(int fd) {
265 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100267 termios tio;
268 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100270 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800271
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100272 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273 tio.c_cc[VTIME] = 0;
274 tio.c_cc[VMIN] = 1;
275
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100276 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277}
278
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100279static void stdin_raw_restore(int fd) {
280 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281}
282#endif
283
284static void read_and_dump(int fd)
285{
286 char buf[4096];
287 int len;
288
289 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700290 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700292 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800293 if(len == 0) {
294 break;
295 }
296
297 if(len < 0) {
298 if(errno == EINTR) continue;
299 break;
300 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400301 fwrite(buf, 1, len, stdout);
302 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800303 }
304}
305
Jeff Sharkey960df972014-06-09 17:30:57 -0700306static void read_status_line(int fd, char* buf, size_t count)
307{
308 count--;
309 while (count > 0) {
310 int len = adb_read(fd, buf, count);
311 if (len == 0) {
312 break;
313 } else if (len < 0) {
314 if (errno == EINTR) continue;
315 break;
316 }
317
318 buf += len;
319 count -= len;
320 }
321 *buf = '\0';
322}
323
Christopher Tated2f54152011-04-21 12:53:28 -0700324static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700325 const size_t BUFSIZE = 32 * 1024;
326 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700327 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700328 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700329
330 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800331
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700332 if (inFd == STDIN_FILENO) {
333 stdin_raw_init(STDIN_FILENO);
334 }
Yabin Cuid325e862014-11-17 14:48:25 -0800335
Christopher Tated2f54152011-04-21 12:53:28 -0700336 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700337 if (inFd == STDIN_FILENO) {
338 len = unix_read(inFd, buf, BUFSIZE);
339 } else {
340 len = adb_read(inFd, buf, BUFSIZE);
341 }
Christopher Tated2f54152011-04-21 12:53:28 -0700342 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700343 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700344 break;
345 }
346 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700347 if (errno == EINTR) {
348 D("copy_to_file() : EINTR, retrying\n");
349 continue;
350 }
Christopher Tated2f54152011-04-21 12:53:28 -0700351 D("copy_to_file() : error %d\n", errno);
352 break;
353 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700354 if (outFd == STDOUT_FILENO) {
355 fwrite(buf, 1, len, stdout);
356 fflush(stdout);
357 } else {
358 adb_write(outFd, buf, len);
359 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700360 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700361 }
Yabin Cuid325e862014-11-17 14:48:25 -0800362
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700363 if (inFd == STDIN_FILENO) {
364 stdin_raw_restore(STDIN_FILENO);
365 }
Yabin Cuid325e862014-11-17 14:48:25 -0800366
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700367 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700368 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700369}
370
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371static void *stdin_read_thread(void *x)
372{
373 int fd, fdi;
374 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 int r, n;
376 int state = 0;
377
378 int *fds = (int*) x;
379 fd = fds[0];
380 fdi = fds[1];
381 free(fds);
382
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 for(;;) {
384 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700385 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700387 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800388 if(r == 0) break;
389 if(r < 0) {
390 if(errno == EINTR) continue;
391 break;
392 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400393 for(n = 0; n < r; n++){
394 switch(buf[n]) {
395 case '\n':
396 state = 1;
397 break;
398 case '\r':
399 state = 1;
400 break;
401 case '~':
402 if(state == 1) state++;
403 break;
404 case '.':
405 if(state == 2) {
406 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400408 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400410 default:
411 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 r = adb_write(fd, buf, r);
415 if(r <= 0) {
416 break;
417 }
418 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800419 return 0;
420}
421
422int interactive_shell(void)
423{
424 adb_thread_t thr;
425 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426
427 fd = adb_connect("shell:");
428 if(fd < 0) {
429 fprintf(stderr,"error: %s\n", adb_error());
430 return 1;
431 }
432 fdi = 0; //dup(0);
433
Dan Albertbac34742015-02-25 17:51:28 -0800434 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800435 fds[0] = fd;
436 fds[1] = fdi;
437
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 adb_thread_create(&thr, stdin_read_thread, fds);
440 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800442 return 0;
443}
444
445
446static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
447{
448 if (serial) {
449 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
450 } else {
451 const char* prefix = "host";
452 if (ttype == kTransportUsb)
453 prefix = "host-usb";
454 else if (ttype == kTransportLocal)
455 prefix = "host-local";
456
457 snprintf(buffer, buflen, "%s:%s", prefix, command);
458 }
459}
460
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100461int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800462 unsigned progress)
463{
464 char buf[4096];
465 unsigned total;
466 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800467
468 sprintf(buf,"%s:%d", service, sz);
469 fd = adb_connect(buf);
470 if(fd < 0) {
471 fprintf(stderr,"error: %s\n", adb_error());
472 return -1;
473 }
474
475 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800476 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800477
478 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800479 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800480
481 if(progress) {
482 char *x = strrchr(service, ':');
483 if(x) service = x + 1;
484 }
485
486 while(sz > 0) {
487 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800488 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800489 adb_status(fd);
490 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
491 return -1;
492 }
493 sz -= xfer;
494 ptr += xfer;
495 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100496 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800497 fflush(stdout);
498 }
499 }
500 if(progress) {
501 printf("\n");
502 }
503
Dan Albertcc731cc2015-02-24 21:26:58 -0800504 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800505 fprintf(stderr,"* error reading response *\n");
506 adb_close(fd);
507 return -1;
508 }
509 if(memcmp(buf, "OKAY", 4)) {
510 buf[4] = 0;
511 fprintf(stderr,"* error response '%s' *\n", buf);
512 adb_close(fd);
513 return -1;
514 }
515
516 adb_close(fd);
517 return 0;
518}
519
520
521int adb_download(const char *service, const char *fn, unsigned progress)
522{
523 void *data;
524 unsigned sz;
525
526 data = load_file(fn, &sz);
527 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100528 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800529 return -1;
530 }
531
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100532 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800533 free(data);
534 return status;
535}
536
Doug Zongker71fe5842014-06-26 15:35:36 -0700537#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
538
539/*
540 * The sideload-host protocol serves the data in a file (given on the
541 * command line) to the client, using a simple protocol:
542 *
543 * - The connect message includes the total number of bytes in the
544 * file and a block size chosen by us.
545 *
546 * - The other side sends the desired block number as eight decimal
547 * digits (eg "00000023" for block 23). Blocks are numbered from
548 * zero.
549 *
550 * - We send back the data of the requested block. The last block is
551 * likely to be partial; when the last block is requested we only
552 * send the part of the block that exists, it's not padded up to the
553 * block size.
554 *
555 * - When the other side sends "DONEDONE" instead of a block number,
556 * we hang up.
557 */
558int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700559 unsigned sz;
560 size_t xfer = 0;
561 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800562 int last_percent = -1;
563 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700564
565 printf("loading: '%s'", fn);
566 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800567 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700568 if (data == 0) {
569 printf("\n");
570 fprintf(stderr, "* cannot read '%s' *\n", fn);
571 return -1;
572 }
573
574 char buf[100];
575 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
576 int fd = adb_connect(buf);
577 if (fd < 0) {
578 // Try falling back to the older sideload method. Maybe this
579 // is an older device that doesn't support sideload-host.
580 printf("\n");
581 status = adb_download_buffer("sideload", fn, data, sz, 1);
582 goto done;
583 }
584
Spencer Lowf055c192015-01-25 14:40:16 -0800585 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700586
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700587 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800588 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700589 fprintf(stderr, "* failed to read command: %s\n", adb_error());
590 status = -1;
591 goto done;
592 }
593
594 if (strncmp("DONEDONE", buf, 8) == 0) {
595 status = 0;
596 break;
597 }
598
599 buf[8] = '\0';
600 int block = strtol(buf, NULL, 10);
601
602 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
603 if (offset >= sz) {
604 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
605 status = -1;
606 goto done;
607 }
608 uint8_t* start = data + offset;
609 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
610 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
611 if (offset_end > sz) {
612 to_write = sz - offset;
613 }
614
Dan Albertcc731cc2015-02-24 21:26:58 -0800615 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700616 adb_status(fd);
617 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
618 status = -1;
619 goto done;
620 }
621 xfer += to_write;
622
623 // For normal OTA packages, we expect to transfer every byte
624 // twice, plus a bit of overhead (one read during
625 // verification, one read of each byte for installation, plus
626 // extra access to things like the zip central directory).
627 // This estimate of the completion becomes 100% when we've
628 // transferred ~2.13 (=100/47) times the package size.
629 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
630 if (percent != last_percent) {
631 printf("\rserving: '%s' (~%d%%) ", fn, percent);
632 fflush(stdout);
633 last_percent = percent;
634 }
635 }
636
Colin Cross6d6a8982014-07-07 14:12:41 -0700637 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700638
639 done:
640 if (fd >= 0) adb_close(fd);
641 free(data);
642 return status;
643}
644
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800645static void status_window(transport_type ttype, const char* serial)
646{
647 char command[4096];
648 char *state = 0;
649 char *laststate = 0;
650
651 /* silence stderr */
652#ifdef _WIN32
653 /* XXX: TODO */
654#else
655 int fd;
656 fd = unix_open("/dev/null", O_WRONLY);
657 dup2(fd, 2);
658 adb_close(fd);
659#endif
660
661 format_host_command(command, sizeof command, "get-state", ttype, serial);
662
663 for(;;) {
664 adb_sleep_ms(250);
665
666 if(state) {
667 free(state);
668 state = 0;
669 }
670
671 state = adb_query(command);
672
673 if(state) {
674 if(laststate && !strcmp(state,laststate)){
675 continue;
676 } else {
677 if(laststate) free(laststate);
678 laststate = strdup(state);
679 }
680 }
681
682 printf("%c[2J%c[2H", 27, 27);
683 printf("Android Debug Bridge\n");
684 printf("State: %s\n", state ? state : "offline");
685 fflush(stdout);
686 }
687}
688
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700689static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700690{
691 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
692}
693
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700694static std::string escape_arg(const std::string& s) {
695 // Preserve empty arguments.
696 if (s.empty()) return "\"\"";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700698 std::string result(s);
699 for (auto it = result.begin(); it != result.end(); ++it) {
700 if (should_escape(*it)) {
701 it = result.insert(it, '\\') + 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800702 }
703 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700704 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800705}
706
707/**
708 * Run ppp in "notty" mode against a resource listed as the first parameter
709 * eg:
710 *
711 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
712 *
713 */
Dan Albertbac34742015-02-25 17:51:28 -0800714int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800716#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800717 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
718 return -1;
719#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800720 pid_t pid;
721 int fd;
722
723 if (argc < 2) {
724 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
725 argv[0]);
726
727 return 1;
728 }
729
Dan Albertbac34742015-02-25 17:51:28 -0800730 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800731 fd = adb_connect(adb_service_name);
732
733 if(fd < 0) {
734 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
735 adb_service_name, adb_error());
736 return 1;
737 }
738
739 pid = fork();
740
741 if (pid < 0) {
742 perror("from fork()");
743 return 1;
744 } else if (pid == 0) {
745 int err;
746 int i;
747 const char **ppp_args;
748
749 // copy args
750 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
751 ppp_args[0] = "pppd";
752 for (i = 2 ; i < argc ; i++) {
753 //argv[2] and beyond become ppp_args[1] and beyond
754 ppp_args[i - 1] = argv[i];
755 }
756 ppp_args[i-1] = NULL;
757
758 // child side
759
760 dup2(fd, STDIN_FILENO);
761 dup2(fd, STDOUT_FILENO);
762 adb_close(STDERR_FILENO);
763 adb_close(fd);
764
765 err = execvp("pppd", (char * const *)ppp_args);
766
767 if (err < 0) {
768 perror("execing pppd");
769 }
770 exit(-1);
771 } else {
772 // parent side
773
774 adb_close(fd);
775 return 0;
776 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800777#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800778}
779
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700780static int send_shell_command(transport_type transport, const char* serial,
781 const std::string& command) {
782 int fd;
783 while (true) {
784 fd = adb_connect(command.c_str());
785 if (fd >= 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800786 break;
787 fprintf(stderr,"- waiting for device -\n");
788 adb_sleep_ms(1000);
789 do_cmd(transport, serial, "wait-for-device", 0);
790 }
791
792 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700793 int rc = adb_close(fd);
794 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800795 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700796 }
797 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800798}
799
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700800static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
801 char* log_tags = getenv("ANDROID_LOG_TAGS");
802 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800803
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700804 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800805
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700806 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700807 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800808 }
809
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800810 argc -= 1;
811 argv += 1;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700812 while (argc-- > 0) {
813 cmd += " ";
814 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800815 }
816
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700817 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800818 return 0;
819}
820
Mark Salyzyn60299df2014-04-30 09:10:31 -0700821static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800822{
823 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700824 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800825
826 for(;;) {
827 x = adb_dirstart(x);
828 if(x == 0) return 0;
829 *x = 0;
830 ret = adb_mkdir(path, 0775);
831 *x = OS_PATH_SEPARATOR;
832 if((ret < 0) && (errno != EEXIST)) {
833 return ret;
834 }
835 x++;
836 }
837 return 0;
838}
839
Dan Albertbac34742015-02-25 17:51:28 -0800840static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700841 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800842 char default_name[32];
843 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700844 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700845 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700846
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700847 /* find, extract, and use any -f argument */
848 for (i = 1; i < argc; i++) {
849 if (!strcmp("-f", argv[i])) {
850 if (i == argc-1) {
851 fprintf(stderr, "adb: -f passed with no filename\n");
852 return usage();
853 }
854 filename = argv[i+1];
855 for (j = i+2; j <= argc; ) {
856 argv[i++] = argv[j++];
857 }
858 argc -= 2;
859 argv[argc] = NULL;
860 }
Christopher Tated2f54152011-04-21 12:53:28 -0700861 }
862
Christopher Tatebb86bc52011-08-22 17:12:08 -0700863 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
864 if (argc < 2) return usage();
865
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800866 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700867 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800868 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700869 if (outFd < 0) {
870 fprintf(stderr, "adb: unable to open file %s\n", filename);
871 return -1;
872 }
873
874 snprintf(buf, sizeof(buf), "backup");
875 for (argc--, argv++; argc; argc--, argv++) {
876 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
877 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
878 }
879
880 D("backup. filename=%s buf=%s\n", filename, buf);
881 fd = adb_connect(buf);
882 if (fd < 0) {
883 fprintf(stderr, "adb: unable to connect for backup\n");
884 adb_close(outFd);
885 return -1;
886 }
887
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800888 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700889 copy_to_file(fd, outFd);
890
891 adb_close(fd);
892 adb_close(outFd);
893 return 0;
894}
895
Dan Albertbac34742015-02-25 17:51:28 -0800896static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700897 const char* filename;
898 int fd, tarFd;
899
900 if (argc != 2) return usage();
901
902 filename = argv[1];
903 tarFd = adb_open(filename, O_RDONLY);
904 if (tarFd < 0) {
905 fprintf(stderr, "adb: unable to open file %s\n", filename);
906 return -1;
907 }
908
909 fd = adb_connect("restore:");
910 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700911 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700912 adb_close(tarFd);
913 return -1;
914 }
915
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800916 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700917 copy_to_file(tarFd, fd);
918
919 adb_close(fd);
920 adb_close(tarFd);
921 return 0;
922}
923
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800924#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
925static int top_works(const char *top)
926{
927 if (top != NULL && adb_is_absolute_host_path(top)) {
928 char path_buf[PATH_MAX];
929 snprintf(path_buf, sizeof(path_buf),
930 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
931 return access(path_buf, F_OK) == 0;
932 }
933 return 0;
934}
935
936static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
937{
938 strcpy(path_buf, indir);
939 while (1) {
940 if (top_works(path_buf)) {
941 return path_buf;
942 }
943 char *s = adb_dirstop(path_buf);
944 if (s != NULL) {
945 *s = '\0';
946 } else {
947 path_buf[0] = '\0';
948 return NULL;
949 }
950 }
951}
952
953static char *find_top(char path_buf[PATH_MAX])
954{
955 char *top = getenv("ANDROID_BUILD_TOP");
956 if (top != NULL && top[0] != '\0') {
957 if (!top_works(top)) {
958 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
959 return NULL;
960 }
961 } else {
962 top = getenv("TOP");
963 if (top != NULL && top[0] != '\0') {
964 if (!top_works(top)) {
965 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
966 return NULL;
967 }
968 } else {
969 top = NULL;
970 }
971 }
972
973 if (top != NULL) {
974 /* The environment pointed to a top directory that works.
975 */
976 strcpy(path_buf, top);
977 return path_buf;
978 }
979
980 /* The environment didn't help. Walk up the tree from the CWD
981 * to see if we can find the top.
982 */
983 char dir[PATH_MAX];
984 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
985 if (top == NULL) {
986 /* If the CWD isn't under a good-looking top, see if the
987 * executable is.
988 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100989 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800990 top = find_top_from(dir, path_buf);
991 }
992 return top;
993}
994
995/* <hint> may be:
996 * - A simple product name
997 * e.g., "sooner"
998TODO: debug? sooner-debug, sooner:debug?
999 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1000 * e.g., "out/target/product/sooner"
1001 * - An absolute path to the PRODUCT_OUT dir
1002 * e.g., "/src/device/out/target/product/sooner"
1003 *
1004 * Given <hint>, try to construct an absolute path to the
1005 * ANDROID_PRODUCT_OUT dir.
1006 */
1007static const char *find_product_out_path(const char *hint)
1008{
1009 static char path_buf[PATH_MAX];
1010
1011 if (hint == NULL || hint[0] == '\0') {
1012 return NULL;
1013 }
1014
1015 /* If it's already absolute, don't bother doing any work.
1016 */
1017 if (adb_is_absolute_host_path(hint)) {
1018 strcpy(path_buf, hint);
1019 return path_buf;
1020 }
1021
1022 /* If there are any slashes in it, assume it's a relative path;
1023 * make it absolute.
1024 */
1025 if (adb_dirstart(hint) != NULL) {
1026 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1027 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1028 return NULL;
1029 }
1030 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1031 fprintf(stderr, "adb: Couldn't assemble path\n");
1032 return NULL;
1033 }
1034 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1035 strcat(path_buf, hint);
1036 return path_buf;
1037 }
1038
1039 /* It's a string without any slashes. Try to do something with it.
1040 *
1041 * Try to find the root of the build tree, and build a PRODUCT_OUT
1042 * path from there.
1043 */
1044 char top_buf[PATH_MAX];
1045 const char *top = find_top(top_buf);
1046 if (top == NULL) {
1047 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1048 return NULL;
1049 }
1050//TODO: if we have a way to indicate debug, look in out/debug/target/...
1051 snprintf(path_buf, sizeof(path_buf),
1052 "%s" OS_PATH_SEPARATOR_STR
1053 "out" OS_PATH_SEPARATOR_STR
1054 "target" OS_PATH_SEPARATOR_STR
1055 "product" OS_PATH_SEPARATOR_STR
1056 "%s", top_buf, hint);
1057 if (access(path_buf, F_OK) < 0) {
1058 fprintf(stderr, "adb: Couldn't find a product dir "
1059 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1060 return NULL;
1061 }
1062 return path_buf;
1063}
1064
Dan Albertbac34742015-02-25 17:51:28 -08001065static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1066 char const **path2, int *show_progress,
1067 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001068 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001069 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001070
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001071 while (narg > 0) {
1072 if (!strcmp(*arg, "-p")) {
1073 *show_progress = 1;
1074 } else if (!strcmp(*arg, "-a")) {
1075 *copy_attrs = 1;
1076 } else {
1077 break;
1078 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001079 ++arg;
1080 --narg;
1081 }
1082
1083 if (narg > 0) {
1084 *path1 = *arg;
1085 ++arg;
1086 --narg;
1087 }
1088
1089 if (narg > 0) {
1090 *path2 = *arg;
1091 }
1092}
1093
Tao Bao175b7bb2015-03-29 11:22:34 -07001094static int adb_connect_command(const char* command) {
1095 int fd = adb_connect(command);
1096 if (fd != -1) {
1097 read_and_dump(fd);
1098 adb_close(fd);
1099 return 0;
1100 }
1101 fprintf(stderr, "Error: %s\n", adb_error());
1102 return 1;
1103}
1104
Dan Albertbac34742015-02-25 17:51:28 -08001105int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001106{
1107 char buf[4096];
1108 int no_daemon = 0;
1109 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001110 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001111 int persist = 0;
1112 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001113 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001114 const char* serial = NULL;
1115 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001116
1117 /* If defined, this should be an absolute path to
1118 * the directory containing all of the various system images
1119 * for a particular product. If not defined, and the adb
1120 * command requires this information, then the user must
1121 * specify the path using "-p".
1122 */
1123 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1124 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1125 gProductOutPath = NULL;
1126 }
1127 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1128
Nick Pellydb449262009-05-07 12:48:03 -07001129 serial = getenv("ANDROID_SERIAL");
1130
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001131 /* Validate and assign the server port */
1132 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1133 int server_port = DEFAULT_ADB_PORT;
1134 if (server_port_str && strlen(server_port_str) > 0) {
1135 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001136 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001137 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001138 "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 +01001139 server_port_str);
1140 return usage();
1141 }
1142 }
1143
1144 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001145 while (argc > 0) {
1146 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001147 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001148 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001149 no_daemon = 1;
1150 } else if (!strcmp(argv[0], "fork-server")) {
1151 /* this is a special flag used only when the ADB client launches the ADB Server */
1152 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001153 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001154 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001155 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001156 const char *product = NULL;
1157 if (argv[0][2] == '\0') {
1158 if (argc < 2) return usage();
1159 product = argv[1];
1160 argc--;
1161 argv++;
1162 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001163 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001164 }
1165 gProductOutPath = find_product_out_path(product);
1166 if (gProductOutPath == NULL) {
1167 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1168 product);
1169 return usage();
1170 }
1171 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1172 if (isdigit(argv[0][2])) {
1173 serial = argv[0] + 2;
1174 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001175 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001176 serial = argv[1];
1177 argc--;
1178 argv++;
1179 }
1180 } else if (!strcmp(argv[0],"-d")) {
1181 ttype = kTransportUsb;
1182 } else if (!strcmp(argv[0],"-e")) {
1183 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001184 } else if (!strcmp(argv[0],"-a")) {
1185 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001186 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001187 const char *hostname = NULL;
1188 if (argv[0][2] == '\0') {
1189 if (argc < 2) return usage();
1190 hostname = argv[1];
1191 argc--;
1192 argv++;
1193 } else {
1194 hostname = argv[0] + 2;
1195 }
1196 adb_set_tcp_name(hostname);
1197
Riley Andrews98f58e82014-12-05 17:37:24 -08001198 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001199 if (argv[0][2] == '\0') {
1200 if (argc < 2) return usage();
1201 server_port_str = argv[1];
1202 argc--;
1203 argv++;
1204 } else {
1205 server_port_str = argv[0] + 2;
1206 }
1207 if (strlen(server_port_str) > 0) {
1208 server_port = (int) strtol(server_port_str, NULL, 0);
1209 if (server_port <= 0 || server_port > 65535) {
1210 fprintf(stderr,
1211 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1212 server_port_str);
1213 return usage();
1214 }
1215 } else {
1216 fprintf(stderr,
1217 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1218 return usage();
1219 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 } else {
1221 /* out of recognized modifiers and flags */
1222 break;
1223 }
1224 argc--;
1225 argv++;
1226 }
1227
1228 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001229 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001230
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001231 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001232 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001233 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001234 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001235 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001236 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001237 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001238 fprintf(stderr,"* could not start server *\n");
1239 }
1240 return r;
1241 }
1242
Riley Andrews98f58e82014-12-05 17:37:24 -08001243 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001244 return usage();
1245 }
1246
Riley Andrewsc8514c82014-12-05 17:32:46 -08001247 /* handle wait-for-* prefix */
1248 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001249 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001250 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1251 if (ttype == kTransportUsb) {
1252 service = "wait-for-usb";
1253 } else if (ttype == kTransportLocal) {
1254 service = "wait-for-local";
1255 } else {
1256 service = "wait-for-any";
1257 }
1258 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001259
Riley Andrewsc8514c82014-12-05 17:32:46 -08001260 format_host_command(buf, sizeof buf, service, ttype, serial);
1261
1262 if (adb_command(buf)) {
1263 D("failure: %s *\n",adb_error());
1264 fprintf(stderr,"error: %s\n", adb_error());
1265 return 1;
1266 }
1267
1268 /* Allow a command to be run after wait-for-device,
1269 * e.g. 'adb wait-for-device shell'.
1270 */
1271 if (argc == 1) {
1272 return 0;
1273 }
1274
1275 /* Fall through */
1276 argc--;
1277 argv++;
1278 }
1279
1280 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001281 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001282 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001283 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001284 if (argc < 2)
1285 listopt = "";
1286 else if (argc == 2 && !strcmp(argv[1], "-l"))
1287 listopt = argv[1];
1288 else {
1289 fprintf(stderr, "Usage: adb devices [-l]\n");
1290 return 1;
1291 }
1292 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001293 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001294 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001295 printf("List of devices attached \n");
1296 printf("%s\n", tmp);
1297 return 0;
1298 } else {
1299 return 1;
1300 }
1301 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001302 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001303 char *tmp;
1304 if (argc != 2) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001305 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001306 return 1;
1307 }
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001308 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1309 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001310 if (tmp) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001311 printf("%s\n", tmp);
1312 return 0;
1313 } else {
1314 return 1;
1315 }
1316 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001317 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001318 char *tmp;
1319 if (argc > 2) {
1320 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1321 return 1;
1322 }
1323 if (argc == 2) {
1324 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1325 } else {
1326 snprintf(buf, sizeof buf, "host:disconnect:");
1327 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001328 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001329 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001330 printf("%s\n", tmp);
1331 return 0;
1332 } else {
1333 return 1;
1334 }
1335 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001336 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001337 return adb_send_emulator_command(argc, argv);
1338 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001339 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001340 char h = (argv[0][0] == 'h');
1341
1342 if (h) {
1343 printf("\x1b[41;33m");
1344 fflush(stdout);
1345 }
1346
Riley Andrews98f58e82014-12-05 17:37:24 -08001347 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001348 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001349 r = interactive_shell();
1350 if (h) {
1351 printf("\x1b[0m");
1352 fflush(stdout);
1353 }
1354 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001355 }
1356
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001357 std::string cmd = "shell:";
1358 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001359 argc -= 2;
1360 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001361 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001362 cmd += " ";
1363 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 }
1365
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001366 while (true) {
1367 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1368 int fd = adb_connect(cmd.c_str());
1369 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001370 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001371 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001372 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001373 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001374 adb_close(fd);
1375 r = 0;
1376 } else {
1377 fprintf(stderr,"error: %s\n", adb_error());
1378 r = -1;
1379 }
1380
Riley Andrews98f58e82014-12-05 17:37:24 -08001381 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001382 fprintf(stderr,"\n- waiting for device -\n");
1383 adb_sleep_ms(1000);
1384 do_cmd(ttype, serial, "wait-for-device", 0);
1385 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001386 if (h) {
1387 printf("\x1b[0m");
1388 fflush(stdout);
1389 }
JP Abgrall408fa572011-03-16 15:57:42 -07001390 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001391 return r;
1392 }
1393 }
1394 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001395 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001396 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001397
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001398 std::string cmd = "exec:";
1399 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001400 argc -= 2;
1401 argv += 2;
1402 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001403 cmd += " ";
1404 cmd += escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001405 }
1406
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001407 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001408 if (fd < 0) {
1409 fprintf(stderr, "error: %s\n", adb_error());
1410 return -1;
1411 }
1412
1413 if (exec_in) {
1414 copy_to_file(STDIN_FILENO, fd);
1415 } else {
1416 copy_to_file(fd, STDOUT_FILENO);
1417 }
1418
1419 adb_close(fd);
1420 return 0;
1421 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001422 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423 int fd;
1424 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001425 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001426 fprintf(stderr,"* server not running *\n");
1427 return 1;
1428 }
1429 return 0;
1430 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001431 else if (!strcmp(argv[0], "sideload")) {
1432 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001433 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001434 return 1;
1435 } else {
1436 return 0;
1437 }
1438 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001439 else if (!strcmp(argv[0], "remount") ||
1440 !strcmp(argv[0], "reboot") ||
1441 !strcmp(argv[0], "reboot-bootloader") ||
1442 !strcmp(argv[0], "tcpip") ||
1443 !strcmp(argv[0], "usb") ||
1444 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001445 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001446 !strcmp(argv[0], "disable-verity") ||
1447 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001448 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001449 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001450 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001451 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001452 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001453 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001454 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001455 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001456 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001457 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001458 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001459 if (argc != 1) return usage();
1460 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001461 return 0;
1462 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001463 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001464 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001465 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001466 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001467 char remove = 0;
1468 char remove_all = 0;
1469 char list = 0;
1470 char no_rebind = 0;
1471
1472 // Parse options here.
1473 while (argc > 1 && argv[1][0] == '-') {
1474 if (!strcmp(argv[1], "--list"))
1475 list = 1;
1476 else if (!strcmp(argv[1], "--remove"))
1477 remove = 1;
1478 else if (!strcmp(argv[1], "--remove-all"))
1479 remove_all = 1;
1480 else if (!strcmp(argv[1], "--no-rebind"))
1481 no_rebind = 1;
1482 else {
1483 return usage();
1484 }
1485 argc--;
1486 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001487 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001488
1489 // Ensure we can only use one option at a time.
1490 if (list + remove + remove_all + no_rebind > 1) {
1491 return usage();
1492 }
1493
1494 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001495 if (reverse) {
1496 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001497 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001498 if (serial) {
1499 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1500 serial);
1501 } else if (ttype == kTransportUsb) {
1502 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1503 } else if (ttype == kTransportLocal) {
1504 snprintf(host_prefix, sizeof host_prefix, "host-local");
1505 } else {
1506 snprintf(host_prefix, sizeof host_prefix, "host");
1507 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001508 }
1509
1510 // Implement forward --list
1511 if (list) {
1512 if (argc != 1)
1513 return usage();
1514 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1515 char* forwards = adb_query(buf);
1516 if (forwards == NULL) {
1517 fprintf(stderr, "error: %s\n", adb_error());
1518 return 1;
1519 }
1520 printf("%s", forwards);
1521 free(forwards);
1522 return 0;
1523 }
1524
1525 // Implement forward --remove-all
1526 else if (remove_all) {
1527 if (argc != 1)
1528 return usage();
1529 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1530 }
1531
1532 // Implement forward --remove <local>
1533 else if (remove) {
1534 if (argc != 2)
1535 return usage();
1536 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1537 }
1538 // Or implement one of:
1539 // forward <local> <remote>
1540 // forward --no-rebind <local> <remote>
1541 else
1542 {
1543 if (argc != 3)
1544 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001545 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001546 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1547 }
1548
Riley Andrews98f58e82014-12-05 17:37:24 -08001549 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001550 fprintf(stderr,"error: %s\n", adb_error());
1551 return 1;
1552 }
1553 return 0;
1554 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001555 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001556 else if (!strcmp(argv[0], "ls")) {
1557 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001558 return do_sync_ls(argv[1]);
1559 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001560 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001561 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001562 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001563 const char* lpath = NULL, *rpath = NULL;
1564
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001565 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001566
1567 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001568 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001569 }
1570
1571 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001572 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001573 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001574 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001575 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001576 const char* rpath = NULL, *lpath = ".";
1577
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001578 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001579
1580 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001581 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001582 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001583
1584 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001585 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001586 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001587 if (argc < 2) return usage();
1588 return install_app(ttype, serial, argc, argv);
1589 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001590 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001591 if (argc < 2) return usage();
1592 return install_multiple_app(ttype, serial, argc, argv);
1593 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001594 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001595 if (argc < 2) return usage();
1596 return uninstall_app(ttype, serial, argc, argv);
1597 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001598 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001599 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001600 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1601
Anthony Newnam705c9442010-02-22 08:36:49 -06001602 int listonly = 0;
1603
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001604 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001605 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001606 /* No local path was specified. */
1607 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001608 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1609 listonly = 1;
1610 if (argc == 3) {
1611 srcarg = argv[2];
1612 } else {
1613 srcarg = NULL;
1614 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001615 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001616 /* A local path or "android"/"data" arg was specified. */
1617 srcarg = argv[1];
1618 } else {
1619 return usage();
1620 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001621 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1622 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001623 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624
Elliott Hughesec7a6672015-03-16 21:58:32 +00001625 if (system_srcpath != NULL)
1626 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001627 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001628 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001629 if(ret == 0 && oem_srcpath != NULL)
1630 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001631 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001632 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633
Elliott Hughesec7a6672015-03-16 21:58:32 +00001634 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001635 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001636 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637 free(data_srcpath);
1638 return ret;
1639 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001640 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001641 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001642 !strcmp(argv[0],"get-serialno") ||
1643 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001644 {
1645 char *tmp;
1646
1647 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1648 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001649 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001650 printf("%s\n", tmp);
1651 return 0;
1652 } else {
1653 return 1;
1654 }
1655 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001656 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001657 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001658 status_window(ttype, serial);
1659 return 0;
1660 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001661 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001662 return logcat(ttype, serial, argc, argv);
1663 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001664 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001665 return ppp(argc, argv);
1666 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001667 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001668 return adb_connect("host:start-server");
1669 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001670 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001671 return backup(argc, argv);
1672 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001673 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001674 return restore(argc, argv);
1675 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001676 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001677 if (argc < 2) return usage();
1678 return adb_auth_keygen(argv[1]);
1679 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001680 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001681 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001683 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001684 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001685 help();
1686 return 0;
1687 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001688 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001689 version(stdout);
1690 return 0;
1691 }
1692
1693 usage();
1694 return 1;
1695}
1696
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001697#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001698static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001699{
Dan Albertbac34742015-02-25 17:51:28 -08001700 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001701 int argc;
1702 va_list ap;
1703
1704 va_start(ap, cmd);
1705 argc = 0;
1706
1707 if (serial) {
1708 argv[argc++] = "-s";
1709 argv[argc++] = serial;
1710 } else if (ttype == kTransportUsb) {
1711 argv[argc++] = "-d";
1712 } else if (ttype == kTransportLocal) {
1713 argv[argc++] = "-e";
1714 }
1715
1716 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001717 while(argc < MAX_ARGV_LENGTH &&
1718 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1719 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001720 va_end(ap);
1721
1722#if 0
1723 int n;
1724 fprintf(stderr,"argc = %d\n",argc);
1725 for(n = 0; n < argc; n++) {
1726 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1727 }
1728#endif
1729
1730 return adb_commandline(argc, argv);
1731}
1732
1733int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001734 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1735 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001736{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001737 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001738 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001739
1740 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001741 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001742 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001743 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001744 oem_srcdir = product_file("oem");
1745 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001746 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1747 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001748 // Check if oem partition exists.
1749 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1750 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001751 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001752 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1753 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001754 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001755 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001756 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001757 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001758 } else if(strcmp(srcarg, "vendor") == 0) {
1759 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001760 } else if(strcmp(srcarg, "oem") == 0) {
1761 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001762 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001763 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001764 return 1;
1765 }
1766 }
1767
Elliott Hughesec7a6672015-03-16 21:58:32 +00001768 if(system_srcdir_out != NULL)
1769 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001770 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001771 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001772
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001773 if(vendor_srcdir_out != NULL)
1774 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001775 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001776 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001777
Elliott Hughesec7a6672015-03-16 21:58:32 +00001778 if(oem_srcdir_out != NULL)
1779 *oem_srcdir_out = oem_srcdir;
1780 else
1781 free(oem_srcdir);
1782
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001783 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001784 *data_srcdir_out = data_srcdir;
1785 else
1786 free(data_srcdir);
1787
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001788 return 0;
1789}
1790
Dan Albertbac34742015-02-25 17:51:28 -08001791static int pm_command(transport_type transport, const char* serial,
1792 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001793{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001794 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001795
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001796 while (argc-- > 0) {
1797 cmd += " ";
1798 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001799 }
1800
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001801 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 return 0;
1803}
1804
Dan Albertbac34742015-02-25 17:51:28 -08001805int uninstall_app(transport_type transport, const char* serial, int argc,
1806 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001807{
1808 /* if the user choose the -k option, we refuse to do it until devices are
1809 out with the option to uninstall the remaining data somehow (adb/ui) */
1810 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1811 {
1812 printf(
1813 "The -k option uninstalls the application while retaining the data/cache.\n"
1814 "At the moment, there is no way to remove the remaining data.\n"
1815 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1816 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1817 return -1;
1818 }
1819
1820 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1821 return pm_command(transport, serial, argc, argv);
1822}
1823
Dan Albertbac34742015-02-25 17:51:28 -08001824static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001825{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001826 std::string cmd = "shell:rm -f " + escape_arg(filename);
1827 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001828 return 0;
1829}
1830
Kenny Root597ea5b2011-08-05 11:19:45 -07001831static const char* get_basename(const char* filename)
1832{
1833 const char* basename = adb_dirstop(filename);
1834 if (basename) {
1835 basename++;
1836 return basename;
1837 } else {
1838 return filename;
1839 }
1840}
1841
Dan Albertbac34742015-02-25 17:51:28 -08001842int install_app(transport_type transport, const char* serial, int argc,
1843 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001844{
1845 static const char *const DATA_DEST = "/data/local/tmp/%s";
1846 static const char *const SD_DEST = "/sdcard/tmp/%s";
1847 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001848 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001849 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001850
1851 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001852 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001853 where = SD_DEST;
1854 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001855 }
1856
Jeff Sharkey960df972014-06-09 17:30:57 -07001857 // Find last APK argument.
1858 // All other arguments passed through verbatim.
1859 int last_apk = -1;
1860 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001861 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001862 char* dot = strrchr(file, '.');
1863 if (dot && !strcasecmp(dot, ".apk")) {
1864 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1865 fprintf(stderr, "Invalid APK file: %s\n", file);
1866 return -1;
1867 }
1868
1869 last_apk = i;
1870 break;
1871 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001872 }
1873
Jeff Sharkey960df972014-06-09 17:30:57 -07001874 if (last_apk == -1) {
1875 fprintf(stderr, "Missing APK file\n");
1876 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001877 }
1878
Dan Albertbac34742015-02-25 17:51:28 -08001879 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001880 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001881 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001882 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001883 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001884 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001885 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001886 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001887 }
1888
1889 pm_command(transport, serial, argc, argv);
1890
Kenny Root60733e92012-03-26 16:14:02 -07001891cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001892 delete_file(transport, serial, apk_dest);
1893 return err;
1894}
1895
Dan Albertbac34742015-02-25 17:51:28 -08001896int install_multiple_app(transport_type transport, const char* serial, int argc,
1897 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001898{
Jeff Sharkey960df972014-06-09 17:30:57 -07001899 int i;
1900 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001901 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001902
1903 // Find all APK arguments starting at end.
1904 // All other arguments passed through verbatim.
1905 int first_apk = -1;
1906 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001907 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001908 char* dot = strrchr(file, '.');
1909 if (dot && !strcasecmp(dot, ".apk")) {
1910 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1911 fprintf(stderr, "Invalid APK file: %s\n", file);
1912 return -1;
1913 }
1914
1915 total_size += sb.st_size;
1916 first_apk = i;
1917 } else {
1918 break;
1919 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001920 }
1921
Jeff Sharkey960df972014-06-09 17:30:57 -07001922 if (first_apk == -1) {
1923 fprintf(stderr, "Missing APK file\n");
1924 return 1;
1925 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001926
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001927 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001928 for (i = 1; i < first_apk; i++) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001929 cmd += " ";
1930 cmd += escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001931 }
1932
1933 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001934 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001935 if (fd < 0) {
1936 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1937 return -1;
1938 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001939 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001940 read_status_line(fd, buf, sizeof(buf));
1941 adb_close(fd);
1942
1943 int session_id = -1;
1944 if (!strncmp("Success", buf, 7)) {
1945 char* start = strrchr(buf, '[');
1946 char* end = strrchr(buf, ']');
1947 if (start && end) {
1948 *end = '\0';
1949 session_id = strtol(start + 1, NULL, 10);
1950 }
1951 }
1952 if (session_id < 0) {
1953 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001954 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001955 return -1;
1956 }
1957
1958 // Valid session, now stream the APKs
1959 int success = 1;
1960 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001961 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001962 if (stat(file, &sb) == -1) {
1963 fprintf(stderr, "Failed to stat %s\n", file);
1964 success = 0;
1965 goto finalize_session;
1966 }
1967
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001968 std::string cmd = android::base::StringPrintf(
1969 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1970 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001971
1972 int localFd = adb_open(file, O_RDONLY);
1973 if (localFd < 0) {
1974 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1975 success = 0;
1976 goto finalize_session;
1977 }
1978
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001979 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001980 if (remoteFd < 0) {
1981 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1982 adb_close(localFd);
1983 success = 0;
1984 goto finalize_session;
1985 }
1986
1987 copy_to_file(localFd, remoteFd);
1988 read_status_line(remoteFd, buf, sizeof(buf));
1989
1990 adb_close(localFd);
1991 adb_close(remoteFd);
1992
1993 if (strncmp("Success", buf, 7)) {
1994 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001995 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001996 success = 0;
1997 goto finalize_session;
1998 }
1999 }
2000
2001finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002002 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002003 if (success) {
2004 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2005 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002006 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002007 }
2008
2009 fd = adb_connect(buf);
2010 if (fd < 0) {
2011 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2012 return -1;
2013 }
2014 read_status_line(fd, buf, sizeof(buf));
2015 adb_close(fd);
2016
2017 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002018 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002019 return 0;
2020 } else {
2021 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002022 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002023 return -1;
2024 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002025}