blob: 4538b048b17ff426f052c443d4eb9e71119d2641 [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 Albert76649012015-02-24 15:51:19 -080017#include <assert.h>
18#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080020#include <limits.h>
21#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080022#include <stdint.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
Yabin Cuid325e862014-11-17 14:48:25 -080029#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080031#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032#endif
33
Dan Albert76649012015-02-24 15:51:19 -080034#include "sysdeps.h"
35
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036#define TRACE_TAG TRACE_ADB
37#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080038#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080039#include "adb_client.h"
40#include "adb_io.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#include "file_sync_service.h"
42
Dan Albertbac34742015-02-25 17:51:28 -080043static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080044
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +000046 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
47 char **oem_srcdir_out);
Dan Albertbac34742015-02-25 17:51:28 -080048int install_app(transport_type transport, const char* serial, int argc,
49 const char** argv);
50int install_multiple_app(transport_type transport, const char* serial, int argc,
51 const char** argv);
52int uninstall_app(transport_type transport, const char* serial, int argc,
53 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054
55static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080056extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080057
58static char *product_file(const char *extra)
59{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060 if (gProductOutPath == NULL) {
61 fprintf(stderr, "adb: Product directory not specified; "
62 "use -p or define ANDROID_PRODUCT_OUT\n");
63 exit(1);
64 }
65
Dan Albertbac34742015-02-25 17:51:28 -080066 int n = strlen(gProductOutPath) + strlen(extra) + 2;
67 char* x = reinterpret_cast<char*>(malloc(n));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080068 if (x == 0) {
69 fprintf(stderr, "adb: Out of memory (product_file())\n");
70 exit(1);
71 }
72
73 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
74 return x;
75}
76
77void version(FILE * out) {
78 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
79 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
80}
81
82void help()
83{
84 version(stderr);
85
86 fprintf(stderr,
87 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080088 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080089 " -d - directs command to the only connected USB device\n"
90 " returns an error if more than one USB device is present.\n"
91 " -e - directs command to the only running emulator.\n"
92 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070093 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070094 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070095 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096 " -p <product name or path> - simple product name like 'sooner', or\n"
97 " a relative/absolute path to a product\n"
98 " out directory like 'out/target/product/sooner'.\n"
99 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
100 " environment variable is used, which must\n"
101 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800102 " -H - Name of adb server host (default: localhost)\n"
103 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700104 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700105 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400106 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
107 " Port 5555 is used by default if no port number is specified.\n"
108 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
109 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200110 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400111 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800112 "\n"
113 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700114 " adb push [-p] <local> <remote>\n"
115 " - copy file/dir to device\n"
116 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700117 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700118 " - copy file/dir from device\n"
119 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700120 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600122 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800123 " (see 'adb help all')\n"
124 " adb shell - run remote shell interactively\n"
125 " adb shell <command> - run remote shell command\n"
126 " adb emu <command> - run emulator console command\n"
127 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100128 " adb forward --list - list all forward socket connections.\n"
129 " the format is a list of lines with the following format:\n"
130 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800131 " adb forward <local> <remote> - forward socket connections\n"
132 " forward specs are one of: \n"
133 " tcp:<port>\n"
134 " localabstract:<unix domain socket name>\n"
135 " localreserved:<unix domain socket name>\n"
136 " localfilesystem:<unix domain socket name>\n"
137 " dev:<character device name>\n"
138 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100139 " adb forward --no-rebind <local> <remote>\n"
140 " - same as 'adb forward <local> <remote>' but fails\n"
141 " if <local> is already forwarded\n"
142 " adb forward --remove <local> - remove a specific forward socket connection\n"
143 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100144 " adb reverse --list - list all reverse socket connections from device\n"
145 " adb reverse <remote> <local> - reverse socket connections\n"
146 " reverse specs are one of:\n"
147 " tcp:<port>\n"
148 " localabstract:<unix domain socket name>\n"
149 " localreserved:<unix domain socket name>\n"
150 " localfilesystem:<unix domain socket name>\n"
151 " adb reverse --norebind <remote> <local>\n"
152 " - same as 'adb reverse <remote> <local>' but fails\n"
153 " if <remote> is already reversed.\n"
154 " adb reverse --remove <remote>\n"
155 " - remove a specific reversed socket connection\n"
156 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700158 " adb install [-lrtsd] <file>\n"
159 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700160 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700161 " (-l: forward lock application)\n"
162 " (-r: replace existing application)\n"
163 " (-t: allow test packages)\n"
164 " (-s: install application on sdcard)\n"
165 " (-d: allow version code downgrade)\n"
166 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 " adb uninstall [-k] <package> - remove this app package from the device\n"
168 " ('-k' means keep the data and cache directories)\n"
169 " adb bugreport - return all information from the device\n"
170 " that should be included in a bug report.\n"
171 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800172 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700173 " - write an archive of the device's data to <file>.\n"
174 " If no -f option is supplied then the data is written\n"
175 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700177 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800178 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
179 " (aka .obb) files associated with each application; the default\n"
180 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (-shared|-noshared enable/disable backup of the device's\n"
182 " shared storage / SD card contents; the default is noshared.)\n"
183 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700184 " (-system|-nosystem toggles whether -all automatically includes\n"
185 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 " (<packages...> is the list of applications to be backed up. If\n"
187 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700188 " list is optional. Applications explicitly given on the\n"
189 " command line will be included even if -nosystem would\n"
190 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700191 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700192 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700193 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800194 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
195 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800196 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
197 " and the public key is stored in <file>.pub. Any existing files\n"
198 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800199 " adb help - show this help message\n"
200 " adb version - show version num\n"
201 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800202 "scripting:\n"
203 " adb wait-for-device - block until device is online\n"
204 " adb start-server - ensure that there is a server running\n"
205 " adb kill-server - kill the server if it is running\n"
206 " adb get-state - prints: offline | bootloader | device\n"
207 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700208 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000210 " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400211 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800212 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700213 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500214 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800215 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000216 " 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 -0800217 "networking:\n"
218 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500219 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800220 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
221 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
222 "\n"
223 "adb sync notes: adb sync [ <directory> ]\n"
224 " <localdir> can be interpreted in several ways:\n"
225 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000226 " - 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 -0800227 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000228 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000230 "\n"
231 "environmental variables:\n"
232 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
233 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
234 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
235 " 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 -0800236 );
237}
238
239int usage()
240{
241 help();
242 return 1;
243}
244
Yabin Cuid325e862014-11-17 14:48:25 -0800245#if defined(_WIN32)
246
247// Windows does not have <termio.h>.
248static void stdin_raw_init(int fd) {
249
250}
251
252static void stdin_raw_restore(int fd) {
253
254}
255
256#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257static struct termios tio_save;
258
259static void stdin_raw_init(int fd)
260{
261 struct termios tio;
262
263 if(tcgetattr(fd, &tio)) return;
264 if(tcgetattr(fd, &tio_save)) return;
265
266 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
267
268 /* no timeout but request at least one character per read */
269 tio.c_cc[VTIME] = 0;
270 tio.c_cc[VMIN] = 1;
271
272 tcsetattr(fd, TCSANOW, &tio);
273 tcflush(fd, TCIFLUSH);
274}
275
276static void stdin_raw_restore(int fd)
277{
278 tcsetattr(fd, TCSANOW, &tio_save);
279 tcflush(fd, TCIFLUSH);
280}
281#endif
282
283static void read_and_dump(int fd)
284{
285 char buf[4096];
286 int len;
287
288 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700291 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 if(len == 0) {
293 break;
294 }
295
296 if(len < 0) {
297 if(errno == EINTR) continue;
298 break;
299 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400300 fwrite(buf, 1, len, stdout);
301 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800302 }
303}
304
Jeff Sharkey960df972014-06-09 17:30:57 -0700305static void read_status_line(int fd, char* buf, size_t count)
306{
307 count--;
308 while (count > 0) {
309 int len = adb_read(fd, buf, count);
310 if (len == 0) {
311 break;
312 } else if (len < 0) {
313 if (errno == EINTR) continue;
314 break;
315 }
316
317 buf += len;
318 count -= len;
319 }
320 *buf = '\0';
321}
322
Christopher Tated2f54152011-04-21 12:53:28 -0700323static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700324 const size_t BUFSIZE = 32 * 1024;
325 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700326 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700327 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700328
329 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800330
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700331 if (inFd == STDIN_FILENO) {
332 stdin_raw_init(STDIN_FILENO);
333 }
Yabin Cuid325e862014-11-17 14:48:25 -0800334
Christopher Tated2f54152011-04-21 12:53:28 -0700335 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700336 if (inFd == STDIN_FILENO) {
337 len = unix_read(inFd, buf, BUFSIZE);
338 } else {
339 len = adb_read(inFd, buf, BUFSIZE);
340 }
Christopher Tated2f54152011-04-21 12:53:28 -0700341 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700342 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700343 break;
344 }
345 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700346 if (errno == EINTR) {
347 D("copy_to_file() : EINTR, retrying\n");
348 continue;
349 }
Christopher Tated2f54152011-04-21 12:53:28 -0700350 D("copy_to_file() : error %d\n", errno);
351 break;
352 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700353 if (outFd == STDOUT_FILENO) {
354 fwrite(buf, 1, len, stdout);
355 fflush(stdout);
356 } else {
357 adb_write(outFd, buf, len);
358 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700359 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700360 }
Yabin Cuid325e862014-11-17 14:48:25 -0800361
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700362 if (inFd == STDIN_FILENO) {
363 stdin_raw_restore(STDIN_FILENO);
364 }
Yabin Cuid325e862014-11-17 14:48:25 -0800365
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700366 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700367 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700368}
369
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370static void *stdin_read_thread(void *x)
371{
372 int fd, fdi;
373 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 int r, n;
375 int state = 0;
376
377 int *fds = (int*) x;
378 fd = fds[0];
379 fdi = fds[1];
380 free(fds);
381
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800382 for(;;) {
383 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700384 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700386 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800387 if(r == 0) break;
388 if(r < 0) {
389 if(errno == EINTR) continue;
390 break;
391 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400392 for(n = 0; n < r; n++){
393 switch(buf[n]) {
394 case '\n':
395 state = 1;
396 break;
397 case '\r':
398 state = 1;
399 break;
400 case '~':
401 if(state == 1) state++;
402 break;
403 case '.':
404 if(state == 2) {
405 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400406 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400409 default:
410 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 r = adb_write(fd, buf, r);
414 if(r <= 0) {
415 break;
416 }
417 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800418 return 0;
419}
420
421int interactive_shell(void)
422{
423 adb_thread_t thr;
424 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425
426 fd = adb_connect("shell:");
427 if(fd < 0) {
428 fprintf(stderr,"error: %s\n", adb_error());
429 return 1;
430 }
431 fdi = 0; //dup(0);
432
Dan Albertbac34742015-02-25 17:51:28 -0800433 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434 fds[0] = fd;
435 fds[1] = fdi;
436
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 adb_thread_create(&thr, stdin_read_thread, fds);
439 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 return 0;
442}
443
444
445static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
446{
447 if (serial) {
448 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
449 } else {
450 const char* prefix = "host";
451 if (ttype == kTransportUsb)
452 prefix = "host-usb";
453 else if (ttype == kTransportLocal)
454 prefix = "host-local";
455
456 snprintf(buffer, buflen, "%s:%s", prefix, command);
457 }
458}
459
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100460int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800461 unsigned progress)
462{
463 char buf[4096];
464 unsigned total;
465 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800466
467 sprintf(buf,"%s:%d", service, sz);
468 fd = adb_connect(buf);
469 if(fd < 0) {
470 fprintf(stderr,"error: %s\n", adb_error());
471 return -1;
472 }
473
474 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800475 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800476
477 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800478 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800479
480 if(progress) {
481 char *x = strrchr(service, ':');
482 if(x) service = x + 1;
483 }
484
485 while(sz > 0) {
486 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800487 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800488 adb_status(fd);
489 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
490 return -1;
491 }
492 sz -= xfer;
493 ptr += xfer;
494 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100495 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800496 fflush(stdout);
497 }
498 }
499 if(progress) {
500 printf("\n");
501 }
502
Dan Albertcc731cc2015-02-24 21:26:58 -0800503 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800504 fprintf(stderr,"* error reading response *\n");
505 adb_close(fd);
506 return -1;
507 }
508 if(memcmp(buf, "OKAY", 4)) {
509 buf[4] = 0;
510 fprintf(stderr,"* error response '%s' *\n", buf);
511 adb_close(fd);
512 return -1;
513 }
514
515 adb_close(fd);
516 return 0;
517}
518
519
520int adb_download(const char *service, const char *fn, unsigned progress)
521{
522 void *data;
523 unsigned sz;
524
525 data = load_file(fn, &sz);
526 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100527 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800528 return -1;
529 }
530
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100531 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800532 free(data);
533 return status;
534}
535
Doug Zongker71fe5842014-06-26 15:35:36 -0700536#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
537
538/*
539 * The sideload-host protocol serves the data in a file (given on the
540 * command line) to the client, using a simple protocol:
541 *
542 * - The connect message includes the total number of bytes in the
543 * file and a block size chosen by us.
544 *
545 * - The other side sends the desired block number as eight decimal
546 * digits (eg "00000023" for block 23). Blocks are numbered from
547 * zero.
548 *
549 * - We send back the data of the requested block. The last block is
550 * likely to be partial; when the last block is requested we only
551 * send the part of the block that exists, it's not padded up to the
552 * block size.
553 *
554 * - When the other side sends "DONEDONE" instead of a block number,
555 * we hang up.
556 */
557int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700558 unsigned sz;
559 size_t xfer = 0;
560 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800561 int last_percent = -1;
562 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700563
564 printf("loading: '%s'", fn);
565 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800566 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700567 if (data == 0) {
568 printf("\n");
569 fprintf(stderr, "* cannot read '%s' *\n", fn);
570 return -1;
571 }
572
573 char buf[100];
574 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
575 int fd = adb_connect(buf);
576 if (fd < 0) {
577 // Try falling back to the older sideload method. Maybe this
578 // is an older device that doesn't support sideload-host.
579 printf("\n");
580 status = adb_download_buffer("sideload", fn, data, sz, 1);
581 goto done;
582 }
583
Spencer Lowf055c192015-01-25 14:40:16 -0800584 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700585
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700586 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800587 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700588 fprintf(stderr, "* failed to read command: %s\n", adb_error());
589 status = -1;
590 goto done;
591 }
592
593 if (strncmp("DONEDONE", buf, 8) == 0) {
594 status = 0;
595 break;
596 }
597
598 buf[8] = '\0';
599 int block = strtol(buf, NULL, 10);
600
601 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
602 if (offset >= sz) {
603 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
604 status = -1;
605 goto done;
606 }
607 uint8_t* start = data + offset;
608 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
609 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
610 if (offset_end > sz) {
611 to_write = sz - offset;
612 }
613
Dan Albertcc731cc2015-02-24 21:26:58 -0800614 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700615 adb_status(fd);
616 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
617 status = -1;
618 goto done;
619 }
620 xfer += to_write;
621
622 // For normal OTA packages, we expect to transfer every byte
623 // twice, plus a bit of overhead (one read during
624 // verification, one read of each byte for installation, plus
625 // extra access to things like the zip central directory).
626 // This estimate of the completion becomes 100% when we've
627 // transferred ~2.13 (=100/47) times the package size.
628 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
629 if (percent != last_percent) {
630 printf("\rserving: '%s' (~%d%%) ", fn, percent);
631 fflush(stdout);
632 last_percent = percent;
633 }
634 }
635
Colin Cross6d6a8982014-07-07 14:12:41 -0700636 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700637
638 done:
639 if (fd >= 0) adb_close(fd);
640 free(data);
641 return status;
642}
643
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800644static void status_window(transport_type ttype, const char* serial)
645{
646 char command[4096];
647 char *state = 0;
648 char *laststate = 0;
649
650 /* silence stderr */
651#ifdef _WIN32
652 /* XXX: TODO */
653#else
654 int fd;
655 fd = unix_open("/dev/null", O_WRONLY);
656 dup2(fd, 2);
657 adb_close(fd);
658#endif
659
660 format_host_command(command, sizeof command, "get-state", ttype, serial);
661
662 for(;;) {
663 adb_sleep_ms(250);
664
665 if(state) {
666 free(state);
667 state = 0;
668 }
669
670 state = adb_query(command);
671
672 if(state) {
673 if(laststate && !strcmp(state,laststate)){
674 continue;
675 } else {
676 if(laststate) free(laststate);
677 laststate = strdup(state);
678 }
679 }
680
681 printf("%c[2J%c[2H", 27, 27);
682 printf("Android Debug Bridge\n");
683 printf("State: %s\n", state ? state : "offline");
684 fflush(stdout);
685 }
686}
687
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700688static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700689{
690 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
691}
692
693/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700694static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800695{
696 const char *ts;
697 size_t alloc_len;
698 char *ret;
699 char *dest;
700
Jeff Sharkey7c460352014-06-10 16:22:17 -0700701 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700702 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700704 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800705 alloc_len++;
706 }
707 }
708
Jeff Sharkey7c460352014-06-10 16:22:17 -0700709 if (alloc_len == 0) {
710 // Preserve empty arguments
711 ret = (char *) malloc(3);
712 ret[0] = '\"';
713 ret[1] = '\"';
714 ret[2] = '\0';
715 return ret;
716 }
717
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700718 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800719 dest = ret;
720
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700721 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700722 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800723 *dest++ = '\\';
724 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725 *dest++ = *ts;
726 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800727 *dest++ = '\0';
728
729 return ret;
730}
731
732/**
733 * Run ppp in "notty" mode against a resource listed as the first parameter
734 * eg:
735 *
736 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
737 *
738 */
Dan Albertbac34742015-02-25 17:51:28 -0800739int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800740{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800741#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800742 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
743 return -1;
744#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800745 pid_t pid;
746 int fd;
747
748 if (argc < 2) {
749 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
750 argv[0]);
751
752 return 1;
753 }
754
Dan Albertbac34742015-02-25 17:51:28 -0800755 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800756 fd = adb_connect(adb_service_name);
757
758 if(fd < 0) {
759 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
760 adb_service_name, adb_error());
761 return 1;
762 }
763
764 pid = fork();
765
766 if (pid < 0) {
767 perror("from fork()");
768 return 1;
769 } else if (pid == 0) {
770 int err;
771 int i;
772 const char **ppp_args;
773
774 // copy args
775 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
776 ppp_args[0] = "pppd";
777 for (i = 2 ; i < argc ; i++) {
778 //argv[2] and beyond become ppp_args[1] and beyond
779 ppp_args[i - 1] = argv[i];
780 }
781 ppp_args[i-1] = NULL;
782
783 // child side
784
785 dup2(fd, STDIN_FILENO);
786 dup2(fd, STDOUT_FILENO);
787 adb_close(STDERR_FILENO);
788 adb_close(fd);
789
790 err = execvp("pppd", (char * const *)ppp_args);
791
792 if (err < 0) {
793 perror("execing pppd");
794 }
795 exit(-1);
796 } else {
797 // parent side
798
799 adb_close(fd);
800 return 0;
801 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800802#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800803}
804
Dan Albertbac34742015-02-25 17:51:28 -0800805static int send_shellcommand(transport_type transport, const char* serial,
806 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800807{
808 int fd, ret;
809
810 for(;;) {
811 fd = adb_connect(buf);
812 if(fd >= 0)
813 break;
814 fprintf(stderr,"- waiting for device -\n");
815 adb_sleep_ms(1000);
816 do_cmd(transport, serial, "wait-for-device", 0);
817 }
818
819 read_and_dump(fd);
820 ret = adb_close(fd);
821 if (ret)
822 perror("close");
823
824 return ret;
825}
826
Dan Albertbac34742015-02-25 17:51:28 -0800827static int logcat(transport_type transport, const char* serial, int argc,
828 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800829{
830 char buf[4096];
831
832 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700833 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800834
835 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700836 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800837 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700838 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700839 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800840
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700841 if (!strcmp(argv[0], "longcat")) {
842 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800843 }
844
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800845 argc -= 1;
846 argv += 1;
847 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700848 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700849 strncat(buf, " ", sizeof(buf) - 1);
850 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800851 free(quoted);
852 }
853
854 send_shellcommand(transport, serial, buf);
855 return 0;
856}
857
Mark Salyzyn60299df2014-04-30 09:10:31 -0700858static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800859{
860 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700861 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800862
863 for(;;) {
864 x = adb_dirstart(x);
865 if(x == 0) return 0;
866 *x = 0;
867 ret = adb_mkdir(path, 0775);
868 *x = OS_PATH_SEPARATOR;
869 if((ret < 0) && (errno != EEXIST)) {
870 return ret;
871 }
872 x++;
873 }
874 return 0;
875}
876
Dan Albertbac34742015-02-25 17:51:28 -0800877static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700878 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800879 char default_name[32];
880 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700881 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700882 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700883
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700884 /* find, extract, and use any -f argument */
885 for (i = 1; i < argc; i++) {
886 if (!strcmp("-f", argv[i])) {
887 if (i == argc-1) {
888 fprintf(stderr, "adb: -f passed with no filename\n");
889 return usage();
890 }
891 filename = argv[i+1];
892 for (j = i+2; j <= argc; ) {
893 argv[i++] = argv[j++];
894 }
895 argc -= 2;
896 argv[argc] = NULL;
897 }
Christopher Tated2f54152011-04-21 12:53:28 -0700898 }
899
Christopher Tatebb86bc52011-08-22 17:12:08 -0700900 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
901 if (argc < 2) return usage();
902
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800903 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700904 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800905 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700906 if (outFd < 0) {
907 fprintf(stderr, "adb: unable to open file %s\n", filename);
908 return -1;
909 }
910
911 snprintf(buf, sizeof(buf), "backup");
912 for (argc--, argv++; argc; argc--, argv++) {
913 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
914 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
915 }
916
917 D("backup. filename=%s buf=%s\n", filename, buf);
918 fd = adb_connect(buf);
919 if (fd < 0) {
920 fprintf(stderr, "adb: unable to connect for backup\n");
921 adb_close(outFd);
922 return -1;
923 }
924
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800925 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700926 copy_to_file(fd, outFd);
927
928 adb_close(fd);
929 adb_close(outFd);
930 return 0;
931}
932
Dan Albertbac34742015-02-25 17:51:28 -0800933static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700934 const char* filename;
935 int fd, tarFd;
936
937 if (argc != 2) return usage();
938
939 filename = argv[1];
940 tarFd = adb_open(filename, O_RDONLY);
941 if (tarFd < 0) {
942 fprintf(stderr, "adb: unable to open file %s\n", filename);
943 return -1;
944 }
945
946 fd = adb_connect("restore:");
947 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700948 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700949 adb_close(tarFd);
950 return -1;
951 }
952
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800953 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700954 copy_to_file(tarFd, fd);
955
956 adb_close(fd);
957 adb_close(tarFd);
958 return 0;
959}
960
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800961#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
962static int top_works(const char *top)
963{
964 if (top != NULL && adb_is_absolute_host_path(top)) {
965 char path_buf[PATH_MAX];
966 snprintf(path_buf, sizeof(path_buf),
967 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
968 return access(path_buf, F_OK) == 0;
969 }
970 return 0;
971}
972
973static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
974{
975 strcpy(path_buf, indir);
976 while (1) {
977 if (top_works(path_buf)) {
978 return path_buf;
979 }
980 char *s = adb_dirstop(path_buf);
981 if (s != NULL) {
982 *s = '\0';
983 } else {
984 path_buf[0] = '\0';
985 return NULL;
986 }
987 }
988}
989
990static char *find_top(char path_buf[PATH_MAX])
991{
992 char *top = getenv("ANDROID_BUILD_TOP");
993 if (top != NULL && top[0] != '\0') {
994 if (!top_works(top)) {
995 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
996 return NULL;
997 }
998 } else {
999 top = getenv("TOP");
1000 if (top != NULL && top[0] != '\0') {
1001 if (!top_works(top)) {
1002 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1003 return NULL;
1004 }
1005 } else {
1006 top = NULL;
1007 }
1008 }
1009
1010 if (top != NULL) {
1011 /* The environment pointed to a top directory that works.
1012 */
1013 strcpy(path_buf, top);
1014 return path_buf;
1015 }
1016
1017 /* The environment didn't help. Walk up the tree from the CWD
1018 * to see if we can find the top.
1019 */
1020 char dir[PATH_MAX];
1021 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1022 if (top == NULL) {
1023 /* If the CWD isn't under a good-looking top, see if the
1024 * executable is.
1025 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001026 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001027 top = find_top_from(dir, path_buf);
1028 }
1029 return top;
1030}
1031
1032/* <hint> may be:
1033 * - A simple product name
1034 * e.g., "sooner"
1035TODO: debug? sooner-debug, sooner:debug?
1036 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1037 * e.g., "out/target/product/sooner"
1038 * - An absolute path to the PRODUCT_OUT dir
1039 * e.g., "/src/device/out/target/product/sooner"
1040 *
1041 * Given <hint>, try to construct an absolute path to the
1042 * ANDROID_PRODUCT_OUT dir.
1043 */
1044static const char *find_product_out_path(const char *hint)
1045{
1046 static char path_buf[PATH_MAX];
1047
1048 if (hint == NULL || hint[0] == '\0') {
1049 return NULL;
1050 }
1051
1052 /* If it's already absolute, don't bother doing any work.
1053 */
1054 if (adb_is_absolute_host_path(hint)) {
1055 strcpy(path_buf, hint);
1056 return path_buf;
1057 }
1058
1059 /* If there are any slashes in it, assume it's a relative path;
1060 * make it absolute.
1061 */
1062 if (adb_dirstart(hint) != NULL) {
1063 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1064 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1065 return NULL;
1066 }
1067 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1068 fprintf(stderr, "adb: Couldn't assemble path\n");
1069 return NULL;
1070 }
1071 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1072 strcat(path_buf, hint);
1073 return path_buf;
1074 }
1075
1076 /* It's a string without any slashes. Try to do something with it.
1077 *
1078 * Try to find the root of the build tree, and build a PRODUCT_OUT
1079 * path from there.
1080 */
1081 char top_buf[PATH_MAX];
1082 const char *top = find_top(top_buf);
1083 if (top == NULL) {
1084 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1085 return NULL;
1086 }
1087//TODO: if we have a way to indicate debug, look in out/debug/target/...
1088 snprintf(path_buf, sizeof(path_buf),
1089 "%s" OS_PATH_SEPARATOR_STR
1090 "out" OS_PATH_SEPARATOR_STR
1091 "target" OS_PATH_SEPARATOR_STR
1092 "product" OS_PATH_SEPARATOR_STR
1093 "%s", top_buf, hint);
1094 if (access(path_buf, F_OK) < 0) {
1095 fprintf(stderr, "adb: Couldn't find a product dir "
1096 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1097 return NULL;
1098 }
1099 return path_buf;
1100}
1101
Dan Albertbac34742015-02-25 17:51:28 -08001102static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1103 char const **path2, int *show_progress,
1104 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001105 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001106 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001107
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001108 while (narg > 0) {
1109 if (!strcmp(*arg, "-p")) {
1110 *show_progress = 1;
1111 } else if (!strcmp(*arg, "-a")) {
1112 *copy_attrs = 1;
1113 } else {
1114 break;
1115 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001116 ++arg;
1117 --narg;
1118 }
1119
1120 if (narg > 0) {
1121 *path1 = *arg;
1122 ++arg;
1123 --narg;
1124 }
1125
1126 if (narg > 0) {
1127 *path2 = *arg;
1128 }
1129}
1130
Dan Albertbac34742015-02-25 17:51:28 -08001131int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001132{
1133 char buf[4096];
1134 int no_daemon = 0;
1135 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001136 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137 int persist = 0;
1138 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001140 const char* serial = NULL;
1141 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001142
1143 /* If defined, this should be an absolute path to
1144 * the directory containing all of the various system images
1145 * for a particular product. If not defined, and the adb
1146 * command requires this information, then the user must
1147 * specify the path using "-p".
1148 */
1149 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1150 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1151 gProductOutPath = NULL;
1152 }
1153 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1154
Nick Pellydb449262009-05-07 12:48:03 -07001155 serial = getenv("ANDROID_SERIAL");
1156
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001157 /* Validate and assign the server port */
1158 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1159 int server_port = DEFAULT_ADB_PORT;
1160 if (server_port_str && strlen(server_port_str) > 0) {
1161 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001162 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001163 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001164 "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 +01001165 server_port_str);
1166 return usage();
1167 }
1168 }
1169
1170 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001171 while (argc > 0) {
1172 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001173 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001174 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 no_daemon = 1;
1176 } else if (!strcmp(argv[0], "fork-server")) {
1177 /* this is a special flag used only when the ADB client launches the ADB Server */
1178 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001179 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001180 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001181 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001182 const char *product = NULL;
1183 if (argv[0][2] == '\0') {
1184 if (argc < 2) return usage();
1185 product = argv[1];
1186 argc--;
1187 argv++;
1188 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001189 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001190 }
1191 gProductOutPath = find_product_out_path(product);
1192 if (gProductOutPath == NULL) {
1193 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1194 product);
1195 return usage();
1196 }
1197 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1198 if (isdigit(argv[0][2])) {
1199 serial = argv[0] + 2;
1200 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001201 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001202 serial = argv[1];
1203 argc--;
1204 argv++;
1205 }
1206 } else if (!strcmp(argv[0],"-d")) {
1207 ttype = kTransportUsb;
1208 } else if (!strcmp(argv[0],"-e")) {
1209 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001210 } else if (!strcmp(argv[0],"-a")) {
1211 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001212 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001213 const char *hostname = NULL;
1214 if (argv[0][2] == '\0') {
1215 if (argc < 2) return usage();
1216 hostname = argv[1];
1217 argc--;
1218 argv++;
1219 } else {
1220 hostname = argv[0] + 2;
1221 }
1222 adb_set_tcp_name(hostname);
1223
Riley Andrews98f58e82014-12-05 17:37:24 -08001224 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001225 if (argv[0][2] == '\0') {
1226 if (argc < 2) return usage();
1227 server_port_str = argv[1];
1228 argc--;
1229 argv++;
1230 } else {
1231 server_port_str = argv[0] + 2;
1232 }
1233 if (strlen(server_port_str) > 0) {
1234 server_port = (int) strtol(server_port_str, NULL, 0);
1235 if (server_port <= 0 || server_port > 65535) {
1236 fprintf(stderr,
1237 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1238 server_port_str);
1239 return usage();
1240 }
1241 } else {
1242 fprintf(stderr,
1243 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1244 return usage();
1245 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001246 } else {
1247 /* out of recognized modifiers and flags */
1248 break;
1249 }
1250 argc--;
1251 argv++;
1252 }
1253
1254 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001255 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001256
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001257 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001259 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001260 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001261 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001262 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001263 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001264 fprintf(stderr,"* could not start server *\n");
1265 }
1266 return r;
1267 }
1268
Riley Andrews98f58e82014-12-05 17:37:24 -08001269 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001270 return usage();
1271 }
1272
Riley Andrewsc8514c82014-12-05 17:32:46 -08001273 /* handle wait-for-* prefix */
1274 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001275 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001276 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1277 if (ttype == kTransportUsb) {
1278 service = "wait-for-usb";
1279 } else if (ttype == kTransportLocal) {
1280 service = "wait-for-local";
1281 } else {
1282 service = "wait-for-any";
1283 }
1284 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001285
Riley Andrewsc8514c82014-12-05 17:32:46 -08001286 format_host_command(buf, sizeof buf, service, ttype, serial);
1287
1288 if (adb_command(buf)) {
1289 D("failure: %s *\n",adb_error());
1290 fprintf(stderr,"error: %s\n", adb_error());
1291 return 1;
1292 }
1293
1294 /* Allow a command to be run after wait-for-device,
1295 * e.g. 'adb wait-for-device shell'.
1296 */
1297 if (argc == 1) {
1298 return 0;
1299 }
1300
1301 /* Fall through */
1302 argc--;
1303 argv++;
1304 }
1305
1306 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001307 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001308 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001309 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001310 if (argc < 2)
1311 listopt = "";
1312 else if (argc == 2 && !strcmp(argv[1], "-l"))
1313 listopt = argv[1];
1314 else {
1315 fprintf(stderr, "Usage: adb devices [-l]\n");
1316 return 1;
1317 }
1318 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001319 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001320 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001321 printf("List of devices attached \n");
1322 printf("%s\n", tmp);
1323 return 0;
1324 } else {
1325 return 1;
1326 }
1327 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001328 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001329 char *tmp;
1330 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001331 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001332 return 1;
1333 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001334 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1335 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001336 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001337 printf("%s\n", tmp);
1338 return 0;
1339 } else {
1340 return 1;
1341 }
1342 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001343 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001344 char *tmp;
1345 if (argc > 2) {
1346 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1347 return 1;
1348 }
1349 if (argc == 2) {
1350 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1351 } else {
1352 snprintf(buf, sizeof buf, "host:disconnect:");
1353 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001354 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001355 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001356 printf("%s\n", tmp);
1357 return 0;
1358 } else {
1359 return 1;
1360 }
1361 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001362 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001363 return adb_send_emulator_command(argc, argv);
1364 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001365 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001366 int r;
1367 int fd;
1368
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001369 char h = (argv[0][0] == 'h');
1370
1371 if (h) {
1372 printf("\x1b[41;33m");
1373 fflush(stdout);
1374 }
1375
Riley Andrews98f58e82014-12-05 17:37:24 -08001376 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001377 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001378 r = interactive_shell();
1379 if (h) {
1380 printf("\x1b[0m");
1381 fflush(stdout);
1382 }
1383 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001384 }
1385
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001386 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001387 argc -= 2;
1388 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001389 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001390 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001391 strncat(buf, " ", sizeof(buf) - 1);
1392 strncat(buf, quoted, sizeof(buf) - 1);
1393 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001394 }
1395
1396 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001397 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001398 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001399 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001400 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001401 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001402 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 adb_close(fd);
1404 r = 0;
1405 } else {
1406 fprintf(stderr,"error: %s\n", adb_error());
1407 r = -1;
1408 }
1409
Riley Andrews98f58e82014-12-05 17:37:24 -08001410 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411 fprintf(stderr,"\n- waiting for device -\n");
1412 adb_sleep_ms(1000);
1413 do_cmd(ttype, serial, "wait-for-device", 0);
1414 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001415 if (h) {
1416 printf("\x1b[0m");
1417 fflush(stdout);
1418 }
JP Abgrall408fa572011-03-16 15:57:42 -07001419 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001420 return r;
1421 }
1422 }
1423 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001424 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001425 int exec_in = !strcmp(argv[0], "exec-in");
1426 int fd;
1427
1428 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1429 argc -= 2;
1430 argv += 2;
1431 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001432 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001433 strncat(buf, " ", sizeof(buf) - 1);
1434 strncat(buf, quoted, sizeof(buf) - 1);
1435 free(quoted);
1436 }
1437
1438 fd = adb_connect(buf);
1439 if (fd < 0) {
1440 fprintf(stderr, "error: %s\n", adb_error());
1441 return -1;
1442 }
1443
1444 if (exec_in) {
1445 copy_to_file(STDIN_FILENO, fd);
1446 } else {
1447 copy_to_file(fd, STDOUT_FILENO);
1448 }
1449
1450 adb_close(fd);
1451 return 0;
1452 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001453 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001454 int fd;
1455 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001456 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001457 fprintf(stderr,"* server not running *\n");
1458 return 1;
1459 }
1460 return 0;
1461 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001462 else if (!strcmp(argv[0], "sideload")) {
1463 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001464 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001465 return 1;
1466 } else {
1467 return 0;
1468 }
1469 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001470 else if (!strcmp(argv[0], "remount") ||
1471 !strcmp(argv[0], "reboot") ||
1472 !strcmp(argv[0], "reboot-bootloader") ||
1473 !strcmp(argv[0], "tcpip") ||
1474 !strcmp(argv[0], "usb") ||
1475 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001476 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001477 !strcmp(argv[0], "disable-verity") ||
1478 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001479 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001480 if (!strcmp(argv[0], "reboot-bootloader"))
1481 snprintf(command, sizeof(command), "reboot:bootloader");
1482 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001483 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001484 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001485 snprintf(command, sizeof(command), "%s:", argv[0]);
1486 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001487 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001488 read_and_dump(fd);
1489 adb_close(fd);
1490 return 0;
1491 }
1492 fprintf(stderr,"error: %s\n", adb_error());
1493 return 1;
1494 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001495 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001496 if (argc != 1) return usage();
1497 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001498 return 0;
1499 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001500 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001501 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001502 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001503 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001504 char remove = 0;
1505 char remove_all = 0;
1506 char list = 0;
1507 char no_rebind = 0;
1508
1509 // Parse options here.
1510 while (argc > 1 && argv[1][0] == '-') {
1511 if (!strcmp(argv[1], "--list"))
1512 list = 1;
1513 else if (!strcmp(argv[1], "--remove"))
1514 remove = 1;
1515 else if (!strcmp(argv[1], "--remove-all"))
1516 remove_all = 1;
1517 else if (!strcmp(argv[1], "--no-rebind"))
1518 no_rebind = 1;
1519 else {
1520 return usage();
1521 }
1522 argc--;
1523 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001524 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001525
1526 // Ensure we can only use one option at a time.
1527 if (list + remove + remove_all + no_rebind > 1) {
1528 return usage();
1529 }
1530
1531 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001532 if (reverse) {
1533 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001534 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001535 if (serial) {
1536 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1537 serial);
1538 } else if (ttype == kTransportUsb) {
1539 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1540 } else if (ttype == kTransportLocal) {
1541 snprintf(host_prefix, sizeof host_prefix, "host-local");
1542 } else {
1543 snprintf(host_prefix, sizeof host_prefix, "host");
1544 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001545 }
1546
1547 // Implement forward --list
1548 if (list) {
1549 if (argc != 1)
1550 return usage();
1551 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1552 char* forwards = adb_query(buf);
1553 if (forwards == NULL) {
1554 fprintf(stderr, "error: %s\n", adb_error());
1555 return 1;
1556 }
1557 printf("%s", forwards);
1558 free(forwards);
1559 return 0;
1560 }
1561
1562 // Implement forward --remove-all
1563 else if (remove_all) {
1564 if (argc != 1)
1565 return usage();
1566 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1567 }
1568
1569 // Implement forward --remove <local>
1570 else if (remove) {
1571 if (argc != 2)
1572 return usage();
1573 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1574 }
1575 // Or implement one of:
1576 // forward <local> <remote>
1577 // forward --no-rebind <local> <remote>
1578 else
1579 {
1580 if (argc != 3)
1581 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001582 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001583 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1584 }
1585
Riley Andrews98f58e82014-12-05 17:37:24 -08001586 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001587 fprintf(stderr,"error: %s\n", adb_error());
1588 return 1;
1589 }
1590 return 0;
1591 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001592 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001593 else if (!strcmp(argv[0], "ls")) {
1594 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001595 return do_sync_ls(argv[1]);
1596 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001597 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001598 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001599 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001600 const char* lpath = NULL, *rpath = NULL;
1601
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001602 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001603
1604 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001605 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001606 }
1607
1608 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001609 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001610 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001611 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001612 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001613 const char* rpath = NULL, *lpath = ".";
1614
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001615 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001616
1617 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001618 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001619 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001620
1621 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001622 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001623 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624 if (argc < 2) return usage();
1625 return install_app(ttype, serial, argc, argv);
1626 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001627 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001628 if (argc < 2) return usage();
1629 return install_multiple_app(ttype, serial, argc, argv);
1630 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001631 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001632 if (argc < 2) return usage();
1633 return uninstall_app(ttype, serial, argc, argv);
1634 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001635 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001636 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001637 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1638
Anthony Newnam705c9442010-02-22 08:36:49 -06001639 int listonly = 0;
1640
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001641 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001642 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001643 /* No local path was specified. */
1644 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001645 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1646 listonly = 1;
1647 if (argc == 3) {
1648 srcarg = argv[2];
1649 } else {
1650 srcarg = NULL;
1651 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001652 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001653 /* A local path or "android"/"data" arg was specified. */
1654 srcarg = argv[1];
1655 } else {
1656 return usage();
1657 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001658 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1659 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001660 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001661
Elliott Hughesec7a6672015-03-16 21:58:32 +00001662 if (system_srcpath != NULL)
1663 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001664 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001665 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001666 if(ret == 0 && oem_srcpath != NULL)
1667 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001668 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001669 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001670
Elliott Hughesec7a6672015-03-16 21:58:32 +00001671 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001672 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001673 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001674 free(data_srcpath);
1675 return ret;
1676 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001677 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001678 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001679 !strcmp(argv[0],"get-serialno") ||
1680 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001681 {
1682 char *tmp;
1683
1684 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1685 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001686 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 printf("%s\n", tmp);
1688 return 0;
1689 } else {
1690 return 1;
1691 }
1692 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001693 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001694 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001695 status_window(ttype, serial);
1696 return 0;
1697 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001698 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001699 return logcat(ttype, serial, argc, argv);
1700 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001701 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001702 return ppp(argc, argv);
1703 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001704 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001705 return adb_connect("host:start-server");
1706 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001707 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001708 return backup(argc, argv);
1709 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001710 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001711 return restore(argc, argv);
1712 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001713 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001714 if (argc < 2) return usage();
1715 return adb_auth_keygen(argv[1]);
1716 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001717 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001718 int fd = adb_connect("jdwp");
1719 if (fd >= 0) {
1720 read_and_dump(fd);
1721 adb_close(fd);
1722 return 0;
1723 } else {
1724 fprintf(stderr, "error: %s\n", adb_error());
1725 return -1;
1726 }
1727 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001728 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001729 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001730 help();
1731 return 0;
1732 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001733 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001734 version(stdout);
1735 return 0;
1736 }
1737
1738 usage();
1739 return 1;
1740}
1741
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001742#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001743static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001744{
Dan Albertbac34742015-02-25 17:51:28 -08001745 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001746 int argc;
1747 va_list ap;
1748
1749 va_start(ap, cmd);
1750 argc = 0;
1751
1752 if (serial) {
1753 argv[argc++] = "-s";
1754 argv[argc++] = serial;
1755 } else if (ttype == kTransportUsb) {
1756 argv[argc++] = "-d";
1757 } else if (ttype == kTransportLocal) {
1758 argv[argc++] = "-e";
1759 }
1760
1761 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001762 while(argc < MAX_ARGV_LENGTH &&
1763 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1764 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001765 va_end(ap);
1766
1767#if 0
1768 int n;
1769 fprintf(stderr,"argc = %d\n",argc);
1770 for(n = 0; n < argc; n++) {
1771 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1772 }
1773#endif
1774
1775 return adb_commandline(argc, argv);
1776}
1777
1778int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001779 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1780 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001781{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001782 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001783 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001784
1785 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001786 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001787 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001788 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001789 oem_srcdir = product_file("oem");
1790 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001791 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1792 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001793 // Check if oem partition exists.
1794 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1795 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001796 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001797 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1798 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001799 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001800 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001801 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001803 } else if(strcmp(srcarg, "vendor") == 0) {
1804 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001805 } else if(strcmp(srcarg, "oem") == 0) {
1806 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001807 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001808 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001809 return 1;
1810 }
1811 }
1812
Elliott Hughesec7a6672015-03-16 21:58:32 +00001813 if(system_srcdir_out != NULL)
1814 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001816 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001817
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001818 if(vendor_srcdir_out != NULL)
1819 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001820 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001821 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001822
Elliott Hughesec7a6672015-03-16 21:58:32 +00001823 if(oem_srcdir_out != NULL)
1824 *oem_srcdir_out = oem_srcdir;
1825 else
1826 free(oem_srcdir);
1827
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001828 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001829 *data_srcdir_out = data_srcdir;
1830 else
1831 free(data_srcdir);
1832
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001833 return 0;
1834}
1835
Dan Albertbac34742015-02-25 17:51:28 -08001836static int pm_command(transport_type transport, const char* serial,
1837 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001838{
1839 char buf[4096];
1840
1841 snprintf(buf, sizeof(buf), "shell:pm");
1842
1843 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001844 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001845 strncat(buf, " ", sizeof(buf) - 1);
1846 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001847 free(quoted);
1848 }
1849
1850 send_shellcommand(transport, serial, buf);
1851 return 0;
1852}
1853
Dan Albertbac34742015-02-25 17:51:28 -08001854int uninstall_app(transport_type transport, const char* serial, int argc,
1855 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001856{
1857 /* if the user choose the -k option, we refuse to do it until devices are
1858 out with the option to uninstall the remaining data somehow (adb/ui) */
1859 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1860 {
1861 printf(
1862 "The -k option uninstalls the application while retaining the data/cache.\n"
1863 "At the moment, there is no way to remove the remaining data.\n"
1864 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1865 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1866 return -1;
1867 }
1868
1869 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1870 return pm_command(transport, serial, argc, argv);
1871}
1872
Dan Albertbac34742015-02-25 17:51:28 -08001873static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001874{
1875 char buf[4096];
1876 char* quoted;
1877
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001878 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001879 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001880 strncat(buf, quoted, sizeof(buf)-1);
1881 free(quoted);
1882
1883 send_shellcommand(transport, serial, buf);
1884 return 0;
1885}
1886
Kenny Root597ea5b2011-08-05 11:19:45 -07001887static const char* get_basename(const char* filename)
1888{
1889 const char* basename = adb_dirstop(filename);
1890 if (basename) {
1891 basename++;
1892 return basename;
1893 } else {
1894 return filename;
1895 }
1896}
1897
Dan Albertbac34742015-02-25 17:51:28 -08001898int install_app(transport_type transport, const char* serial, int argc,
1899 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001900{
1901 static const char *const DATA_DEST = "/data/local/tmp/%s";
1902 static const char *const SD_DEST = "/sdcard/tmp/%s";
1903 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001904 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001905 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001906
1907 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001908 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001909 where = SD_DEST;
1910 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001911 }
1912
Jeff Sharkey960df972014-06-09 17:30:57 -07001913 // Find last APK argument.
1914 // All other arguments passed through verbatim.
1915 int last_apk = -1;
1916 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001917 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001918 char* dot = strrchr(file, '.');
1919 if (dot && !strcasecmp(dot, ".apk")) {
1920 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1921 fprintf(stderr, "Invalid APK file: %s\n", file);
1922 return -1;
1923 }
1924
1925 last_apk = i;
1926 break;
1927 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001928 }
1929
Jeff Sharkey960df972014-06-09 17:30:57 -07001930 if (last_apk == -1) {
1931 fprintf(stderr, "Missing APK file\n");
1932 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001933 }
1934
Dan Albertbac34742015-02-25 17:51:28 -08001935 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001936 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001937 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001938 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001939 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001940 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001941 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001942 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001943 }
1944
1945 pm_command(transport, serial, argc, argv);
1946
Kenny Root60733e92012-03-26 16:14:02 -07001947cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001948 delete_file(transport, serial, apk_dest);
1949 return err;
1950}
1951
Dan Albertbac34742015-02-25 17:51:28 -08001952int install_multiple_app(transport_type transport, const char* serial, int argc,
1953 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001954{
1955 char buf[1024];
1956 int i;
1957 struct stat sb;
1958 unsigned long long total_size = 0;
1959
1960 // Find all APK arguments starting at end.
1961 // All other arguments passed through verbatim.
1962 int first_apk = -1;
1963 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001964 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001965 char* dot = strrchr(file, '.');
1966 if (dot && !strcasecmp(dot, ".apk")) {
1967 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1968 fprintf(stderr, "Invalid APK file: %s\n", file);
1969 return -1;
1970 }
1971
1972 total_size += sb.st_size;
1973 first_apk = i;
1974 } else {
1975 break;
1976 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001977 }
1978
Jeff Sharkey960df972014-06-09 17:30:57 -07001979 if (first_apk == -1) {
1980 fprintf(stderr, "Missing APK file\n");
1981 return 1;
1982 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001983
Jeff Sharkey960df972014-06-09 17:30:57 -07001984 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1985 for (i = 1; i < first_apk; i++) {
1986 char *quoted = escape_arg(argv[i]);
1987 strncat(buf, " ", sizeof(buf) - 1);
1988 strncat(buf, quoted, sizeof(buf) - 1);
1989 free(quoted);
1990 }
1991
1992 // Create install session
1993 int fd = adb_connect(buf);
1994 if (fd < 0) {
1995 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1996 return -1;
1997 }
1998 read_status_line(fd, buf, sizeof(buf));
1999 adb_close(fd);
2000
2001 int session_id = -1;
2002 if (!strncmp("Success", buf, 7)) {
2003 char* start = strrchr(buf, '[');
2004 char* end = strrchr(buf, ']');
2005 if (start && end) {
2006 *end = '\0';
2007 session_id = strtol(start + 1, NULL, 10);
2008 }
2009 }
2010 if (session_id < 0) {
2011 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002012 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002013 return -1;
2014 }
2015
2016 // Valid session, now stream the APKs
2017 int success = 1;
2018 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002019 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002020 if (stat(file, &sb) == -1) {
2021 fprintf(stderr, "Failed to stat %s\n", file);
2022 success = 0;
2023 goto finalize_session;
2024 }
2025
2026 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002027 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002028
2029 int localFd = adb_open(file, O_RDONLY);
2030 if (localFd < 0) {
2031 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2032 success = 0;
2033 goto finalize_session;
2034 }
2035
2036 int remoteFd = adb_connect(buf);
2037 if (remoteFd < 0) {
2038 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2039 adb_close(localFd);
2040 success = 0;
2041 goto finalize_session;
2042 }
2043
2044 copy_to_file(localFd, remoteFd);
2045 read_status_line(remoteFd, buf, sizeof(buf));
2046
2047 adb_close(localFd);
2048 adb_close(remoteFd);
2049
2050 if (strncmp("Success", buf, 7)) {
2051 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002052 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002053 success = 0;
2054 goto finalize_session;
2055 }
2056 }
2057
2058finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002059 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002060 if (success) {
2061 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2062 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002063 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002064 }
2065
2066 fd = adb_connect(buf);
2067 if (fd < 0) {
2068 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2069 return -1;
2070 }
2071 read_status_line(fd, buf, sizeof(buf));
2072 adb_close(fd);
2073
2074 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002075 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002076 return 0;
2077 } else {
2078 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002079 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002080 return -1;
2081 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002082}