blob: 3330baa64c643c4391977cda07e6223b1fec110a [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
19#include "sysdeps.h"
20
Dan Albert76649012015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <limits.h>
25#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080026#include <stdint.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080031#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032
Yabin Cuid325e862014-11-17 14:48:25 -080033#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080034#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080035#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036#endif
37
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080039#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080040#include "adb_client.h"
41#include "adb_io.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042#include "file_sync_service.h"
43
Dan Albertbac34742015-02-25 17:51:28 -080044static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +000047 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
48 char **oem_srcdir_out);
Dan Albertbac34742015-02-25 17:51:28 -080049int install_app(transport_type transport, const char* serial, int argc,
50 const char** argv);
51int install_multiple_app(transport_type transport, const char* serial, int argc,
52 const char** argv);
53int uninstall_app(transport_type transport, const char* serial, int argc,
54 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080055
56static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080057extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
59static char *product_file(const char *extra)
60{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080061 if (gProductOutPath == NULL) {
62 fprintf(stderr, "adb: Product directory not specified; "
63 "use -p or define ANDROID_PRODUCT_OUT\n");
64 exit(1);
65 }
66
Dan Albertbac34742015-02-25 17:51:28 -080067 int n = strlen(gProductOutPath) + strlen(extra) + 2;
68 char* x = reinterpret_cast<char*>(malloc(n));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080069 if (x == 0) {
70 fprintf(stderr, "adb: Out of memory (product_file())\n");
71 exit(1);
72 }
73
74 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
75 return x;
76}
77
78void version(FILE * out) {
79 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
80 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
81}
82
83void help()
84{
85 version(stderr);
86
87 fprintf(stderr,
88 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080089 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080090 " -d - directs command to the only connected USB device\n"
91 " returns an error if more than one USB device is present.\n"
92 " -e - directs command to the only running emulator.\n"
93 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070094 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070095 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070096 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080097 " -p <product name or path> - simple product name like 'sooner', or\n"
98 " a relative/absolute path to a product\n"
99 " out directory like 'out/target/product/sooner'.\n"
100 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
101 " environment variable is used, which must\n"
102 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800103 " -H - Name of adb server host (default: localhost)\n"
104 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700105 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700106 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400107 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
108 " Port 5555 is used by default if no port number is specified.\n"
109 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
110 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200111 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400112 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 "\n"
114 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700115 " adb push [-p] <local> <remote>\n"
116 " - copy file/dir to device\n"
117 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700118 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700119 " - copy file/dir from device\n"
120 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700121 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800122 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600123 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800124 " (see 'adb help all')\n"
125 " adb shell - run remote shell interactively\n"
126 " adb shell <command> - run remote shell command\n"
127 " adb emu <command> - run emulator console command\n"
128 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100129 " adb forward --list - list all forward socket connections.\n"
130 " the format is a list of lines with the following format:\n"
131 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800132 " adb forward <local> <remote> - forward socket connections\n"
133 " forward specs are one of: \n"
134 " tcp:<port>\n"
135 " localabstract:<unix domain socket name>\n"
136 " localreserved:<unix domain socket name>\n"
137 " localfilesystem:<unix domain socket name>\n"
138 " dev:<character device name>\n"
139 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100140 " adb forward --no-rebind <local> <remote>\n"
141 " - same as 'adb forward <local> <remote>' but fails\n"
142 " if <local> is already forwarded\n"
143 " adb forward --remove <local> - remove a specific forward socket connection\n"
144 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100145 " adb reverse --list - list all reverse socket connections from device\n"
146 " adb reverse <remote> <local> - reverse socket connections\n"
147 " reverse specs are one of:\n"
148 " tcp:<port>\n"
149 " localabstract:<unix domain socket name>\n"
150 " localreserved:<unix domain socket name>\n"
151 " localfilesystem:<unix domain socket name>\n"
152 " adb reverse --norebind <remote> <local>\n"
153 " - same as 'adb reverse <remote> <local>' but fails\n"
154 " if <remote> is already reversed.\n"
155 " adb reverse --remove <remote>\n"
156 " - remove a specific reversed socket connection\n"
157 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800158 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700159 " adb install [-lrtsd] <file>\n"
160 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700161 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700162 " (-l: forward lock application)\n"
163 " (-r: replace existing application)\n"
164 " (-t: allow test packages)\n"
165 " (-s: install application on sdcard)\n"
166 " (-d: allow version code downgrade)\n"
167 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168 " adb uninstall [-k] <package> - remove this app package from the device\n"
169 " ('-k' means keep the data and cache directories)\n"
170 " adb bugreport - return all information from the device\n"
171 " that should be included in a bug report.\n"
172 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800173 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700174 " - write an archive of the device's data to <file>.\n"
175 " If no -f option is supplied then the data is written\n"
176 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700177 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700178 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800179 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
180 " (aka .obb) files associated with each application; the default\n"
181 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700182 " (-shared|-noshared enable/disable backup of the device's\n"
183 " shared storage / SD card contents; the default is noshared.)\n"
184 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700185 " (-system|-nosystem toggles whether -all automatically includes\n"
186 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700187 " (<packages...> is the list of applications to be backed up. If\n"
188 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700189 " list is optional. Applications explicitly given on the\n"
190 " command line will be included even if -nosystem would\n"
191 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700192 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700193 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700194 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800195 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
196 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800197 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
198 " and the public key is stored in <file>.pub. Any existing files\n"
199 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 " adb help - show this help message\n"
201 " adb version - show version num\n"
202 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800203 "scripting:\n"
204 " adb wait-for-device - block until device is online\n"
205 " adb start-server - ensure that there is a server running\n"
206 " adb kill-server - kill the server if it is running\n"
207 " adb get-state - prints: offline | bootloader | device\n"
208 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700209 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000211 " 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 -0400212 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800213 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700214 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500215 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800216 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000217 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218 "networking:\n"
219 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500220 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
222 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
223 "\n"
224 "adb sync notes: adb sync [ <directory> ]\n"
225 " <localdir> can be interpreted in several ways:\n"
226 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000227 " - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000229 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000231 "\n"
232 "environmental variables:\n"
233 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
234 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
235 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
236 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800237 );
238}
239
240int usage()
241{
242 help();
243 return 1;
244}
245
Yabin Cuid325e862014-11-17 14:48:25 -0800246#if defined(_WIN32)
247
Spencer Low50184062015-03-01 15:06:21 -0800248// Implemented in sysdeps_win32.c.
249extern "C" {
250void stdin_raw_init(int fd);
251void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800252}
253
254#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255static struct termios tio_save;
256
257static void stdin_raw_init(int fd)
258{
259 struct termios tio;
260
261 if(tcgetattr(fd, &tio)) return;
262 if(tcgetattr(fd, &tio_save)) return;
263
264 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
265
266 /* no timeout but request at least one character per read */
267 tio.c_cc[VTIME] = 0;
268 tio.c_cc[VMIN] = 1;
269
270 tcsetattr(fd, TCSANOW, &tio);
271 tcflush(fd, TCIFLUSH);
272}
273
274static void stdin_raw_restore(int fd)
275{
276 tcsetattr(fd, TCSANOW, &tio_save);
277 tcflush(fd, TCIFLUSH);
278}
279#endif
280
281static void read_and_dump(int fd)
282{
283 char buf[4096];
284 int len;
285
286 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700287 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 if(len == 0) {
291 break;
292 }
293
294 if(len < 0) {
295 if(errno == EINTR) continue;
296 break;
297 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400298 fwrite(buf, 1, len, stdout);
299 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 }
301}
302
Jeff Sharkey960df972014-06-09 17:30:57 -0700303static void read_status_line(int fd, char* buf, size_t count)
304{
305 count--;
306 while (count > 0) {
307 int len = adb_read(fd, buf, count);
308 if (len == 0) {
309 break;
310 } else if (len < 0) {
311 if (errno == EINTR) continue;
312 break;
313 }
314
315 buf += len;
316 count -= len;
317 }
318 *buf = '\0';
319}
320
Christopher Tated2f54152011-04-21 12:53:28 -0700321static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700322 const size_t BUFSIZE = 32 * 1024;
323 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700324 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700325 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700326
327 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800328
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700329 if (inFd == STDIN_FILENO) {
330 stdin_raw_init(STDIN_FILENO);
331 }
Yabin Cuid325e862014-11-17 14:48:25 -0800332
Christopher Tated2f54152011-04-21 12:53:28 -0700333 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700334 if (inFd == STDIN_FILENO) {
335 len = unix_read(inFd, buf, BUFSIZE);
336 } else {
337 len = adb_read(inFd, buf, BUFSIZE);
338 }
Christopher Tated2f54152011-04-21 12:53:28 -0700339 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700340 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700341 break;
342 }
343 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700344 if (errno == EINTR) {
345 D("copy_to_file() : EINTR, retrying\n");
346 continue;
347 }
Christopher Tated2f54152011-04-21 12:53:28 -0700348 D("copy_to_file() : error %d\n", errno);
349 break;
350 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700351 if (outFd == STDOUT_FILENO) {
352 fwrite(buf, 1, len, stdout);
353 fflush(stdout);
354 } else {
355 adb_write(outFd, buf, len);
356 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700357 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700358 }
Yabin Cuid325e862014-11-17 14:48:25 -0800359
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700360 if (inFd == STDIN_FILENO) {
361 stdin_raw_restore(STDIN_FILENO);
362 }
Yabin Cuid325e862014-11-17 14:48:25 -0800363
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700364 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700365 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700366}
367
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800368static void *stdin_read_thread(void *x)
369{
370 int fd, fdi;
371 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 int r, n;
373 int state = 0;
374
375 int *fds = (int*) x;
376 fd = fds[0];
377 fdi = fds[1];
378 free(fds);
379
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380 for(;;) {
381 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700382 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700384 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 if(r == 0) break;
386 if(r < 0) {
387 if(errno == EINTR) continue;
388 break;
389 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400390 for(n = 0; n < r; n++){
391 switch(buf[n]) {
392 case '\n':
393 state = 1;
394 break;
395 case '\r':
396 state = 1;
397 break;
398 case '~':
399 if(state == 1) state++;
400 break;
401 case '.':
402 if(state == 2) {
403 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400404 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400405 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800406 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 default:
408 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 r = adb_write(fd, buf, r);
412 if(r <= 0) {
413 break;
414 }
415 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800416 return 0;
417}
418
419int interactive_shell(void)
420{
421 adb_thread_t thr;
422 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423
424 fd = adb_connect("shell:");
425 if(fd < 0) {
426 fprintf(stderr,"error: %s\n", adb_error());
427 return 1;
428 }
429 fdi = 0; //dup(0);
430
Dan Albertbac34742015-02-25 17:51:28 -0800431 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800432 fds[0] = fd;
433 fds[1] = fdi;
434
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800435 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 adb_thread_create(&thr, stdin_read_thread, fds);
437 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 return 0;
440}
441
442
443static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
444{
445 if (serial) {
446 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
447 } else {
448 const char* prefix = "host";
449 if (ttype == kTransportUsb)
450 prefix = "host-usb";
451 else if (ttype == kTransportLocal)
452 prefix = "host-local";
453
454 snprintf(buffer, buflen, "%s:%s", prefix, command);
455 }
456}
457
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100458int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800459 unsigned progress)
460{
461 char buf[4096];
462 unsigned total;
463 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800464
465 sprintf(buf,"%s:%d", service, sz);
466 fd = adb_connect(buf);
467 if(fd < 0) {
468 fprintf(stderr,"error: %s\n", adb_error());
469 return -1;
470 }
471
472 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800473 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800474
475 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800476 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800477
478 if(progress) {
479 char *x = strrchr(service, ':');
480 if(x) service = x + 1;
481 }
482
483 while(sz > 0) {
484 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800485 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800486 adb_status(fd);
487 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
488 return -1;
489 }
490 sz -= xfer;
491 ptr += xfer;
492 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100493 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800494 fflush(stdout);
495 }
496 }
497 if(progress) {
498 printf("\n");
499 }
500
Dan Albertcc731cc2015-02-24 21:26:58 -0800501 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800502 fprintf(stderr,"* error reading response *\n");
503 adb_close(fd);
504 return -1;
505 }
506 if(memcmp(buf, "OKAY", 4)) {
507 buf[4] = 0;
508 fprintf(stderr,"* error response '%s' *\n", buf);
509 adb_close(fd);
510 return -1;
511 }
512
513 adb_close(fd);
514 return 0;
515}
516
517
518int adb_download(const char *service, const char *fn, unsigned progress)
519{
520 void *data;
521 unsigned sz;
522
523 data = load_file(fn, &sz);
524 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100525 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800526 return -1;
527 }
528
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100529 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800530 free(data);
531 return status;
532}
533
Doug Zongker71fe5842014-06-26 15:35:36 -0700534#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
535
536/*
537 * The sideload-host protocol serves the data in a file (given on the
538 * command line) to the client, using a simple protocol:
539 *
540 * - The connect message includes the total number of bytes in the
541 * file and a block size chosen by us.
542 *
543 * - The other side sends the desired block number as eight decimal
544 * digits (eg "00000023" for block 23). Blocks are numbered from
545 * zero.
546 *
547 * - We send back the data of the requested block. The last block is
548 * likely to be partial; when the last block is requested we only
549 * send the part of the block that exists, it's not padded up to the
550 * block size.
551 *
552 * - When the other side sends "DONEDONE" instead of a block number,
553 * we hang up.
554 */
555int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700556 unsigned sz;
557 size_t xfer = 0;
558 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800559 int last_percent = -1;
560 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700561
562 printf("loading: '%s'", fn);
563 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800564 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700565 if (data == 0) {
566 printf("\n");
567 fprintf(stderr, "* cannot read '%s' *\n", fn);
568 return -1;
569 }
570
571 char buf[100];
572 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
573 int fd = adb_connect(buf);
574 if (fd < 0) {
575 // Try falling back to the older sideload method. Maybe this
576 // is an older device that doesn't support sideload-host.
577 printf("\n");
578 status = adb_download_buffer("sideload", fn, data, sz, 1);
579 goto done;
580 }
581
Spencer Lowf055c192015-01-25 14:40:16 -0800582 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700583
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700584 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800585 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700586 fprintf(stderr, "* failed to read command: %s\n", adb_error());
587 status = -1;
588 goto done;
589 }
590
591 if (strncmp("DONEDONE", buf, 8) == 0) {
592 status = 0;
593 break;
594 }
595
596 buf[8] = '\0';
597 int block = strtol(buf, NULL, 10);
598
599 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
600 if (offset >= sz) {
601 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
602 status = -1;
603 goto done;
604 }
605 uint8_t* start = data + offset;
606 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
607 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
608 if (offset_end > sz) {
609 to_write = sz - offset;
610 }
611
Dan Albertcc731cc2015-02-24 21:26:58 -0800612 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700613 adb_status(fd);
614 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
615 status = -1;
616 goto done;
617 }
618 xfer += to_write;
619
620 // For normal OTA packages, we expect to transfer every byte
621 // twice, plus a bit of overhead (one read during
622 // verification, one read of each byte for installation, plus
623 // extra access to things like the zip central directory).
624 // This estimate of the completion becomes 100% when we've
625 // transferred ~2.13 (=100/47) times the package size.
626 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
627 if (percent != last_percent) {
628 printf("\rserving: '%s' (~%d%%) ", fn, percent);
629 fflush(stdout);
630 last_percent = percent;
631 }
632 }
633
Colin Cross6d6a8982014-07-07 14:12:41 -0700634 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700635
636 done:
637 if (fd >= 0) adb_close(fd);
638 free(data);
639 return status;
640}
641
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800642static void status_window(transport_type ttype, const char* serial)
643{
644 char command[4096];
645 char *state = 0;
646 char *laststate = 0;
647
648 /* silence stderr */
649#ifdef _WIN32
650 /* XXX: TODO */
651#else
652 int fd;
653 fd = unix_open("/dev/null", O_WRONLY);
654 dup2(fd, 2);
655 adb_close(fd);
656#endif
657
658 format_host_command(command, sizeof command, "get-state", ttype, serial);
659
660 for(;;) {
661 adb_sleep_ms(250);
662
663 if(state) {
664 free(state);
665 state = 0;
666 }
667
668 state = adb_query(command);
669
670 if(state) {
671 if(laststate && !strcmp(state,laststate)){
672 continue;
673 } else {
674 if(laststate) free(laststate);
675 laststate = strdup(state);
676 }
677 }
678
679 printf("%c[2J%c[2H", 27, 27);
680 printf("Android Debug Bridge\n");
681 printf("State: %s\n", state ? state : "offline");
682 fflush(stdout);
683 }
684}
685
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700686static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700687{
688 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
689}
690
691/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700692static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693{
694 const char *ts;
695 size_t alloc_len;
696 char *ret;
697 char *dest;
698
Jeff Sharkey7c460352014-06-10 16:22:17 -0700699 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700700 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700702 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 alloc_len++;
704 }
705 }
706
Jeff Sharkey7c460352014-06-10 16:22:17 -0700707 if (alloc_len == 0) {
708 // Preserve empty arguments
709 ret = (char *) malloc(3);
710 ret[0] = '\"';
711 ret[1] = '\"';
712 ret[2] = '\0';
713 return ret;
714 }
715
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700716 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800717 dest = ret;
718
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700719 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700720 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 *dest++ = '\\';
722 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800723 *dest++ = *ts;
724 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725 *dest++ = '\0';
726
727 return ret;
728}
729
730/**
731 * Run ppp in "notty" mode against a resource listed as the first parameter
732 * eg:
733 *
734 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
735 *
736 */
Dan Albertbac34742015-02-25 17:51:28 -0800737int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800738{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800739#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800740 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
741 return -1;
742#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800743 pid_t pid;
744 int fd;
745
746 if (argc < 2) {
747 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
748 argv[0]);
749
750 return 1;
751 }
752
Dan Albertbac34742015-02-25 17:51:28 -0800753 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800754 fd = adb_connect(adb_service_name);
755
756 if(fd < 0) {
757 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
758 adb_service_name, adb_error());
759 return 1;
760 }
761
762 pid = fork();
763
764 if (pid < 0) {
765 perror("from fork()");
766 return 1;
767 } else if (pid == 0) {
768 int err;
769 int i;
770 const char **ppp_args;
771
772 // copy args
773 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
774 ppp_args[0] = "pppd";
775 for (i = 2 ; i < argc ; i++) {
776 //argv[2] and beyond become ppp_args[1] and beyond
777 ppp_args[i - 1] = argv[i];
778 }
779 ppp_args[i-1] = NULL;
780
781 // child side
782
783 dup2(fd, STDIN_FILENO);
784 dup2(fd, STDOUT_FILENO);
785 adb_close(STDERR_FILENO);
786 adb_close(fd);
787
788 err = execvp("pppd", (char * const *)ppp_args);
789
790 if (err < 0) {
791 perror("execing pppd");
792 }
793 exit(-1);
794 } else {
795 // parent side
796
797 adb_close(fd);
798 return 0;
799 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800800#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800801}
802
Dan Albertbac34742015-02-25 17:51:28 -0800803static int send_shellcommand(transport_type transport, const char* serial,
804 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800805{
806 int fd, ret;
807
808 for(;;) {
809 fd = adb_connect(buf);
810 if(fd >= 0)
811 break;
812 fprintf(stderr,"- waiting for device -\n");
813 adb_sleep_ms(1000);
814 do_cmd(transport, serial, "wait-for-device", 0);
815 }
816
817 read_and_dump(fd);
818 ret = adb_close(fd);
819 if (ret)
820 perror("close");
821
822 return ret;
823}
824
Dan Albertbac34742015-02-25 17:51:28 -0800825static int logcat(transport_type transport, const char* serial, int argc,
826 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800827{
828 char buf[4096];
829
830 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700831 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800832
833 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700834 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700836 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700837 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800838
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700839 if (!strcmp(argv[0], "longcat")) {
840 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800841 }
842
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800843 argc -= 1;
844 argv += 1;
845 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700846 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700847 strncat(buf, " ", sizeof(buf) - 1);
848 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800849 free(quoted);
850 }
851
852 send_shellcommand(transport, serial, buf);
853 return 0;
854}
855
Mark Salyzyn60299df2014-04-30 09:10:31 -0700856static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800857{
858 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700859 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800860
861 for(;;) {
862 x = adb_dirstart(x);
863 if(x == 0) return 0;
864 *x = 0;
865 ret = adb_mkdir(path, 0775);
866 *x = OS_PATH_SEPARATOR;
867 if((ret < 0) && (errno != EEXIST)) {
868 return ret;
869 }
870 x++;
871 }
872 return 0;
873}
874
Dan Albertbac34742015-02-25 17:51:28 -0800875static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700876 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800877 char default_name[32];
878 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700879 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700880 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700881
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700882 /* find, extract, and use any -f argument */
883 for (i = 1; i < argc; i++) {
884 if (!strcmp("-f", argv[i])) {
885 if (i == argc-1) {
886 fprintf(stderr, "adb: -f passed with no filename\n");
887 return usage();
888 }
889 filename = argv[i+1];
890 for (j = i+2; j <= argc; ) {
891 argv[i++] = argv[j++];
892 }
893 argc -= 2;
894 argv[argc] = NULL;
895 }
Christopher Tated2f54152011-04-21 12:53:28 -0700896 }
897
Christopher Tatebb86bc52011-08-22 17:12:08 -0700898 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
899 if (argc < 2) return usage();
900
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800901 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700902 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800903 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700904 if (outFd < 0) {
905 fprintf(stderr, "adb: unable to open file %s\n", filename);
906 return -1;
907 }
908
909 snprintf(buf, sizeof(buf), "backup");
910 for (argc--, argv++; argc; argc--, argv++) {
911 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
912 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
913 }
914
915 D("backup. filename=%s buf=%s\n", filename, buf);
916 fd = adb_connect(buf);
917 if (fd < 0) {
918 fprintf(stderr, "adb: unable to connect for backup\n");
919 adb_close(outFd);
920 return -1;
921 }
922
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800923 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700924 copy_to_file(fd, outFd);
925
926 adb_close(fd);
927 adb_close(outFd);
928 return 0;
929}
930
Dan Albertbac34742015-02-25 17:51:28 -0800931static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700932 const char* filename;
933 int fd, tarFd;
934
935 if (argc != 2) return usage();
936
937 filename = argv[1];
938 tarFd = adb_open(filename, O_RDONLY);
939 if (tarFd < 0) {
940 fprintf(stderr, "adb: unable to open file %s\n", filename);
941 return -1;
942 }
943
944 fd = adb_connect("restore:");
945 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700946 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700947 adb_close(tarFd);
948 return -1;
949 }
950
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800951 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700952 copy_to_file(tarFd, fd);
953
954 adb_close(fd);
955 adb_close(tarFd);
956 return 0;
957}
958
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800959#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
960static int top_works(const char *top)
961{
962 if (top != NULL && adb_is_absolute_host_path(top)) {
963 char path_buf[PATH_MAX];
964 snprintf(path_buf, sizeof(path_buf),
965 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
966 return access(path_buf, F_OK) == 0;
967 }
968 return 0;
969}
970
971static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
972{
973 strcpy(path_buf, indir);
974 while (1) {
975 if (top_works(path_buf)) {
976 return path_buf;
977 }
978 char *s = adb_dirstop(path_buf);
979 if (s != NULL) {
980 *s = '\0';
981 } else {
982 path_buf[0] = '\0';
983 return NULL;
984 }
985 }
986}
987
988static char *find_top(char path_buf[PATH_MAX])
989{
990 char *top = getenv("ANDROID_BUILD_TOP");
991 if (top != NULL && top[0] != '\0') {
992 if (!top_works(top)) {
993 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
994 return NULL;
995 }
996 } else {
997 top = getenv("TOP");
998 if (top != NULL && top[0] != '\0') {
999 if (!top_works(top)) {
1000 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1001 return NULL;
1002 }
1003 } else {
1004 top = NULL;
1005 }
1006 }
1007
1008 if (top != NULL) {
1009 /* The environment pointed to a top directory that works.
1010 */
1011 strcpy(path_buf, top);
1012 return path_buf;
1013 }
1014
1015 /* The environment didn't help. Walk up the tree from the CWD
1016 * to see if we can find the top.
1017 */
1018 char dir[PATH_MAX];
1019 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1020 if (top == NULL) {
1021 /* If the CWD isn't under a good-looking top, see if the
1022 * executable is.
1023 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001024 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001025 top = find_top_from(dir, path_buf);
1026 }
1027 return top;
1028}
1029
1030/* <hint> may be:
1031 * - A simple product name
1032 * e.g., "sooner"
1033TODO: debug? sooner-debug, sooner:debug?
1034 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1035 * e.g., "out/target/product/sooner"
1036 * - An absolute path to the PRODUCT_OUT dir
1037 * e.g., "/src/device/out/target/product/sooner"
1038 *
1039 * Given <hint>, try to construct an absolute path to the
1040 * ANDROID_PRODUCT_OUT dir.
1041 */
1042static const char *find_product_out_path(const char *hint)
1043{
1044 static char path_buf[PATH_MAX];
1045
1046 if (hint == NULL || hint[0] == '\0') {
1047 return NULL;
1048 }
1049
1050 /* If it's already absolute, don't bother doing any work.
1051 */
1052 if (adb_is_absolute_host_path(hint)) {
1053 strcpy(path_buf, hint);
1054 return path_buf;
1055 }
1056
1057 /* If there are any slashes in it, assume it's a relative path;
1058 * make it absolute.
1059 */
1060 if (adb_dirstart(hint) != NULL) {
1061 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1062 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1063 return NULL;
1064 }
1065 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1066 fprintf(stderr, "adb: Couldn't assemble path\n");
1067 return NULL;
1068 }
1069 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1070 strcat(path_buf, hint);
1071 return path_buf;
1072 }
1073
1074 /* It's a string without any slashes. Try to do something with it.
1075 *
1076 * Try to find the root of the build tree, and build a PRODUCT_OUT
1077 * path from there.
1078 */
1079 char top_buf[PATH_MAX];
1080 const char *top = find_top(top_buf);
1081 if (top == NULL) {
1082 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1083 return NULL;
1084 }
1085//TODO: if we have a way to indicate debug, look in out/debug/target/...
1086 snprintf(path_buf, sizeof(path_buf),
1087 "%s" OS_PATH_SEPARATOR_STR
1088 "out" OS_PATH_SEPARATOR_STR
1089 "target" OS_PATH_SEPARATOR_STR
1090 "product" OS_PATH_SEPARATOR_STR
1091 "%s", top_buf, hint);
1092 if (access(path_buf, F_OK) < 0) {
1093 fprintf(stderr, "adb: Couldn't find a product dir "
1094 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1095 return NULL;
1096 }
1097 return path_buf;
1098}
1099
Dan Albertbac34742015-02-25 17:51:28 -08001100static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1101 char const **path2, int *show_progress,
1102 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001103 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001104 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001105
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001106 while (narg > 0) {
1107 if (!strcmp(*arg, "-p")) {
1108 *show_progress = 1;
1109 } else if (!strcmp(*arg, "-a")) {
1110 *copy_attrs = 1;
1111 } else {
1112 break;
1113 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001114 ++arg;
1115 --narg;
1116 }
1117
1118 if (narg > 0) {
1119 *path1 = *arg;
1120 ++arg;
1121 --narg;
1122 }
1123
1124 if (narg > 0) {
1125 *path2 = *arg;
1126 }
1127}
1128
Dan Albertbac34742015-02-25 17:51:28 -08001129int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001130{
1131 char buf[4096];
1132 int no_daemon = 0;
1133 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001134 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001135 int persist = 0;
1136 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001138 const char* serial = NULL;
1139 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001140
1141 /* If defined, this should be an absolute path to
1142 * the directory containing all of the various system images
1143 * for a particular product. If not defined, and the adb
1144 * command requires this information, then the user must
1145 * specify the path using "-p".
1146 */
1147 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1148 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1149 gProductOutPath = NULL;
1150 }
1151 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1152
Nick Pellydb449262009-05-07 12:48:03 -07001153 serial = getenv("ANDROID_SERIAL");
1154
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001155 /* Validate and assign the server port */
1156 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1157 int server_port = DEFAULT_ADB_PORT;
1158 if (server_port_str && strlen(server_port_str) > 0) {
1159 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001160 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001161 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001162 "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 +01001163 server_port_str);
1164 return usage();
1165 }
1166 }
1167
1168 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001169 while (argc > 0) {
1170 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001171 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001172 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001173 no_daemon = 1;
1174 } else if (!strcmp(argv[0], "fork-server")) {
1175 /* this is a special flag used only when the ADB client launches the ADB Server */
1176 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001177 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001178 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001179 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001180 const char *product = NULL;
1181 if (argv[0][2] == '\0') {
1182 if (argc < 2) return usage();
1183 product = argv[1];
1184 argc--;
1185 argv++;
1186 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001187 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001188 }
1189 gProductOutPath = find_product_out_path(product);
1190 if (gProductOutPath == NULL) {
1191 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1192 product);
1193 return usage();
1194 }
1195 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1196 if (isdigit(argv[0][2])) {
1197 serial = argv[0] + 2;
1198 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001199 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001200 serial = argv[1];
1201 argc--;
1202 argv++;
1203 }
1204 } else if (!strcmp(argv[0],"-d")) {
1205 ttype = kTransportUsb;
1206 } else if (!strcmp(argv[0],"-e")) {
1207 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001208 } else if (!strcmp(argv[0],"-a")) {
1209 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001210 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001211 const char *hostname = NULL;
1212 if (argv[0][2] == '\0') {
1213 if (argc < 2) return usage();
1214 hostname = argv[1];
1215 argc--;
1216 argv++;
1217 } else {
1218 hostname = argv[0] + 2;
1219 }
1220 adb_set_tcp_name(hostname);
1221
Riley Andrews98f58e82014-12-05 17:37:24 -08001222 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001223 if (argv[0][2] == '\0') {
1224 if (argc < 2) return usage();
1225 server_port_str = argv[1];
1226 argc--;
1227 argv++;
1228 } else {
1229 server_port_str = argv[0] + 2;
1230 }
1231 if (strlen(server_port_str) > 0) {
1232 server_port = (int) strtol(server_port_str, NULL, 0);
1233 if (server_port <= 0 || server_port > 65535) {
1234 fprintf(stderr,
1235 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1236 server_port_str);
1237 return usage();
1238 }
1239 } else {
1240 fprintf(stderr,
1241 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1242 return usage();
1243 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001244 } else {
1245 /* out of recognized modifiers and flags */
1246 break;
1247 }
1248 argc--;
1249 argv++;
1250 }
1251
1252 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001253 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001254
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001255 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001256 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001257 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001259 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001260 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001261 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001262 fprintf(stderr,"* could not start server *\n");
1263 }
1264 return r;
1265 }
1266
Riley Andrews98f58e82014-12-05 17:37:24 -08001267 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001268 return usage();
1269 }
1270
Riley Andrewsc8514c82014-12-05 17:32:46 -08001271 /* handle wait-for-* prefix */
1272 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001273 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001274 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1275 if (ttype == kTransportUsb) {
1276 service = "wait-for-usb";
1277 } else if (ttype == kTransportLocal) {
1278 service = "wait-for-local";
1279 } else {
1280 service = "wait-for-any";
1281 }
1282 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001283
Riley Andrewsc8514c82014-12-05 17:32:46 -08001284 format_host_command(buf, sizeof buf, service, ttype, serial);
1285
1286 if (adb_command(buf)) {
1287 D("failure: %s *\n",adb_error());
1288 fprintf(stderr,"error: %s\n", adb_error());
1289 return 1;
1290 }
1291
1292 /* Allow a command to be run after wait-for-device,
1293 * e.g. 'adb wait-for-device shell'.
1294 */
1295 if (argc == 1) {
1296 return 0;
1297 }
1298
1299 /* Fall through */
1300 argc--;
1301 argv++;
1302 }
1303
1304 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001305 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001306 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001307 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001308 if (argc < 2)
1309 listopt = "";
1310 else if (argc == 2 && !strcmp(argv[1], "-l"))
1311 listopt = argv[1];
1312 else {
1313 fprintf(stderr, "Usage: adb devices [-l]\n");
1314 return 1;
1315 }
1316 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001317 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001318 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001319 printf("List of devices attached \n");
1320 printf("%s\n", tmp);
1321 return 0;
1322 } else {
1323 return 1;
1324 }
1325 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001326 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001327 char *tmp;
1328 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001329 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001330 return 1;
1331 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001332 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1333 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001334 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001335 printf("%s\n", tmp);
1336 return 0;
1337 } else {
1338 return 1;
1339 }
1340 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001341 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001342 char *tmp;
1343 if (argc > 2) {
1344 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1345 return 1;
1346 }
1347 if (argc == 2) {
1348 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1349 } else {
1350 snprintf(buf, sizeof buf, "host:disconnect:");
1351 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001352 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001353 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001354 printf("%s\n", tmp);
1355 return 0;
1356 } else {
1357 return 1;
1358 }
1359 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001360 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001361 return adb_send_emulator_command(argc, argv);
1362 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001363 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 int r;
1365 int fd;
1366
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001367 char h = (argv[0][0] == 'h');
1368
1369 if (h) {
1370 printf("\x1b[41;33m");
1371 fflush(stdout);
1372 }
1373
Riley Andrews98f58e82014-12-05 17:37:24 -08001374 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001375 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001376 r = interactive_shell();
1377 if (h) {
1378 printf("\x1b[0m");
1379 fflush(stdout);
1380 }
1381 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001382 }
1383
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001384 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385 argc -= 2;
1386 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001387 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001388 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001389 strncat(buf, " ", sizeof(buf) - 1);
1390 strncat(buf, quoted, sizeof(buf) - 1);
1391 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001392 }
1393
1394 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001395 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001397 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001398 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001399 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001400 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001401 adb_close(fd);
1402 r = 0;
1403 } else {
1404 fprintf(stderr,"error: %s\n", adb_error());
1405 r = -1;
1406 }
1407
Riley Andrews98f58e82014-12-05 17:37:24 -08001408 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001409 fprintf(stderr,"\n- waiting for device -\n");
1410 adb_sleep_ms(1000);
1411 do_cmd(ttype, serial, "wait-for-device", 0);
1412 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001413 if (h) {
1414 printf("\x1b[0m");
1415 fflush(stdout);
1416 }
JP Abgrall408fa572011-03-16 15:57:42 -07001417 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418 return r;
1419 }
1420 }
1421 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001422 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001423 int exec_in = !strcmp(argv[0], "exec-in");
1424 int fd;
1425
1426 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1427 argc -= 2;
1428 argv += 2;
1429 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001430 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001431 strncat(buf, " ", sizeof(buf) - 1);
1432 strncat(buf, quoted, sizeof(buf) - 1);
1433 free(quoted);
1434 }
1435
1436 fd = adb_connect(buf);
1437 if (fd < 0) {
1438 fprintf(stderr, "error: %s\n", adb_error());
1439 return -1;
1440 }
1441
1442 if (exec_in) {
1443 copy_to_file(STDIN_FILENO, fd);
1444 } else {
1445 copy_to_file(fd, STDOUT_FILENO);
1446 }
1447
1448 adb_close(fd);
1449 return 0;
1450 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001451 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001452 int fd;
1453 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001454 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001455 fprintf(stderr,"* server not running *\n");
1456 return 1;
1457 }
1458 return 0;
1459 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001460 else if (!strcmp(argv[0], "sideload")) {
1461 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001462 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001463 return 1;
1464 } else {
1465 return 0;
1466 }
1467 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001468 else if (!strcmp(argv[0], "remount") ||
1469 !strcmp(argv[0], "reboot") ||
1470 !strcmp(argv[0], "reboot-bootloader") ||
1471 !strcmp(argv[0], "tcpip") ||
1472 !strcmp(argv[0], "usb") ||
1473 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001474 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001475 !strcmp(argv[0], "disable-verity") ||
1476 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001477 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001478 if (!strcmp(argv[0], "reboot-bootloader"))
1479 snprintf(command, sizeof(command), "reboot:bootloader");
1480 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001481 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001482 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001483 snprintf(command, sizeof(command), "%s:", argv[0]);
1484 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001485 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001486 read_and_dump(fd);
1487 adb_close(fd);
1488 return 0;
1489 }
1490 fprintf(stderr,"error: %s\n", adb_error());
1491 return 1;
1492 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001493 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001494 if (argc != 1) return usage();
1495 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001496 return 0;
1497 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001498 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001499 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001500 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001501 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001502 char remove = 0;
1503 char remove_all = 0;
1504 char list = 0;
1505 char no_rebind = 0;
1506
1507 // Parse options here.
1508 while (argc > 1 && argv[1][0] == '-') {
1509 if (!strcmp(argv[1], "--list"))
1510 list = 1;
1511 else if (!strcmp(argv[1], "--remove"))
1512 remove = 1;
1513 else if (!strcmp(argv[1], "--remove-all"))
1514 remove_all = 1;
1515 else if (!strcmp(argv[1], "--no-rebind"))
1516 no_rebind = 1;
1517 else {
1518 return usage();
1519 }
1520 argc--;
1521 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001522 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001523
1524 // Ensure we can only use one option at a time.
1525 if (list + remove + remove_all + no_rebind > 1) {
1526 return usage();
1527 }
1528
1529 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001530 if (reverse) {
1531 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001532 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001533 if (serial) {
1534 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1535 serial);
1536 } else if (ttype == kTransportUsb) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1538 } else if (ttype == kTransportLocal) {
1539 snprintf(host_prefix, sizeof host_prefix, "host-local");
1540 } else {
1541 snprintf(host_prefix, sizeof host_prefix, "host");
1542 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001543 }
1544
1545 // Implement forward --list
1546 if (list) {
1547 if (argc != 1)
1548 return usage();
1549 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1550 char* forwards = adb_query(buf);
1551 if (forwards == NULL) {
1552 fprintf(stderr, "error: %s\n", adb_error());
1553 return 1;
1554 }
1555 printf("%s", forwards);
1556 free(forwards);
1557 return 0;
1558 }
1559
1560 // Implement forward --remove-all
1561 else if (remove_all) {
1562 if (argc != 1)
1563 return usage();
1564 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1565 }
1566
1567 // Implement forward --remove <local>
1568 else if (remove) {
1569 if (argc != 2)
1570 return usage();
1571 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1572 }
1573 // Or implement one of:
1574 // forward <local> <remote>
1575 // forward --no-rebind <local> <remote>
1576 else
1577 {
1578 if (argc != 3)
1579 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001580 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001581 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1582 }
1583
Riley Andrews98f58e82014-12-05 17:37:24 -08001584 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001585 fprintf(stderr,"error: %s\n", adb_error());
1586 return 1;
1587 }
1588 return 0;
1589 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001590 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001591 else if (!strcmp(argv[0], "ls")) {
1592 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001593 return do_sync_ls(argv[1]);
1594 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001595 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001596 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001597 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001598 const char* lpath = NULL, *rpath = NULL;
1599
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001600 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001601
1602 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001603 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001604 }
1605
1606 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001607 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001608 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001609 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001610 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001611 const char* rpath = NULL, *lpath = ".";
1612
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001613 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001614
1615 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001616 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001617 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001618
1619 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001620 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001621 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001622 if (argc < 2) return usage();
1623 return install_app(ttype, serial, argc, argv);
1624 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001625 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001626 if (argc < 2) return usage();
1627 return install_multiple_app(ttype, serial, argc, argv);
1628 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001629 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001630 if (argc < 2) return usage();
1631 return uninstall_app(ttype, serial, argc, argv);
1632 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001633 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001634 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001635 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1636
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 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001656 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1657 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001658 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001659
Elliott Hughesec7a6672015-03-16 21:58:32 +00001660 if (system_srcpath != NULL)
1661 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001662 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001663 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001664 if(ret == 0 && oem_srcpath != NULL)
1665 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001666 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001667 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001668
Elliott Hughesec7a6672015-03-16 21:58:32 +00001669 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001670 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001671 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001672 free(data_srcpath);
1673 return ret;
1674 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001675 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001676 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001677 !strcmp(argv[0],"get-serialno") ||
1678 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001679 {
1680 char *tmp;
1681
1682 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1683 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001684 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001685 printf("%s\n", tmp);
1686 return 0;
1687 } else {
1688 return 1;
1689 }
1690 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001691 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001692 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001693 status_window(ttype, serial);
1694 return 0;
1695 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001696 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001697 return logcat(ttype, serial, argc, argv);
1698 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001699 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001700 return ppp(argc, argv);
1701 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001703 return adb_connect("host:start-server");
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001706 return backup(argc, argv);
1707 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001709 return restore(argc, argv);
1710 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001712 if (argc < 2) return usage();
1713 return adb_auth_keygen(argv[1]);
1714 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001715 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001716 int fd = adb_connect("jdwp");
1717 if (fd >= 0) {
1718 read_and_dump(fd);
1719 adb_close(fd);
1720 return 0;
1721 } else {
1722 fprintf(stderr, "error: %s\n", adb_error());
1723 return -1;
1724 }
1725 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001726 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001727 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001728 help();
1729 return 0;
1730 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001731 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001732 version(stdout);
1733 return 0;
1734 }
1735
1736 usage();
1737 return 1;
1738}
1739
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001740#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001741static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001742{
Dan Albertbac34742015-02-25 17:51:28 -08001743 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001744 int argc;
1745 va_list ap;
1746
1747 va_start(ap, cmd);
1748 argc = 0;
1749
1750 if (serial) {
1751 argv[argc++] = "-s";
1752 argv[argc++] = serial;
1753 } else if (ttype == kTransportUsb) {
1754 argv[argc++] = "-d";
1755 } else if (ttype == kTransportLocal) {
1756 argv[argc++] = "-e";
1757 }
1758
1759 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001760 while(argc < MAX_ARGV_LENGTH &&
1761 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1762 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001763 va_end(ap);
1764
1765#if 0
1766 int n;
1767 fprintf(stderr,"argc = %d\n",argc);
1768 for(n = 0; n < argc; n++) {
1769 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1770 }
1771#endif
1772
1773 return adb_commandline(argc, argv);
1774}
1775
1776int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001777 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1778 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001779{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001780 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001781 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001782
1783 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001784 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001785 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001786 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001787 oem_srcdir = product_file("oem");
1788 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001789 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1790 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001791 // Check if oem partition exists.
1792 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1793 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001794 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001795 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1796 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001797 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001798 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001799 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001800 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001801 } else if(strcmp(srcarg, "vendor") == 0) {
1802 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001803 } else if(strcmp(srcarg, "oem") == 0) {
1804 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001805 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001806 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001807 return 1;
1808 }
1809 }
1810
Elliott Hughesec7a6672015-03-16 21:58:32 +00001811 if(system_srcdir_out != NULL)
1812 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001813 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001814 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001816 if(vendor_srcdir_out != NULL)
1817 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001818 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001819 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001820
Elliott Hughesec7a6672015-03-16 21:58:32 +00001821 if(oem_srcdir_out != NULL)
1822 *oem_srcdir_out = oem_srcdir;
1823 else
1824 free(oem_srcdir);
1825
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001826 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001827 *data_srcdir_out = data_srcdir;
1828 else
1829 free(data_srcdir);
1830
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001831 return 0;
1832}
1833
Dan Albertbac34742015-02-25 17:51:28 -08001834static int pm_command(transport_type transport, const char* serial,
1835 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001836{
1837 char buf[4096];
1838
1839 snprintf(buf, sizeof(buf), "shell:pm");
1840
1841 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001842 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001843 strncat(buf, " ", sizeof(buf) - 1);
1844 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001845 free(quoted);
1846 }
1847
1848 send_shellcommand(transport, serial, buf);
1849 return 0;
1850}
1851
Dan Albertbac34742015-02-25 17:51:28 -08001852int uninstall_app(transport_type transport, const char* serial, int argc,
1853 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001854{
1855 /* if the user choose the -k option, we refuse to do it until devices are
1856 out with the option to uninstall the remaining data somehow (adb/ui) */
1857 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1858 {
1859 printf(
1860 "The -k option uninstalls the application while retaining the data/cache.\n"
1861 "At the moment, there is no way to remove the remaining data.\n"
1862 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1863 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1864 return -1;
1865 }
1866
1867 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1868 return pm_command(transport, serial, argc, argv);
1869}
1870
Dan Albertbac34742015-02-25 17:51:28 -08001871static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001872{
1873 char buf[4096];
1874 char* quoted;
1875
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001876 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001877 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001878 strncat(buf, quoted, sizeof(buf)-1);
1879 free(quoted);
1880
1881 send_shellcommand(transport, serial, buf);
1882 return 0;
1883}
1884
Kenny Root597ea5b2011-08-05 11:19:45 -07001885static const char* get_basename(const char* filename)
1886{
1887 const char* basename = adb_dirstop(filename);
1888 if (basename) {
1889 basename++;
1890 return basename;
1891 } else {
1892 return filename;
1893 }
1894}
1895
Dan Albertbac34742015-02-25 17:51:28 -08001896int install_app(transport_type transport, const char* serial, int argc,
1897 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001898{
1899 static const char *const DATA_DEST = "/data/local/tmp/%s";
1900 static const char *const SD_DEST = "/sdcard/tmp/%s";
1901 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001902 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001903 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001904
1905 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001906 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001907 where = SD_DEST;
1908 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001909 }
1910
Jeff Sharkey960df972014-06-09 17:30:57 -07001911 // Find last APK argument.
1912 // All other arguments passed through verbatim.
1913 int last_apk = -1;
1914 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001915 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001916 char* dot = strrchr(file, '.');
1917 if (dot && !strcasecmp(dot, ".apk")) {
1918 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1919 fprintf(stderr, "Invalid APK file: %s\n", file);
1920 return -1;
1921 }
1922
1923 last_apk = i;
1924 break;
1925 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001926 }
1927
Jeff Sharkey960df972014-06-09 17:30:57 -07001928 if (last_apk == -1) {
1929 fprintf(stderr, "Missing APK file\n");
1930 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001931 }
1932
Dan Albertbac34742015-02-25 17:51:28 -08001933 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001934 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001935 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001936 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001937 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001938 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001939 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001940 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001941 }
1942
1943 pm_command(transport, serial, argc, argv);
1944
Kenny Root60733e92012-03-26 16:14:02 -07001945cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001946 delete_file(transport, serial, apk_dest);
1947 return err;
1948}
1949
Dan Albertbac34742015-02-25 17:51:28 -08001950int install_multiple_app(transport_type transport, const char* serial, int argc,
1951 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001952{
1953 char buf[1024];
1954 int i;
1955 struct stat sb;
1956 unsigned long long total_size = 0;
1957
1958 // Find all APK arguments starting at end.
1959 // All other arguments passed through verbatim.
1960 int first_apk = -1;
1961 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001962 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001963 char* dot = strrchr(file, '.');
1964 if (dot && !strcasecmp(dot, ".apk")) {
1965 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1966 fprintf(stderr, "Invalid APK file: %s\n", file);
1967 return -1;
1968 }
1969
1970 total_size += sb.st_size;
1971 first_apk = i;
1972 } else {
1973 break;
1974 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001975 }
1976
Jeff Sharkey960df972014-06-09 17:30:57 -07001977 if (first_apk == -1) {
1978 fprintf(stderr, "Missing APK file\n");
1979 return 1;
1980 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001981
Jeff Sharkey960df972014-06-09 17:30:57 -07001982 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1983 for (i = 1; i < first_apk; i++) {
1984 char *quoted = escape_arg(argv[i]);
1985 strncat(buf, " ", sizeof(buf) - 1);
1986 strncat(buf, quoted, sizeof(buf) - 1);
1987 free(quoted);
1988 }
1989
1990 // Create install session
1991 int fd = adb_connect(buf);
1992 if (fd < 0) {
1993 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1994 return -1;
1995 }
1996 read_status_line(fd, buf, sizeof(buf));
1997 adb_close(fd);
1998
1999 int session_id = -1;
2000 if (!strncmp("Success", buf, 7)) {
2001 char* start = strrchr(buf, '[');
2002 char* end = strrchr(buf, ']');
2003 if (start && end) {
2004 *end = '\0';
2005 session_id = strtol(start + 1, NULL, 10);
2006 }
2007 }
2008 if (session_id < 0) {
2009 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002010 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002011 return -1;
2012 }
2013
2014 // Valid session, now stream the APKs
2015 int success = 1;
2016 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002017 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002018 if (stat(file, &sb) == -1) {
2019 fprintf(stderr, "Failed to stat %s\n", file);
2020 success = 0;
2021 goto finalize_session;
2022 }
2023
2024 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002025 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002026
2027 int localFd = adb_open(file, O_RDONLY);
2028 if (localFd < 0) {
2029 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2030 success = 0;
2031 goto finalize_session;
2032 }
2033
2034 int remoteFd = adb_connect(buf);
2035 if (remoteFd < 0) {
2036 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2037 adb_close(localFd);
2038 success = 0;
2039 goto finalize_session;
2040 }
2041
2042 copy_to_file(localFd, remoteFd);
2043 read_status_line(remoteFd, buf, sizeof(buf));
2044
2045 adb_close(localFd);
2046 adb_close(remoteFd);
2047
2048 if (strncmp("Success", buf, 7)) {
2049 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002050 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002051 success = 0;
2052 goto finalize_session;
2053 }
2054 }
2055
2056finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002057 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002058 if (success) {
2059 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2060 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002061 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002062 }
2063
2064 fd = adb_connect(buf);
2065 if (fd < 0) {
2066 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2067 return -1;
2068 }
2069 read_status_line(fd, buf, sizeof(buf));
2070 adb_close(fd);
2071
2072 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002073 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002074 return 0;
2075 } else {
2076 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002077 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002078 return -1;
2079 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002080}