blob: ecaab835e6fd142b4e7a6b469a412af20e5ac157 [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,
Dan Albert6084a012015-03-16 21:35:53 +000046 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
Dan Albertbac34742015-02-25 17:51:28 -080047int install_app(transport_type transport, const char* serial, int argc,
48 const char** argv);
49int install_multiple_app(transport_type transport, const char* serial, int argc,
50 const char** argv);
51int uninstall_app(transport_type transport, const char* serial, int argc,
52 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080053
54static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080055extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056
57static char *product_file(const char *extra)
58{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080059 if (gProductOutPath == NULL) {
60 fprintf(stderr, "adb: Product directory not specified; "
61 "use -p or define ANDROID_PRODUCT_OUT\n");
62 exit(1);
63 }
64
Dan Albertbac34742015-02-25 17:51:28 -080065 int n = strlen(gProductOutPath) + strlen(extra) + 2;
66 char* x = reinterpret_cast<char*>(malloc(n));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080067 if (x == 0) {
68 fprintf(stderr, "adb: Out of memory (product_file())\n");
69 exit(1);
70 }
71
72 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
73 return x;
74}
75
76void version(FILE * out) {
77 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
78 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
79}
80
81void help()
82{
83 version(stderr);
84
85 fprintf(stderr,
86 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080087 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080088 " -d - directs command to the only connected USB device\n"
89 " returns an error if more than one USB device is present.\n"
90 " -e - directs command to the only running emulator.\n"
91 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070092 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070093 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070094 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 " -p <product name or path> - simple product name like 'sooner', or\n"
96 " a relative/absolute path to a product\n"
97 " out directory like 'out/target/product/sooner'.\n"
98 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
99 " environment variable is used, which must\n"
100 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800101 " -H - Name of adb server host (default: localhost)\n"
102 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700103 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700104 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400105 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
106 " Port 5555 is used by default if no port number is specified.\n"
107 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
108 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200109 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400110 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 "\n"
112 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700113 " adb push [-p] <local> <remote>\n"
114 " - copy file/dir to device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700116 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700117 " - copy file/dir from device\n"
118 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700119 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600121 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800122 " (see 'adb help all')\n"
123 " adb shell - run remote shell interactively\n"
124 " adb shell <command> - run remote shell command\n"
125 " adb emu <command> - run emulator console command\n"
126 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100127 " adb forward --list - list all forward socket connections.\n"
128 " the format is a list of lines with the following format:\n"
129 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800130 " adb forward <local> <remote> - forward socket connections\n"
131 " forward specs are one of: \n"
132 " tcp:<port>\n"
133 " localabstract:<unix domain socket name>\n"
134 " localreserved:<unix domain socket name>\n"
135 " localfilesystem:<unix domain socket name>\n"
136 " dev:<character device name>\n"
137 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100138 " adb forward --no-rebind <local> <remote>\n"
139 " - same as 'adb forward <local> <remote>' but fails\n"
140 " if <local> is already forwarded\n"
141 " adb forward --remove <local> - remove a specific forward socket connection\n"
142 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100143 " adb reverse --list - list all reverse socket connections from device\n"
144 " adb reverse <remote> <local> - reverse socket connections\n"
145 " reverse specs are one of:\n"
146 " tcp:<port>\n"
147 " localabstract:<unix domain socket name>\n"
148 " localreserved:<unix domain socket name>\n"
149 " localfilesystem:<unix domain socket name>\n"
150 " adb reverse --norebind <remote> <local>\n"
151 " - same as 'adb reverse <remote> <local>' but fails\n"
152 " if <remote> is already reversed.\n"
153 " adb reverse --remove <remote>\n"
154 " - remove a specific reversed socket connection\n"
155 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700157 " adb install [-lrtsd] <file>\n"
158 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700160 " (-l: forward lock application)\n"
161 " (-r: replace existing application)\n"
162 " (-t: allow test packages)\n"
163 " (-s: install application on sdcard)\n"
164 " (-d: allow version code downgrade)\n"
165 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166 " adb uninstall [-k] <package> - remove this app package from the device\n"
167 " ('-k' means keep the data and cache directories)\n"
168 " adb bugreport - return all information from the device\n"
169 " that should be included in a bug report.\n"
170 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800171 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700172 " - write an archive of the device's data to <file>.\n"
173 " If no -f option is supplied then the data is written\n"
174 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700175 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700176 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800177 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
178 " (aka .obb) files associated with each application; the default\n"
179 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700180 " (-shared|-noshared enable/disable backup of the device's\n"
181 " shared storage / SD card contents; the default is noshared.)\n"
182 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700183 " (-system|-nosystem toggles whether -all automatically includes\n"
184 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700185 " (<packages...> is the list of applications to be backed up. If\n"
186 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700187 " list is optional. Applications explicitly given on the\n"
188 " command line will be included even if -nosystem would\n"
189 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700190 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700191 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700192 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800193 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
194 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800195 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
196 " and the public key is stored in <file>.pub. Any existing files\n"
197 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800198 " adb help - show this help message\n"
199 " adb version - show version num\n"
200 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800201 "scripting:\n"
202 " adb wait-for-device - block until device is online\n"
203 " adb start-server - ensure that there is a server running\n"
204 " adb kill-server - kill the server if it is running\n"
205 " adb get-state - prints: offline | bootloader | device\n"
206 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700207 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 " adb status-window - continuously print device status for a specified device\n"
Dan Albert6084a012015-03-16 21:35:53 +0000209 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400210 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800211 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700212 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500213 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800214 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000215 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800216 "networking:\n"
217 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500218 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800219 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
220 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
221 "\n"
222 "adb sync notes: adb sync [ <directory> ]\n"
223 " <localdir> can be interpreted in several ways:\n"
224 "\n"
Dan Albert6084a012015-03-16 21:35:53 +0000225 " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 "\n"
Dan Albert6084a012015-03-16 21:35:53 +0000227 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000229 "\n"
230 "environmental variables:\n"
231 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
232 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
233 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
234 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800235 );
236}
237
238int usage()
239{
240 help();
241 return 1;
242}
243
Yabin Cuid325e862014-11-17 14:48:25 -0800244#if defined(_WIN32)
245
246// Windows does not have <termio.h>.
247static void stdin_raw_init(int fd) {
248
249}
250
251static void stdin_raw_restore(int fd) {
252
253}
254
255#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256static struct termios tio_save;
257
258static void stdin_raw_init(int fd)
259{
260 struct termios tio;
261
262 if(tcgetattr(fd, &tio)) return;
263 if(tcgetattr(fd, &tio_save)) return;
264
265 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
266
267 /* no timeout but request at least one character per read */
268 tio.c_cc[VTIME] = 0;
269 tio.c_cc[VMIN] = 1;
270
271 tcsetattr(fd, TCSANOW, &tio);
272 tcflush(fd, TCIFLUSH);
273}
274
275static void stdin_raw_restore(int fd)
276{
277 tcsetattr(fd, TCSANOW, &tio_save);
278 tcflush(fd, TCIFLUSH);
279}
280#endif
281
282static void read_and_dump(int fd)
283{
284 char buf[4096];
285 int len;
286
287 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700288 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800289 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700290 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 if(len == 0) {
292 break;
293 }
294
295 if(len < 0) {
296 if(errno == EINTR) continue;
297 break;
298 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400299 fwrite(buf, 1, len, stdout);
300 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301 }
302}
303
Jeff Sharkey960df972014-06-09 17:30:57 -0700304static void read_status_line(int fd, char* buf, size_t count)
305{
306 count--;
307 while (count > 0) {
308 int len = adb_read(fd, buf, count);
309 if (len == 0) {
310 break;
311 } else if (len < 0) {
312 if (errno == EINTR) continue;
313 break;
314 }
315
316 buf += len;
317 count -= len;
318 }
319 *buf = '\0';
320}
321
Christopher Tated2f54152011-04-21 12:53:28 -0700322static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700323 const size_t BUFSIZE = 32 * 1024;
324 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700325 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700326 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700327
328 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800329
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700330 if (inFd == STDIN_FILENO) {
331 stdin_raw_init(STDIN_FILENO);
332 }
Yabin Cuid325e862014-11-17 14:48:25 -0800333
Christopher Tated2f54152011-04-21 12:53:28 -0700334 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700335 if (inFd == STDIN_FILENO) {
336 len = unix_read(inFd, buf, BUFSIZE);
337 } else {
338 len = adb_read(inFd, buf, BUFSIZE);
339 }
Christopher Tated2f54152011-04-21 12:53:28 -0700340 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700341 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700342 break;
343 }
344 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700345 if (errno == EINTR) {
346 D("copy_to_file() : EINTR, retrying\n");
347 continue;
348 }
Christopher Tated2f54152011-04-21 12:53:28 -0700349 D("copy_to_file() : error %d\n", errno);
350 break;
351 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700352 if (outFd == STDOUT_FILENO) {
353 fwrite(buf, 1, len, stdout);
354 fflush(stdout);
355 } else {
356 adb_write(outFd, buf, len);
357 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700358 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700359 }
Yabin Cuid325e862014-11-17 14:48:25 -0800360
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700361 if (inFd == STDIN_FILENO) {
362 stdin_raw_restore(STDIN_FILENO);
363 }
Yabin Cuid325e862014-11-17 14:48:25 -0800364
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700365 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700366 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700367}
368
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369static void *stdin_read_thread(void *x)
370{
371 int fd, fdi;
372 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 int r, n;
374 int state = 0;
375
376 int *fds = (int*) x;
377 fd = fds[0];
378 fdi = fds[1];
379 free(fds);
380
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800381 for(;;) {
382 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700383 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800384 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700385 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386 if(r == 0) break;
387 if(r < 0) {
388 if(errno == EINTR) continue;
389 break;
390 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400391 for(n = 0; n < r; n++){
392 switch(buf[n]) {
393 case '\n':
394 state = 1;
395 break;
396 case '\r':
397 state = 1;
398 break;
399 case '~':
400 if(state == 1) state++;
401 break;
402 case '.':
403 if(state == 2) {
404 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400405 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400406 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400408 default:
409 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 r = adb_write(fd, buf, r);
413 if(r <= 0) {
414 break;
415 }
416 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800417 return 0;
418}
419
420int interactive_shell(void)
421{
422 adb_thread_t thr;
423 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800424
425 fd = adb_connect("shell:");
426 if(fd < 0) {
427 fprintf(stderr,"error: %s\n", adb_error());
428 return 1;
429 }
430 fdi = 0; //dup(0);
431
Dan Albertbac34742015-02-25 17:51:28 -0800432 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800433 fds[0] = fd;
434 fds[1] = fdi;
435
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 adb_thread_create(&thr, stdin_read_thread, fds);
438 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 return 0;
441}
442
443
444static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
445{
446 if (serial) {
447 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
448 } else {
449 const char* prefix = "host";
450 if (ttype == kTransportUsb)
451 prefix = "host-usb";
452 else if (ttype == kTransportLocal)
453 prefix = "host-local";
454
455 snprintf(buffer, buflen, "%s:%s", prefix, command);
456 }
457}
458
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100459int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800460 unsigned progress)
461{
462 char buf[4096];
463 unsigned total;
464 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800465
466 sprintf(buf,"%s:%d", service, sz);
467 fd = adb_connect(buf);
468 if(fd < 0) {
469 fprintf(stderr,"error: %s\n", adb_error());
470 return -1;
471 }
472
473 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800474 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800475
476 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800477 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800478
479 if(progress) {
480 char *x = strrchr(service, ':');
481 if(x) service = x + 1;
482 }
483
484 while(sz > 0) {
485 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800486 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800487 adb_status(fd);
488 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
489 return -1;
490 }
491 sz -= xfer;
492 ptr += xfer;
493 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100494 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800495 fflush(stdout);
496 }
497 }
498 if(progress) {
499 printf("\n");
500 }
501
Dan Albertcc731cc2015-02-24 21:26:58 -0800502 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800503 fprintf(stderr,"* error reading response *\n");
504 adb_close(fd);
505 return -1;
506 }
507 if(memcmp(buf, "OKAY", 4)) {
508 buf[4] = 0;
509 fprintf(stderr,"* error response '%s' *\n", buf);
510 adb_close(fd);
511 return -1;
512 }
513
514 adb_close(fd);
515 return 0;
516}
517
518
519int adb_download(const char *service, const char *fn, unsigned progress)
520{
521 void *data;
522 unsigned sz;
523
524 data = load_file(fn, &sz);
525 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100526 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800527 return -1;
528 }
529
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100530 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800531 free(data);
532 return status;
533}
534
Doug Zongker71fe5842014-06-26 15:35:36 -0700535#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
536
537/*
538 * The sideload-host protocol serves the data in a file (given on the
539 * command line) to the client, using a simple protocol:
540 *
541 * - The connect message includes the total number of bytes in the
542 * file and a block size chosen by us.
543 *
544 * - The other side sends the desired block number as eight decimal
545 * digits (eg "00000023" for block 23). Blocks are numbered from
546 * zero.
547 *
548 * - We send back the data of the requested block. The last block is
549 * likely to be partial; when the last block is requested we only
550 * send the part of the block that exists, it's not padded up to the
551 * block size.
552 *
553 * - When the other side sends "DONEDONE" instead of a block number,
554 * we hang up.
555 */
556int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700557 unsigned sz;
558 size_t xfer = 0;
559 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800560 int last_percent = -1;
561 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700562
563 printf("loading: '%s'", fn);
564 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800565 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700566 if (data == 0) {
567 printf("\n");
568 fprintf(stderr, "* cannot read '%s' *\n", fn);
569 return -1;
570 }
571
572 char buf[100];
573 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
574 int fd = adb_connect(buf);
575 if (fd < 0) {
576 // Try falling back to the older sideload method. Maybe this
577 // is an older device that doesn't support sideload-host.
578 printf("\n");
579 status = adb_download_buffer("sideload", fn, data, sz, 1);
580 goto done;
581 }
582
Spencer Lowf055c192015-01-25 14:40:16 -0800583 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700584
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700585 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800586 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700587 fprintf(stderr, "* failed to read command: %s\n", adb_error());
588 status = -1;
589 goto done;
590 }
591
592 if (strncmp("DONEDONE", buf, 8) == 0) {
593 status = 0;
594 break;
595 }
596
597 buf[8] = '\0';
598 int block = strtol(buf, NULL, 10);
599
600 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
601 if (offset >= sz) {
602 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
603 status = -1;
604 goto done;
605 }
606 uint8_t* start = data + offset;
607 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
608 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
609 if (offset_end > sz) {
610 to_write = sz - offset;
611 }
612
Dan Albertcc731cc2015-02-24 21:26:58 -0800613 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700614 adb_status(fd);
615 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
616 status = -1;
617 goto done;
618 }
619 xfer += to_write;
620
621 // For normal OTA packages, we expect to transfer every byte
622 // twice, plus a bit of overhead (one read during
623 // verification, one read of each byte for installation, plus
624 // extra access to things like the zip central directory).
625 // This estimate of the completion becomes 100% when we've
626 // transferred ~2.13 (=100/47) times the package size.
627 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
628 if (percent != last_percent) {
629 printf("\rserving: '%s' (~%d%%) ", fn, percent);
630 fflush(stdout);
631 last_percent = percent;
632 }
633 }
634
Colin Cross6d6a8982014-07-07 14:12:41 -0700635 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700636
637 done:
638 if (fd >= 0) adb_close(fd);
639 free(data);
640 return status;
641}
642
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800643static void status_window(transport_type ttype, const char* serial)
644{
645 char command[4096];
646 char *state = 0;
647 char *laststate = 0;
648
649 /* silence stderr */
650#ifdef _WIN32
651 /* XXX: TODO */
652#else
653 int fd;
654 fd = unix_open("/dev/null", O_WRONLY);
655 dup2(fd, 2);
656 adb_close(fd);
657#endif
658
659 format_host_command(command, sizeof command, "get-state", ttype, serial);
660
661 for(;;) {
662 adb_sleep_ms(250);
663
664 if(state) {
665 free(state);
666 state = 0;
667 }
668
669 state = adb_query(command);
670
671 if(state) {
672 if(laststate && !strcmp(state,laststate)){
673 continue;
674 } else {
675 if(laststate) free(laststate);
676 laststate = strdup(state);
677 }
678 }
679
680 printf("%c[2J%c[2H", 27, 27);
681 printf("Android Debug Bridge\n");
682 printf("State: %s\n", state ? state : "offline");
683 fflush(stdout);
684 }
685}
686
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700687static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700688{
689 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
690}
691
692/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700693static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800694{
695 const char *ts;
696 size_t alloc_len;
697 char *ret;
698 char *dest;
699
Jeff Sharkey7c460352014-06-10 16:22:17 -0700700 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700701 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800702 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700703 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800704 alloc_len++;
705 }
706 }
707
Jeff Sharkey7c460352014-06-10 16:22:17 -0700708 if (alloc_len == 0) {
709 // Preserve empty arguments
710 ret = (char *) malloc(3);
711 ret[0] = '\"';
712 ret[1] = '\"';
713 ret[2] = '\0';
714 return ret;
715 }
716
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700717 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800718 dest = ret;
719
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700720 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700721 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800722 *dest++ = '\\';
723 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800724 *dest++ = *ts;
725 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800726 *dest++ = '\0';
727
728 return ret;
729}
730
731/**
732 * Run ppp in "notty" mode against a resource listed as the first parameter
733 * eg:
734 *
735 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
736 *
737 */
Dan Albertbac34742015-02-25 17:51:28 -0800738int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800739{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800740#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800741 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
742 return -1;
743#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800744 pid_t pid;
745 int fd;
746
747 if (argc < 2) {
748 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
749 argv[0]);
750
751 return 1;
752 }
753
Dan Albertbac34742015-02-25 17:51:28 -0800754 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800755 fd = adb_connect(adb_service_name);
756
757 if(fd < 0) {
758 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
759 adb_service_name, adb_error());
760 return 1;
761 }
762
763 pid = fork();
764
765 if (pid < 0) {
766 perror("from fork()");
767 return 1;
768 } else if (pid == 0) {
769 int err;
770 int i;
771 const char **ppp_args;
772
773 // copy args
774 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
775 ppp_args[0] = "pppd";
776 for (i = 2 ; i < argc ; i++) {
777 //argv[2] and beyond become ppp_args[1] and beyond
778 ppp_args[i - 1] = argv[i];
779 }
780 ppp_args[i-1] = NULL;
781
782 // child side
783
784 dup2(fd, STDIN_FILENO);
785 dup2(fd, STDOUT_FILENO);
786 adb_close(STDERR_FILENO);
787 adb_close(fd);
788
789 err = execvp("pppd", (char * const *)ppp_args);
790
791 if (err < 0) {
792 perror("execing pppd");
793 }
794 exit(-1);
795 } else {
796 // parent side
797
798 adb_close(fd);
799 return 0;
800 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800801#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800802}
803
Dan Albertbac34742015-02-25 17:51:28 -0800804static int send_shellcommand(transport_type transport, const char* serial,
805 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800806{
807 int fd, ret;
808
809 for(;;) {
810 fd = adb_connect(buf);
811 if(fd >= 0)
812 break;
813 fprintf(stderr,"- waiting for device -\n");
814 adb_sleep_ms(1000);
815 do_cmd(transport, serial, "wait-for-device", 0);
816 }
817
818 read_and_dump(fd);
819 ret = adb_close(fd);
820 if (ret)
821 perror("close");
822
823 return ret;
824}
825
Dan Albertbac34742015-02-25 17:51:28 -0800826static int logcat(transport_type transport, const char* serial, int argc,
827 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800828{
829 char buf[4096];
830
831 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700832 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800833
834 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700835 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700837 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700838 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800839
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700840 if (!strcmp(argv[0], "longcat")) {
841 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800842 }
843
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800844 argc -= 1;
845 argv += 1;
846 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700847 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700848 strncat(buf, " ", sizeof(buf) - 1);
849 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800850 free(quoted);
851 }
852
853 send_shellcommand(transport, serial, buf);
854 return 0;
855}
856
Mark Salyzyn60299df2014-04-30 09:10:31 -0700857static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800858{
859 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700860 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800861
862 for(;;) {
863 x = adb_dirstart(x);
864 if(x == 0) return 0;
865 *x = 0;
866 ret = adb_mkdir(path, 0775);
867 *x = OS_PATH_SEPARATOR;
868 if((ret < 0) && (errno != EEXIST)) {
869 return ret;
870 }
871 x++;
872 }
873 return 0;
874}
875
Dan Albertbac34742015-02-25 17:51:28 -0800876static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700877 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800878 char default_name[32];
879 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700880 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700881 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700882
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700883 /* find, extract, and use any -f argument */
884 for (i = 1; i < argc; i++) {
885 if (!strcmp("-f", argv[i])) {
886 if (i == argc-1) {
887 fprintf(stderr, "adb: -f passed with no filename\n");
888 return usage();
889 }
890 filename = argv[i+1];
891 for (j = i+2; j <= argc; ) {
892 argv[i++] = argv[j++];
893 }
894 argc -= 2;
895 argv[argc] = NULL;
896 }
Christopher Tated2f54152011-04-21 12:53:28 -0700897 }
898
Christopher Tatebb86bc52011-08-22 17:12:08 -0700899 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
900 if (argc < 2) return usage();
901
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800902 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700903 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800904 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700905 if (outFd < 0) {
906 fprintf(stderr, "adb: unable to open file %s\n", filename);
907 return -1;
908 }
909
910 snprintf(buf, sizeof(buf), "backup");
911 for (argc--, argv++; argc; argc--, argv++) {
912 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
913 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
914 }
915
916 D("backup. filename=%s buf=%s\n", filename, buf);
917 fd = adb_connect(buf);
918 if (fd < 0) {
919 fprintf(stderr, "adb: unable to connect for backup\n");
920 adb_close(outFd);
921 return -1;
922 }
923
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800924 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700925 copy_to_file(fd, outFd);
926
927 adb_close(fd);
928 adb_close(outFd);
929 return 0;
930}
931
Dan Albertbac34742015-02-25 17:51:28 -0800932static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700933 const char* filename;
934 int fd, tarFd;
935
936 if (argc != 2) return usage();
937
938 filename = argv[1];
939 tarFd = adb_open(filename, O_RDONLY);
940 if (tarFd < 0) {
941 fprintf(stderr, "adb: unable to open file %s\n", filename);
942 return -1;
943 }
944
945 fd = adb_connect("restore:");
946 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700947 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700948 adb_close(tarFd);
949 return -1;
950 }
951
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800952 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700953 copy_to_file(tarFd, fd);
954
955 adb_close(fd);
956 adb_close(tarFd);
957 return 0;
958}
959
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800960#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
961static int top_works(const char *top)
962{
963 if (top != NULL && adb_is_absolute_host_path(top)) {
964 char path_buf[PATH_MAX];
965 snprintf(path_buf, sizeof(path_buf),
966 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
967 return access(path_buf, F_OK) == 0;
968 }
969 return 0;
970}
971
972static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
973{
974 strcpy(path_buf, indir);
975 while (1) {
976 if (top_works(path_buf)) {
977 return path_buf;
978 }
979 char *s = adb_dirstop(path_buf);
980 if (s != NULL) {
981 *s = '\0';
982 } else {
983 path_buf[0] = '\0';
984 return NULL;
985 }
986 }
987}
988
989static char *find_top(char path_buf[PATH_MAX])
990{
991 char *top = getenv("ANDROID_BUILD_TOP");
992 if (top != NULL && top[0] != '\0') {
993 if (!top_works(top)) {
994 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
995 return NULL;
996 }
997 } else {
998 top = getenv("TOP");
999 if (top != NULL && top[0] != '\0') {
1000 if (!top_works(top)) {
1001 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1002 return NULL;
1003 }
1004 } else {
1005 top = NULL;
1006 }
1007 }
1008
1009 if (top != NULL) {
1010 /* The environment pointed to a top directory that works.
1011 */
1012 strcpy(path_buf, top);
1013 return path_buf;
1014 }
1015
1016 /* The environment didn't help. Walk up the tree from the CWD
1017 * to see if we can find the top.
1018 */
1019 char dir[PATH_MAX];
1020 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1021 if (top == NULL) {
1022 /* If the CWD isn't under a good-looking top, see if the
1023 * executable is.
1024 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001025 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001026 top = find_top_from(dir, path_buf);
1027 }
1028 return top;
1029}
1030
1031/* <hint> may be:
1032 * - A simple product name
1033 * e.g., "sooner"
1034TODO: debug? sooner-debug, sooner:debug?
1035 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1036 * e.g., "out/target/product/sooner"
1037 * - An absolute path to the PRODUCT_OUT dir
1038 * e.g., "/src/device/out/target/product/sooner"
1039 *
1040 * Given <hint>, try to construct an absolute path to the
1041 * ANDROID_PRODUCT_OUT dir.
1042 */
1043static const char *find_product_out_path(const char *hint)
1044{
1045 static char path_buf[PATH_MAX];
1046
1047 if (hint == NULL || hint[0] == '\0') {
1048 return NULL;
1049 }
1050
1051 /* If it's already absolute, don't bother doing any work.
1052 */
1053 if (adb_is_absolute_host_path(hint)) {
1054 strcpy(path_buf, hint);
1055 return path_buf;
1056 }
1057
1058 /* If there are any slashes in it, assume it's a relative path;
1059 * make it absolute.
1060 */
1061 if (adb_dirstart(hint) != NULL) {
1062 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1063 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1064 return NULL;
1065 }
1066 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1067 fprintf(stderr, "adb: Couldn't assemble path\n");
1068 return NULL;
1069 }
1070 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1071 strcat(path_buf, hint);
1072 return path_buf;
1073 }
1074
1075 /* It's a string without any slashes. Try to do something with it.
1076 *
1077 * Try to find the root of the build tree, and build a PRODUCT_OUT
1078 * path from there.
1079 */
1080 char top_buf[PATH_MAX];
1081 const char *top = find_top(top_buf);
1082 if (top == NULL) {
1083 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1084 return NULL;
1085 }
1086//TODO: if we have a way to indicate debug, look in out/debug/target/...
1087 snprintf(path_buf, sizeof(path_buf),
1088 "%s" OS_PATH_SEPARATOR_STR
1089 "out" OS_PATH_SEPARATOR_STR
1090 "target" OS_PATH_SEPARATOR_STR
1091 "product" OS_PATH_SEPARATOR_STR
1092 "%s", top_buf, hint);
1093 if (access(path_buf, F_OK) < 0) {
1094 fprintf(stderr, "adb: Couldn't find a product dir "
1095 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1096 return NULL;
1097 }
1098 return path_buf;
1099}
1100
Dan Albertbac34742015-02-25 17:51:28 -08001101static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1102 char const **path2, int *show_progress,
1103 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001104 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001105 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001106
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001107 while (narg > 0) {
1108 if (!strcmp(*arg, "-p")) {
1109 *show_progress = 1;
1110 } else if (!strcmp(*arg, "-a")) {
1111 *copy_attrs = 1;
1112 } else {
1113 break;
1114 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001115 ++arg;
1116 --narg;
1117 }
1118
1119 if (narg > 0) {
1120 *path1 = *arg;
1121 ++arg;
1122 --narg;
1123 }
1124
1125 if (narg > 0) {
1126 *path2 = *arg;
1127 }
1128}
1129
Dan Albertbac34742015-02-25 17:51:28 -08001130int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001131{
1132 char buf[4096];
1133 int no_daemon = 0;
1134 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001135 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001136 int persist = 0;
1137 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001138 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001139 const char* serial = NULL;
1140 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141
1142 /* If defined, this should be an absolute path to
1143 * the directory containing all of the various system images
1144 * for a particular product. If not defined, and the adb
1145 * command requires this information, then the user must
1146 * specify the path using "-p".
1147 */
1148 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1149 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1150 gProductOutPath = NULL;
1151 }
1152 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1153
Nick Pellydb449262009-05-07 12:48:03 -07001154 serial = getenv("ANDROID_SERIAL");
1155
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001156 /* Validate and assign the server port */
1157 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1158 int server_port = DEFAULT_ADB_PORT;
1159 if (server_port_str && strlen(server_port_str) > 0) {
1160 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001161 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001162 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001163 "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 +01001164 server_port_str);
1165 return usage();
1166 }
1167 }
1168
1169 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001170 while (argc > 0) {
1171 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001172 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001173 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001174 no_daemon = 1;
1175 } else if (!strcmp(argv[0], "fork-server")) {
1176 /* this is a special flag used only when the ADB client launches the ADB Server */
1177 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001178 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001179 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001180 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001181 const char *product = NULL;
1182 if (argv[0][2] == '\0') {
1183 if (argc < 2) return usage();
1184 product = argv[1];
1185 argc--;
1186 argv++;
1187 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001188 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 }
1190 gProductOutPath = find_product_out_path(product);
1191 if (gProductOutPath == NULL) {
1192 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1193 product);
1194 return usage();
1195 }
1196 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1197 if (isdigit(argv[0][2])) {
1198 serial = argv[0] + 2;
1199 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001200 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001201 serial = argv[1];
1202 argc--;
1203 argv++;
1204 }
1205 } else if (!strcmp(argv[0],"-d")) {
1206 ttype = kTransportUsb;
1207 } else if (!strcmp(argv[0],"-e")) {
1208 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001209 } else if (!strcmp(argv[0],"-a")) {
1210 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001211 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001212 const char *hostname = NULL;
1213 if (argv[0][2] == '\0') {
1214 if (argc < 2) return usage();
1215 hostname = argv[1];
1216 argc--;
1217 argv++;
1218 } else {
1219 hostname = argv[0] + 2;
1220 }
1221 adb_set_tcp_name(hostname);
1222
Riley Andrews98f58e82014-12-05 17:37:24 -08001223 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001224 if (argv[0][2] == '\0') {
1225 if (argc < 2) return usage();
1226 server_port_str = argv[1];
1227 argc--;
1228 argv++;
1229 } else {
1230 server_port_str = argv[0] + 2;
1231 }
1232 if (strlen(server_port_str) > 0) {
1233 server_port = (int) strtol(server_port_str, NULL, 0);
1234 if (server_port <= 0 || server_port > 65535) {
1235 fprintf(stderr,
1236 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1237 server_port_str);
1238 return usage();
1239 }
1240 } else {
1241 fprintf(stderr,
1242 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1243 return usage();
1244 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001245 } else {
1246 /* out of recognized modifiers and flags */
1247 break;
1248 }
1249 argc--;
1250 argv++;
1251 }
1252
1253 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001254 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001255
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001256 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001257 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001258 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001259 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001260 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001261 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001262 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263 fprintf(stderr,"* could not start server *\n");
1264 }
1265 return r;
1266 }
1267
Riley Andrews98f58e82014-12-05 17:37:24 -08001268 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001269 return usage();
1270 }
1271
Riley Andrewsc8514c82014-12-05 17:32:46 -08001272 /* handle wait-for-* prefix */
1273 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001274 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001275 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1276 if (ttype == kTransportUsb) {
1277 service = "wait-for-usb";
1278 } else if (ttype == kTransportLocal) {
1279 service = "wait-for-local";
1280 } else {
1281 service = "wait-for-any";
1282 }
1283 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001284
Riley Andrewsc8514c82014-12-05 17:32:46 -08001285 format_host_command(buf, sizeof buf, service, ttype, serial);
1286
1287 if (adb_command(buf)) {
1288 D("failure: %s *\n",adb_error());
1289 fprintf(stderr,"error: %s\n", adb_error());
1290 return 1;
1291 }
1292
1293 /* Allow a command to be run after wait-for-device,
1294 * e.g. 'adb wait-for-device shell'.
1295 */
1296 if (argc == 1) {
1297 return 0;
1298 }
1299
1300 /* Fall through */
1301 argc--;
1302 argv++;
1303 }
1304
1305 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001306 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001307 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001308 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001309 if (argc < 2)
1310 listopt = "";
1311 else if (argc == 2 && !strcmp(argv[1], "-l"))
1312 listopt = argv[1];
1313 else {
1314 fprintf(stderr, "Usage: adb devices [-l]\n");
1315 return 1;
1316 }
1317 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001318 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001319 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 printf("List of devices attached \n");
1321 printf("%s\n", tmp);
1322 return 0;
1323 } else {
1324 return 1;
1325 }
1326 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001327 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001328 char *tmp;
1329 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001330 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001331 return 1;
1332 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001333 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1334 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001335 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001336 printf("%s\n", tmp);
1337 return 0;
1338 } else {
1339 return 1;
1340 }
1341 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001342 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001343 char *tmp;
1344 if (argc > 2) {
1345 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1346 return 1;
1347 }
1348 if (argc == 2) {
1349 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1350 } else {
1351 snprintf(buf, sizeof buf, "host:disconnect:");
1352 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001353 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001354 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001355 printf("%s\n", tmp);
1356 return 0;
1357 } else {
1358 return 1;
1359 }
1360 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001361 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001362 return adb_send_emulator_command(argc, argv);
1363 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001364 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001365 int r;
1366 int fd;
1367
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001368 char h = (argv[0][0] == 'h');
1369
1370 if (h) {
1371 printf("\x1b[41;33m");
1372 fflush(stdout);
1373 }
1374
Riley Andrews98f58e82014-12-05 17:37:24 -08001375 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001376 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001377 r = interactive_shell();
1378 if (h) {
1379 printf("\x1b[0m");
1380 fflush(stdout);
1381 }
1382 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001383 }
1384
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001385 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001386 argc -= 2;
1387 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001388 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001389 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001390 strncat(buf, " ", sizeof(buf) - 1);
1391 strncat(buf, quoted, sizeof(buf) - 1);
1392 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001393 }
1394
1395 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001396 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001397 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001398 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001399 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001400 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001401 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 adb_close(fd);
1403 r = 0;
1404 } else {
1405 fprintf(stderr,"error: %s\n", adb_error());
1406 r = -1;
1407 }
1408
Riley Andrews98f58e82014-12-05 17:37:24 -08001409 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 fprintf(stderr,"\n- waiting for device -\n");
1411 adb_sleep_ms(1000);
1412 do_cmd(ttype, serial, "wait-for-device", 0);
1413 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001414 if (h) {
1415 printf("\x1b[0m");
1416 fflush(stdout);
1417 }
JP Abgrall408fa572011-03-16 15:57:42 -07001418 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001419 return r;
1420 }
1421 }
1422 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001423 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001424 int exec_in = !strcmp(argv[0], "exec-in");
1425 int fd;
1426
1427 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1428 argc -= 2;
1429 argv += 2;
1430 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001431 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001432 strncat(buf, " ", sizeof(buf) - 1);
1433 strncat(buf, quoted, sizeof(buf) - 1);
1434 free(quoted);
1435 }
1436
1437 fd = adb_connect(buf);
1438 if (fd < 0) {
1439 fprintf(stderr, "error: %s\n", adb_error());
1440 return -1;
1441 }
1442
1443 if (exec_in) {
1444 copy_to_file(STDIN_FILENO, fd);
1445 } else {
1446 copy_to_file(fd, STDOUT_FILENO);
1447 }
1448
1449 adb_close(fd);
1450 return 0;
1451 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001452 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001453 int fd;
1454 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001455 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001456 fprintf(stderr,"* server not running *\n");
1457 return 1;
1458 }
1459 return 0;
1460 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001461 else if (!strcmp(argv[0], "sideload")) {
1462 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001463 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001464 return 1;
1465 } else {
1466 return 0;
1467 }
1468 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001469 else if (!strcmp(argv[0], "remount") ||
1470 !strcmp(argv[0], "reboot") ||
1471 !strcmp(argv[0], "reboot-bootloader") ||
1472 !strcmp(argv[0], "tcpip") ||
1473 !strcmp(argv[0], "usb") ||
1474 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001475 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001476 !strcmp(argv[0], "disable-verity") ||
1477 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001478 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001479 if (!strcmp(argv[0], "reboot-bootloader"))
1480 snprintf(command, sizeof(command), "reboot:bootloader");
1481 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001482 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001483 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001484 snprintf(command, sizeof(command), "%s:", argv[0]);
1485 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001486 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001487 read_and_dump(fd);
1488 adb_close(fd);
1489 return 0;
1490 }
1491 fprintf(stderr,"error: %s\n", adb_error());
1492 return 1;
1493 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001494 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001495 if (argc != 1) return usage();
1496 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001497 return 0;
1498 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001499 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001500 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001501 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001502 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001503 char remove = 0;
1504 char remove_all = 0;
1505 char list = 0;
1506 char no_rebind = 0;
1507
1508 // Parse options here.
1509 while (argc > 1 && argv[1][0] == '-') {
1510 if (!strcmp(argv[1], "--list"))
1511 list = 1;
1512 else if (!strcmp(argv[1], "--remove"))
1513 remove = 1;
1514 else if (!strcmp(argv[1], "--remove-all"))
1515 remove_all = 1;
1516 else if (!strcmp(argv[1], "--no-rebind"))
1517 no_rebind = 1;
1518 else {
1519 return usage();
1520 }
1521 argc--;
1522 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001523 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001524
1525 // Ensure we can only use one option at a time.
1526 if (list + remove + remove_all + no_rebind > 1) {
1527 return usage();
1528 }
1529
1530 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001531 if (reverse) {
1532 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001533 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001534 if (serial) {
1535 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1536 serial);
1537 } else if (ttype == kTransportUsb) {
1538 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1539 } else if (ttype == kTransportLocal) {
1540 snprintf(host_prefix, sizeof host_prefix, "host-local");
1541 } else {
1542 snprintf(host_prefix, sizeof host_prefix, "host");
1543 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001544 }
1545
1546 // Implement forward --list
1547 if (list) {
1548 if (argc != 1)
1549 return usage();
1550 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1551 char* forwards = adb_query(buf);
1552 if (forwards == NULL) {
1553 fprintf(stderr, "error: %s\n", adb_error());
1554 return 1;
1555 }
1556 printf("%s", forwards);
1557 free(forwards);
1558 return 0;
1559 }
1560
1561 // Implement forward --remove-all
1562 else if (remove_all) {
1563 if (argc != 1)
1564 return usage();
1565 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1566 }
1567
1568 // Implement forward --remove <local>
1569 else if (remove) {
1570 if (argc != 2)
1571 return usage();
1572 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1573 }
1574 // Or implement one of:
1575 // forward <local> <remote>
1576 // forward --no-rebind <local> <remote>
1577 else
1578 {
1579 if (argc != 3)
1580 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001581 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001582 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1583 }
1584
Riley Andrews98f58e82014-12-05 17:37:24 -08001585 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001586 fprintf(stderr,"error: %s\n", adb_error());
1587 return 1;
1588 }
1589 return 0;
1590 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001591 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001592 else if (!strcmp(argv[0], "ls")) {
1593 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001594 return do_sync_ls(argv[1]);
1595 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001596 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001597 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001598 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001599 const char* lpath = NULL, *rpath = NULL;
1600
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001601 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001602
1603 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001604 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001605 }
1606
1607 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001608 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001609 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001610 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001611 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001612 const char* rpath = NULL, *lpath = ".";
1613
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001614 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001615
1616 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001617 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001618 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001619
1620 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001621 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001622 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 if (argc < 2) return usage();
1624 return install_app(ttype, serial, argc, argv);
1625 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001626 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001627 if (argc < 2) return usage();
1628 return install_multiple_app(ttype, serial, argc, argv);
1629 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001630 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001631 if (argc < 2) return usage();
1632 return uninstall_app(ttype, serial, argc, argv);
1633 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001634 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001635 const char* srcarg;
Dan Albert6084a012015-03-16 21:35:53 +00001636 char *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001637 int listonly = 0;
1638
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001639 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001640 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001641 /* No local path was specified. */
1642 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001643 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1644 listonly = 1;
1645 if (argc == 3) {
1646 srcarg = argv[2];
1647 } else {
1648 srcarg = NULL;
1649 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001650 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001651 /* A local path or "android"/"data" arg was specified. */
1652 srcarg = argv[1];
1653 } else {
1654 return usage();
1655 }
Dan Albert6084a012015-03-16 21:35:53 +00001656 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001657 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001658
Dan Albert6084a012015-03-16 21:35:53 +00001659 if (android_srcpath != NULL)
1660 ret = do_sync_sync(android_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001661 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001662 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001663 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001664 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001665
Dan Albert6084a012015-03-16 21:35:53 +00001666 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001667 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001668 free(data_srcpath);
1669 return ret;
1670 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001671 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001672 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001673 !strcmp(argv[0],"get-serialno") ||
1674 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001675 {
1676 char *tmp;
1677
1678 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1679 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001680 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001681 printf("%s\n", tmp);
1682 return 0;
1683 } else {
1684 return 1;
1685 }
1686 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001688 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001689 status_window(ttype, serial);
1690 return 0;
1691 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001692 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001693 return logcat(ttype, serial, argc, argv);
1694 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001696 return ppp(argc, argv);
1697 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001698 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001699 return adb_connect("host:start-server");
1700 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001701 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001702 return backup(argc, argv);
1703 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001704 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001705 return restore(argc, argv);
1706 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001707 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001708 if (argc < 2) return usage();
1709 return adb_auth_keygen(argv[1]);
1710 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001712 int fd = adb_connect("jdwp");
1713 if (fd >= 0) {
1714 read_and_dump(fd);
1715 adb_close(fd);
1716 return 0;
1717 } else {
1718 fprintf(stderr, "error: %s\n", adb_error());
1719 return -1;
1720 }
1721 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001722 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001723 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001724 help();
1725 return 0;
1726 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001727 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001728 version(stdout);
1729 return 0;
1730 }
1731
1732 usage();
1733 return 1;
1734}
1735
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001736#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001737static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001738{
Dan Albertbac34742015-02-25 17:51:28 -08001739 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001740 int argc;
1741 va_list ap;
1742
1743 va_start(ap, cmd);
1744 argc = 0;
1745
1746 if (serial) {
1747 argv[argc++] = "-s";
1748 argv[argc++] = serial;
1749 } else if (ttype == kTransportUsb) {
1750 argv[argc++] = "-d";
1751 } else if (ttype == kTransportLocal) {
1752 argv[argc++] = "-e";
1753 }
1754
1755 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001756 while(argc < MAX_ARGV_LENGTH &&
1757 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1758 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001759 va_end(ap);
1760
1761#if 0
1762 int n;
1763 fprintf(stderr,"argc = %d\n",argc);
1764 for(n = 0; n < argc; n++) {
1765 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1766 }
1767#endif
1768
1769 return adb_commandline(argc, argv);
1770}
1771
1772int find_sync_dirs(const char *srcarg,
Dan Albert6084a012015-03-16 21:35:53 +00001773 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001774{
Dan Albert6084a012015-03-16 21:35:53 +00001775 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001776 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001777
1778 if(srcarg == NULL) {
Dan Albert6084a012015-03-16 21:35:53 +00001779 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001780 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001781 vendor_srcdir = product_file("vendor");
Dan Albert6084a012015-03-16 21:35:53 +00001782 /* Check if vendor partition exists */
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001783 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1784 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001785 } else {
Dan Albert6084a012015-03-16 21:35:53 +00001786 /* srcarg may be "data", "system" or NULL.
1787 * if srcarg is NULL, then both data and system are synced
1788 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001789 if(strcmp(srcarg, "system") == 0) {
Dan Albert6084a012015-03-16 21:35:53 +00001790 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001791 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001792 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001793 } else if(strcmp(srcarg, "vendor") == 0) {
1794 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001795 } else {
Dan Albert6084a012015-03-16 21:35:53 +00001796 /* It's not "system", "vendor", or "data".
1797 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001798 return 1;
1799 }
1800 }
1801
Dan Albert6084a012015-03-16 21:35:53 +00001802 if(android_srcdir_out != NULL)
1803 *android_srcdir_out = android_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001804 else
Dan Albert6084a012015-03-16 21:35:53 +00001805 free(android_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001806
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001807 if(vendor_srcdir_out != NULL)
1808 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001809 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001810 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001811
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001812 if(data_srcdir_out != NULL)
Dan Albert6084a012015-03-16 21:35:53 +00001813 *data_srcdir_out = data_srcdir;
1814 else
1815 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001816 return 0;
1817}
1818
Dan Albertbac34742015-02-25 17:51:28 -08001819static int pm_command(transport_type transport, const char* serial,
1820 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001821{
1822 char buf[4096];
1823
1824 snprintf(buf, sizeof(buf), "shell:pm");
1825
1826 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001827 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001828 strncat(buf, " ", sizeof(buf) - 1);
1829 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001830 free(quoted);
1831 }
1832
1833 send_shellcommand(transport, serial, buf);
1834 return 0;
1835}
1836
Dan Albertbac34742015-02-25 17:51:28 -08001837int uninstall_app(transport_type transport, const char* serial, int argc,
1838 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001839{
1840 /* if the user choose the -k option, we refuse to do it until devices are
1841 out with the option to uninstall the remaining data somehow (adb/ui) */
1842 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1843 {
1844 printf(
1845 "The -k option uninstalls the application while retaining the data/cache.\n"
1846 "At the moment, there is no way to remove the remaining data.\n"
1847 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1848 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1849 return -1;
1850 }
1851
1852 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1853 return pm_command(transport, serial, argc, argv);
1854}
1855
Dan Albertbac34742015-02-25 17:51:28 -08001856static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001857{
1858 char buf[4096];
1859 char* quoted;
1860
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001861 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001862 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001863 strncat(buf, quoted, sizeof(buf)-1);
1864 free(quoted);
1865
1866 send_shellcommand(transport, serial, buf);
1867 return 0;
1868}
1869
Kenny Root597ea5b2011-08-05 11:19:45 -07001870static const char* get_basename(const char* filename)
1871{
1872 const char* basename = adb_dirstop(filename);
1873 if (basename) {
1874 basename++;
1875 return basename;
1876 } else {
1877 return filename;
1878 }
1879}
1880
Dan Albertbac34742015-02-25 17:51:28 -08001881int install_app(transport_type transport, const char* serial, int argc,
1882 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001883{
1884 static const char *const DATA_DEST = "/data/local/tmp/%s";
1885 static const char *const SD_DEST = "/sdcard/tmp/%s";
1886 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001887 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001888 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001889
1890 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001891 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001892 where = SD_DEST;
1893 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001894 }
1895
Jeff Sharkey960df972014-06-09 17:30:57 -07001896 // Find last APK argument.
1897 // All other arguments passed through verbatim.
1898 int last_apk = -1;
1899 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001900 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001901 char* dot = strrchr(file, '.');
1902 if (dot && !strcasecmp(dot, ".apk")) {
1903 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1904 fprintf(stderr, "Invalid APK file: %s\n", file);
1905 return -1;
1906 }
1907
1908 last_apk = i;
1909 break;
1910 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001911 }
1912
Jeff Sharkey960df972014-06-09 17:30:57 -07001913 if (last_apk == -1) {
1914 fprintf(stderr, "Missing APK file\n");
1915 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001916 }
1917
Dan Albertbac34742015-02-25 17:51:28 -08001918 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001919 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001920 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001921 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001922 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001923 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001924 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001925 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001926 }
1927
1928 pm_command(transport, serial, argc, argv);
1929
Kenny Root60733e92012-03-26 16:14:02 -07001930cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001931 delete_file(transport, serial, apk_dest);
1932 return err;
1933}
1934
Dan Albertbac34742015-02-25 17:51:28 -08001935int install_multiple_app(transport_type transport, const char* serial, int argc,
1936 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001937{
1938 char buf[1024];
1939 int i;
1940 struct stat sb;
1941 unsigned long long total_size = 0;
1942
1943 // Find all APK arguments starting at end.
1944 // All other arguments passed through verbatim.
1945 int first_apk = -1;
1946 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001947 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001948 char* dot = strrchr(file, '.');
1949 if (dot && !strcasecmp(dot, ".apk")) {
1950 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1951 fprintf(stderr, "Invalid APK file: %s\n", file);
1952 return -1;
1953 }
1954
1955 total_size += sb.st_size;
1956 first_apk = i;
1957 } else {
1958 break;
1959 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001960 }
1961
Jeff Sharkey960df972014-06-09 17:30:57 -07001962 if (first_apk == -1) {
1963 fprintf(stderr, "Missing APK file\n");
1964 return 1;
1965 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001966
Jeff Sharkey960df972014-06-09 17:30:57 -07001967 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1968 for (i = 1; i < first_apk; i++) {
1969 char *quoted = escape_arg(argv[i]);
1970 strncat(buf, " ", sizeof(buf) - 1);
1971 strncat(buf, quoted, sizeof(buf) - 1);
1972 free(quoted);
1973 }
1974
1975 // Create install session
1976 int fd = adb_connect(buf);
1977 if (fd < 0) {
1978 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1979 return -1;
1980 }
1981 read_status_line(fd, buf, sizeof(buf));
1982 adb_close(fd);
1983
1984 int session_id = -1;
1985 if (!strncmp("Success", buf, 7)) {
1986 char* start = strrchr(buf, '[');
1987 char* end = strrchr(buf, ']');
1988 if (start && end) {
1989 *end = '\0';
1990 session_id = strtol(start + 1, NULL, 10);
1991 }
1992 }
1993 if (session_id < 0) {
1994 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001995 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001996 return -1;
1997 }
1998
1999 // Valid session, now stream the APKs
2000 int success = 1;
2001 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002002 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002003 if (stat(file, &sb) == -1) {
2004 fprintf(stderr, "Failed to stat %s\n", file);
2005 success = 0;
2006 goto finalize_session;
2007 }
2008
2009 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002010 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002011
2012 int localFd = adb_open(file, O_RDONLY);
2013 if (localFd < 0) {
2014 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2015 success = 0;
2016 goto finalize_session;
2017 }
2018
2019 int remoteFd = adb_connect(buf);
2020 if (remoteFd < 0) {
2021 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2022 adb_close(localFd);
2023 success = 0;
2024 goto finalize_session;
2025 }
2026
2027 copy_to_file(localFd, remoteFd);
2028 read_status_line(remoteFd, buf, sizeof(buf));
2029
2030 adb_close(localFd);
2031 adb_close(remoteFd);
2032
2033 if (strncmp("Success", buf, 7)) {
2034 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002035 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002036 success = 0;
2037 goto finalize_session;
2038 }
2039 }
2040
2041finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002042 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002043 if (success) {
2044 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2045 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002046 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002047 }
2048
2049 fd = adb_connect(buf);
2050 if (fd < 0) {
2051 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2052 return -1;
2053 }
2054 read_status_line(fd, buf, sizeof(buf));
2055 adb_close(fd);
2056
2057 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002058 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002059 return 0;
2060 } else {
2061 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002062 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002063 return -1;
2064 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002065}