blob: c9b1eabc7b90e3f4c99313d6b9162dcd1bb6e1f2 [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
248// Windows does not have <termio.h>.
249static void stdin_raw_init(int fd) {
250
251}
252
253static void stdin_raw_restore(int fd) {
254
255}
256
257#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258static struct termios tio_save;
259
260static void stdin_raw_init(int fd)
261{
262 struct termios tio;
263
264 if(tcgetattr(fd, &tio)) return;
265 if(tcgetattr(fd, &tio_save)) return;
266
267 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
268
269 /* no timeout but request at least one character per read */
270 tio.c_cc[VTIME] = 0;
271 tio.c_cc[VMIN] = 1;
272
273 tcsetattr(fd, TCSANOW, &tio);
274 tcflush(fd, TCIFLUSH);
275}
276
277static void stdin_raw_restore(int fd)
278{
279 tcsetattr(fd, TCSANOW, &tio_save);
280 tcflush(fd, TCIFLUSH);
281}
282#endif
283
284static void read_and_dump(int fd)
285{
286 char buf[4096];
287 int len;
288
289 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700290 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700292 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800293 if(len == 0) {
294 break;
295 }
296
297 if(len < 0) {
298 if(errno == EINTR) continue;
299 break;
300 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400301 fwrite(buf, 1, len, stdout);
302 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800303 }
304}
305
Jeff Sharkey960df972014-06-09 17:30:57 -0700306static void read_status_line(int fd, char* buf, size_t count)
307{
308 count--;
309 while (count > 0) {
310 int len = adb_read(fd, buf, count);
311 if (len == 0) {
312 break;
313 } else if (len < 0) {
314 if (errno == EINTR) continue;
315 break;
316 }
317
318 buf += len;
319 count -= len;
320 }
321 *buf = '\0';
322}
323
Christopher Tated2f54152011-04-21 12:53:28 -0700324static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700325 const size_t BUFSIZE = 32 * 1024;
326 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700327 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700328 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700329
330 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800331
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700332 if (inFd == STDIN_FILENO) {
333 stdin_raw_init(STDIN_FILENO);
334 }
Yabin Cuid325e862014-11-17 14:48:25 -0800335
Christopher Tated2f54152011-04-21 12:53:28 -0700336 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700337 if (inFd == STDIN_FILENO) {
338 len = unix_read(inFd, buf, BUFSIZE);
339 } else {
340 len = adb_read(inFd, buf, BUFSIZE);
341 }
Christopher Tated2f54152011-04-21 12:53:28 -0700342 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700343 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700344 break;
345 }
346 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700347 if (errno == EINTR) {
348 D("copy_to_file() : EINTR, retrying\n");
349 continue;
350 }
Christopher Tated2f54152011-04-21 12:53:28 -0700351 D("copy_to_file() : error %d\n", errno);
352 break;
353 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700354 if (outFd == STDOUT_FILENO) {
355 fwrite(buf, 1, len, stdout);
356 fflush(stdout);
357 } else {
358 adb_write(outFd, buf, len);
359 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700360 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700361 }
Yabin Cuid325e862014-11-17 14:48:25 -0800362
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700363 if (inFd == STDIN_FILENO) {
364 stdin_raw_restore(STDIN_FILENO);
365 }
Yabin Cuid325e862014-11-17 14:48:25 -0800366
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700367 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700368 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700369}
370
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371static void *stdin_read_thread(void *x)
372{
373 int fd, fdi;
374 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 int r, n;
376 int state = 0;
377
378 int *fds = (int*) x;
379 fd = fds[0];
380 fdi = fds[1];
381 free(fds);
382
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 for(;;) {
384 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700385 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700387 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800388 if(r == 0) break;
389 if(r < 0) {
390 if(errno == EINTR) continue;
391 break;
392 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400393 for(n = 0; n < r; n++){
394 switch(buf[n]) {
395 case '\n':
396 state = 1;
397 break;
398 case '\r':
399 state = 1;
400 break;
401 case '~':
402 if(state == 1) state++;
403 break;
404 case '.':
405 if(state == 2) {
406 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400408 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400410 default:
411 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 r = adb_write(fd, buf, r);
415 if(r <= 0) {
416 break;
417 }
418 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800419 return 0;
420}
421
422int interactive_shell(void)
423{
424 adb_thread_t thr;
425 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426
427 fd = adb_connect("shell:");
428 if(fd < 0) {
429 fprintf(stderr,"error: %s\n", adb_error());
430 return 1;
431 }
432 fdi = 0; //dup(0);
433
Dan Albertbac34742015-02-25 17:51:28 -0800434 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800435 fds[0] = fd;
436 fds[1] = fdi;
437
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 adb_thread_create(&thr, stdin_read_thread, fds);
440 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800442 return 0;
443}
444
445
446static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
447{
448 if (serial) {
449 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
450 } else {
451 const char* prefix = "host";
452 if (ttype == kTransportUsb)
453 prefix = "host-usb";
454 else if (ttype == kTransportLocal)
455 prefix = "host-local";
456
457 snprintf(buffer, buflen, "%s:%s", prefix, command);
458 }
459}
460
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100461int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800462 unsigned progress)
463{
464 char buf[4096];
465 unsigned total;
466 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800467
468 sprintf(buf,"%s:%d", service, sz);
469 fd = adb_connect(buf);
470 if(fd < 0) {
471 fprintf(stderr,"error: %s\n", adb_error());
472 return -1;
473 }
474
475 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800476 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800477
478 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800479 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800480
481 if(progress) {
482 char *x = strrchr(service, ':');
483 if(x) service = x + 1;
484 }
485
486 while(sz > 0) {
487 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800488 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800489 adb_status(fd);
490 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
491 return -1;
492 }
493 sz -= xfer;
494 ptr += xfer;
495 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100496 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800497 fflush(stdout);
498 }
499 }
500 if(progress) {
501 printf("\n");
502 }
503
Dan Albertcc731cc2015-02-24 21:26:58 -0800504 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800505 fprintf(stderr,"* error reading response *\n");
506 adb_close(fd);
507 return -1;
508 }
509 if(memcmp(buf, "OKAY", 4)) {
510 buf[4] = 0;
511 fprintf(stderr,"* error response '%s' *\n", buf);
512 adb_close(fd);
513 return -1;
514 }
515
516 adb_close(fd);
517 return 0;
518}
519
520
521int adb_download(const char *service, const char *fn, unsigned progress)
522{
523 void *data;
524 unsigned sz;
525
526 data = load_file(fn, &sz);
527 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100528 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800529 return -1;
530 }
531
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100532 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800533 free(data);
534 return status;
535}
536
Doug Zongker71fe5842014-06-26 15:35:36 -0700537#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
538
539/*
540 * The sideload-host protocol serves the data in a file (given on the
541 * command line) to the client, using a simple protocol:
542 *
543 * - The connect message includes the total number of bytes in the
544 * file and a block size chosen by us.
545 *
546 * - The other side sends the desired block number as eight decimal
547 * digits (eg "00000023" for block 23). Blocks are numbered from
548 * zero.
549 *
550 * - We send back the data of the requested block. The last block is
551 * likely to be partial; when the last block is requested we only
552 * send the part of the block that exists, it's not padded up to the
553 * block size.
554 *
555 * - When the other side sends "DONEDONE" instead of a block number,
556 * we hang up.
557 */
558int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700559 unsigned sz;
560 size_t xfer = 0;
561 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800562 int last_percent = -1;
563 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700564
565 printf("loading: '%s'", fn);
566 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800567 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700568 if (data == 0) {
569 printf("\n");
570 fprintf(stderr, "* cannot read '%s' *\n", fn);
571 return -1;
572 }
573
574 char buf[100];
575 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
576 int fd = adb_connect(buf);
577 if (fd < 0) {
578 // Try falling back to the older sideload method. Maybe this
579 // is an older device that doesn't support sideload-host.
580 printf("\n");
581 status = adb_download_buffer("sideload", fn, data, sz, 1);
582 goto done;
583 }
584
Spencer Lowf055c192015-01-25 14:40:16 -0800585 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700586
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700587 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800588 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700589 fprintf(stderr, "* failed to read command: %s\n", adb_error());
590 status = -1;
591 goto done;
592 }
593
594 if (strncmp("DONEDONE", buf, 8) == 0) {
595 status = 0;
596 break;
597 }
598
599 buf[8] = '\0';
600 int block = strtol(buf, NULL, 10);
601
602 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
603 if (offset >= sz) {
604 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
605 status = -1;
606 goto done;
607 }
608 uint8_t* start = data + offset;
609 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
610 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
611 if (offset_end > sz) {
612 to_write = sz - offset;
613 }
614
Dan Albertcc731cc2015-02-24 21:26:58 -0800615 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700616 adb_status(fd);
617 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
618 status = -1;
619 goto done;
620 }
621 xfer += to_write;
622
623 // For normal OTA packages, we expect to transfer every byte
624 // twice, plus a bit of overhead (one read during
625 // verification, one read of each byte for installation, plus
626 // extra access to things like the zip central directory).
627 // This estimate of the completion becomes 100% when we've
628 // transferred ~2.13 (=100/47) times the package size.
629 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
630 if (percent != last_percent) {
631 printf("\rserving: '%s' (~%d%%) ", fn, percent);
632 fflush(stdout);
633 last_percent = percent;
634 }
635 }
636
Colin Cross6d6a8982014-07-07 14:12:41 -0700637 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700638
639 done:
640 if (fd >= 0) adb_close(fd);
641 free(data);
642 return status;
643}
644
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800645static void status_window(transport_type ttype, const char* serial)
646{
647 char command[4096];
648 char *state = 0;
649 char *laststate = 0;
650
651 /* silence stderr */
652#ifdef _WIN32
653 /* XXX: TODO */
654#else
655 int fd;
656 fd = unix_open("/dev/null", O_WRONLY);
657 dup2(fd, 2);
658 adb_close(fd);
659#endif
660
661 format_host_command(command, sizeof command, "get-state", ttype, serial);
662
663 for(;;) {
664 adb_sleep_ms(250);
665
666 if(state) {
667 free(state);
668 state = 0;
669 }
670
671 state = adb_query(command);
672
673 if(state) {
674 if(laststate && !strcmp(state,laststate)){
675 continue;
676 } else {
677 if(laststate) free(laststate);
678 laststate = strdup(state);
679 }
680 }
681
682 printf("%c[2J%c[2H", 27, 27);
683 printf("Android Debug Bridge\n");
684 printf("State: %s\n", state ? state : "offline");
685 fflush(stdout);
686 }
687}
688
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700689static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700690{
691 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
692}
693
694/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700695static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696{
697 const char *ts;
698 size_t alloc_len;
699 char *ret;
700 char *dest;
701
Jeff Sharkey7c460352014-06-10 16:22:17 -0700702 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700703 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800704 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700705 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706 alloc_len++;
707 }
708 }
709
Jeff Sharkey7c460352014-06-10 16:22:17 -0700710 if (alloc_len == 0) {
711 // Preserve empty arguments
712 ret = (char *) malloc(3);
713 ret[0] = '\"';
714 ret[1] = '\"';
715 ret[2] = '\0';
716 return ret;
717 }
718
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700719 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800720 dest = ret;
721
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700722 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700723 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800724 *dest++ = '\\';
725 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800726 *dest++ = *ts;
727 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800728 *dest++ = '\0';
729
730 return ret;
731}
732
733/**
734 * Run ppp in "notty" mode against a resource listed as the first parameter
735 * eg:
736 *
737 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
738 *
739 */
Dan Albertbac34742015-02-25 17:51:28 -0800740int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800741{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800742#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800743 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
744 return -1;
745#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800746 pid_t pid;
747 int fd;
748
749 if (argc < 2) {
750 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
751 argv[0]);
752
753 return 1;
754 }
755
Dan Albertbac34742015-02-25 17:51:28 -0800756 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800757 fd = adb_connect(adb_service_name);
758
759 if(fd < 0) {
760 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
761 adb_service_name, adb_error());
762 return 1;
763 }
764
765 pid = fork();
766
767 if (pid < 0) {
768 perror("from fork()");
769 return 1;
770 } else if (pid == 0) {
771 int err;
772 int i;
773 const char **ppp_args;
774
775 // copy args
776 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
777 ppp_args[0] = "pppd";
778 for (i = 2 ; i < argc ; i++) {
779 //argv[2] and beyond become ppp_args[1] and beyond
780 ppp_args[i - 1] = argv[i];
781 }
782 ppp_args[i-1] = NULL;
783
784 // child side
785
786 dup2(fd, STDIN_FILENO);
787 dup2(fd, STDOUT_FILENO);
788 adb_close(STDERR_FILENO);
789 adb_close(fd);
790
791 err = execvp("pppd", (char * const *)ppp_args);
792
793 if (err < 0) {
794 perror("execing pppd");
795 }
796 exit(-1);
797 } else {
798 // parent side
799
800 adb_close(fd);
801 return 0;
802 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800803#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800804}
805
Dan Albertbac34742015-02-25 17:51:28 -0800806static int send_shellcommand(transport_type transport, const char* serial,
807 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800808{
809 int fd, ret;
810
811 for(;;) {
812 fd = adb_connect(buf);
813 if(fd >= 0)
814 break;
815 fprintf(stderr,"- waiting for device -\n");
816 adb_sleep_ms(1000);
817 do_cmd(transport, serial, "wait-for-device", 0);
818 }
819
820 read_and_dump(fd);
821 ret = adb_close(fd);
822 if (ret)
823 perror("close");
824
825 return ret;
826}
827
Dan Albertbac34742015-02-25 17:51:28 -0800828static int logcat(transport_type transport, const char* serial, int argc,
829 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800830{
831 char buf[4096];
832
833 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700834 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835
836 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700837 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800838 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700839 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700840 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700842 if (!strcmp(argv[0], "longcat")) {
843 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800844 }
845
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 argc -= 1;
847 argv += 1;
848 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700849 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700850 strncat(buf, " ", sizeof(buf) - 1);
851 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800852 free(quoted);
853 }
854
855 send_shellcommand(transport, serial, buf);
856 return 0;
857}
858
Mark Salyzyn60299df2014-04-30 09:10:31 -0700859static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800860{
861 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700862 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800863
864 for(;;) {
865 x = adb_dirstart(x);
866 if(x == 0) return 0;
867 *x = 0;
868 ret = adb_mkdir(path, 0775);
869 *x = OS_PATH_SEPARATOR;
870 if((ret < 0) && (errno != EEXIST)) {
871 return ret;
872 }
873 x++;
874 }
875 return 0;
876}
877
Dan Albertbac34742015-02-25 17:51:28 -0800878static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700879 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800880 char default_name[32];
881 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700882 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700883 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700884
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700885 /* find, extract, and use any -f argument */
886 for (i = 1; i < argc; i++) {
887 if (!strcmp("-f", argv[i])) {
888 if (i == argc-1) {
889 fprintf(stderr, "adb: -f passed with no filename\n");
890 return usage();
891 }
892 filename = argv[i+1];
893 for (j = i+2; j <= argc; ) {
894 argv[i++] = argv[j++];
895 }
896 argc -= 2;
897 argv[argc] = NULL;
898 }
Christopher Tated2f54152011-04-21 12:53:28 -0700899 }
900
Christopher Tatebb86bc52011-08-22 17:12:08 -0700901 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
902 if (argc < 2) return usage();
903
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800904 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700905 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800906 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700907 if (outFd < 0) {
908 fprintf(stderr, "adb: unable to open file %s\n", filename);
909 return -1;
910 }
911
912 snprintf(buf, sizeof(buf), "backup");
913 for (argc--, argv++; argc; argc--, argv++) {
914 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
915 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
916 }
917
918 D("backup. filename=%s buf=%s\n", filename, buf);
919 fd = adb_connect(buf);
920 if (fd < 0) {
921 fprintf(stderr, "adb: unable to connect for backup\n");
922 adb_close(outFd);
923 return -1;
924 }
925
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800926 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700927 copy_to_file(fd, outFd);
928
929 adb_close(fd);
930 adb_close(outFd);
931 return 0;
932}
933
Dan Albertbac34742015-02-25 17:51:28 -0800934static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700935 const char* filename;
936 int fd, tarFd;
937
938 if (argc != 2) return usage();
939
940 filename = argv[1];
941 tarFd = adb_open(filename, O_RDONLY);
942 if (tarFd < 0) {
943 fprintf(stderr, "adb: unable to open file %s\n", filename);
944 return -1;
945 }
946
947 fd = adb_connect("restore:");
948 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700949 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700950 adb_close(tarFd);
951 return -1;
952 }
953
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800954 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700955 copy_to_file(tarFd, fd);
956
957 adb_close(fd);
958 adb_close(tarFd);
959 return 0;
960}
961
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800962#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
963static int top_works(const char *top)
964{
965 if (top != NULL && adb_is_absolute_host_path(top)) {
966 char path_buf[PATH_MAX];
967 snprintf(path_buf, sizeof(path_buf),
968 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
969 return access(path_buf, F_OK) == 0;
970 }
971 return 0;
972}
973
974static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
975{
976 strcpy(path_buf, indir);
977 while (1) {
978 if (top_works(path_buf)) {
979 return path_buf;
980 }
981 char *s = adb_dirstop(path_buf);
982 if (s != NULL) {
983 *s = '\0';
984 } else {
985 path_buf[0] = '\0';
986 return NULL;
987 }
988 }
989}
990
991static char *find_top(char path_buf[PATH_MAX])
992{
993 char *top = getenv("ANDROID_BUILD_TOP");
994 if (top != NULL && top[0] != '\0') {
995 if (!top_works(top)) {
996 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
997 return NULL;
998 }
999 } else {
1000 top = getenv("TOP");
1001 if (top != NULL && top[0] != '\0') {
1002 if (!top_works(top)) {
1003 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1004 return NULL;
1005 }
1006 } else {
1007 top = NULL;
1008 }
1009 }
1010
1011 if (top != NULL) {
1012 /* The environment pointed to a top directory that works.
1013 */
1014 strcpy(path_buf, top);
1015 return path_buf;
1016 }
1017
1018 /* The environment didn't help. Walk up the tree from the CWD
1019 * to see if we can find the top.
1020 */
1021 char dir[PATH_MAX];
1022 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1023 if (top == NULL) {
1024 /* If the CWD isn't under a good-looking top, see if the
1025 * executable is.
1026 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001027 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 top = find_top_from(dir, path_buf);
1029 }
1030 return top;
1031}
1032
1033/* <hint> may be:
1034 * - A simple product name
1035 * e.g., "sooner"
1036TODO: debug? sooner-debug, sooner:debug?
1037 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1038 * e.g., "out/target/product/sooner"
1039 * - An absolute path to the PRODUCT_OUT dir
1040 * e.g., "/src/device/out/target/product/sooner"
1041 *
1042 * Given <hint>, try to construct an absolute path to the
1043 * ANDROID_PRODUCT_OUT dir.
1044 */
1045static const char *find_product_out_path(const char *hint)
1046{
1047 static char path_buf[PATH_MAX];
1048
1049 if (hint == NULL || hint[0] == '\0') {
1050 return NULL;
1051 }
1052
1053 /* If it's already absolute, don't bother doing any work.
1054 */
1055 if (adb_is_absolute_host_path(hint)) {
1056 strcpy(path_buf, hint);
1057 return path_buf;
1058 }
1059
1060 /* If there are any slashes in it, assume it's a relative path;
1061 * make it absolute.
1062 */
1063 if (adb_dirstart(hint) != NULL) {
1064 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1065 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1066 return NULL;
1067 }
1068 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1069 fprintf(stderr, "adb: Couldn't assemble path\n");
1070 return NULL;
1071 }
1072 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1073 strcat(path_buf, hint);
1074 return path_buf;
1075 }
1076
1077 /* It's a string without any slashes. Try to do something with it.
1078 *
1079 * Try to find the root of the build tree, and build a PRODUCT_OUT
1080 * path from there.
1081 */
1082 char top_buf[PATH_MAX];
1083 const char *top = find_top(top_buf);
1084 if (top == NULL) {
1085 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1086 return NULL;
1087 }
1088//TODO: if we have a way to indicate debug, look in out/debug/target/...
1089 snprintf(path_buf, sizeof(path_buf),
1090 "%s" OS_PATH_SEPARATOR_STR
1091 "out" OS_PATH_SEPARATOR_STR
1092 "target" OS_PATH_SEPARATOR_STR
1093 "product" OS_PATH_SEPARATOR_STR
1094 "%s", top_buf, hint);
1095 if (access(path_buf, F_OK) < 0) {
1096 fprintf(stderr, "adb: Couldn't find a product dir "
1097 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1098 return NULL;
1099 }
1100 return path_buf;
1101}
1102
Dan Albertbac34742015-02-25 17:51:28 -08001103static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1104 char const **path2, int *show_progress,
1105 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001106 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001107 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001108
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001109 while (narg > 0) {
1110 if (!strcmp(*arg, "-p")) {
1111 *show_progress = 1;
1112 } else if (!strcmp(*arg, "-a")) {
1113 *copy_attrs = 1;
1114 } else {
1115 break;
1116 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001117 ++arg;
1118 --narg;
1119 }
1120
1121 if (narg > 0) {
1122 *path1 = *arg;
1123 ++arg;
1124 --narg;
1125 }
1126
1127 if (narg > 0) {
1128 *path2 = *arg;
1129 }
1130}
1131
Dan Albertbac34742015-02-25 17:51:28 -08001132int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133{
1134 char buf[4096];
1135 int no_daemon = 0;
1136 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001137 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001138 int persist = 0;
1139 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001140 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001141 const char* serial = NULL;
1142 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001143
1144 /* If defined, this should be an absolute path to
1145 * the directory containing all of the various system images
1146 * for a particular product. If not defined, and the adb
1147 * command requires this information, then the user must
1148 * specify the path using "-p".
1149 */
1150 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1151 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1152 gProductOutPath = NULL;
1153 }
1154 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1155
Nick Pellydb449262009-05-07 12:48:03 -07001156 serial = getenv("ANDROID_SERIAL");
1157
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001158 /* Validate and assign the server port */
1159 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1160 int server_port = DEFAULT_ADB_PORT;
1161 if (server_port_str && strlen(server_port_str) > 0) {
1162 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001163 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001164 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001165 "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 +01001166 server_port_str);
1167 return usage();
1168 }
1169 }
1170
1171 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001172 while (argc > 0) {
1173 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001174 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001175 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001176 no_daemon = 1;
1177 } else if (!strcmp(argv[0], "fork-server")) {
1178 /* this is a special flag used only when the ADB client launches the ADB Server */
1179 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001180 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001181 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001182 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001183 const char *product = NULL;
1184 if (argv[0][2] == '\0') {
1185 if (argc < 2) return usage();
1186 product = argv[1];
1187 argc--;
1188 argv++;
1189 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001190 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191 }
1192 gProductOutPath = find_product_out_path(product);
1193 if (gProductOutPath == NULL) {
1194 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1195 product);
1196 return usage();
1197 }
1198 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1199 if (isdigit(argv[0][2])) {
1200 serial = argv[0] + 2;
1201 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001202 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001203 serial = argv[1];
1204 argc--;
1205 argv++;
1206 }
1207 } else if (!strcmp(argv[0],"-d")) {
1208 ttype = kTransportUsb;
1209 } else if (!strcmp(argv[0],"-e")) {
1210 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001211 } else if (!strcmp(argv[0],"-a")) {
1212 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001213 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001214 const char *hostname = NULL;
1215 if (argv[0][2] == '\0') {
1216 if (argc < 2) return usage();
1217 hostname = argv[1];
1218 argc--;
1219 argv++;
1220 } else {
1221 hostname = argv[0] + 2;
1222 }
1223 adb_set_tcp_name(hostname);
1224
Riley Andrews98f58e82014-12-05 17:37:24 -08001225 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001226 if (argv[0][2] == '\0') {
1227 if (argc < 2) return usage();
1228 server_port_str = argv[1];
1229 argc--;
1230 argv++;
1231 } else {
1232 server_port_str = argv[0] + 2;
1233 }
1234 if (strlen(server_port_str) > 0) {
1235 server_port = (int) strtol(server_port_str, NULL, 0);
1236 if (server_port <= 0 || server_port > 65535) {
1237 fprintf(stderr,
1238 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1239 server_port_str);
1240 return usage();
1241 }
1242 } else {
1243 fprintf(stderr,
1244 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1245 return usage();
1246 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001247 } else {
1248 /* out of recognized modifiers and flags */
1249 break;
1250 }
1251 argc--;
1252 argv++;
1253 }
1254
1255 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001256 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001257
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001258 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001259 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001260 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001261 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001262 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001264 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001265 fprintf(stderr,"* could not start server *\n");
1266 }
1267 return r;
1268 }
1269
Riley Andrews98f58e82014-12-05 17:37:24 -08001270 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001271 return usage();
1272 }
1273
Riley Andrewsc8514c82014-12-05 17:32:46 -08001274 /* handle wait-for-* prefix */
1275 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001276 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001277 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1278 if (ttype == kTransportUsb) {
1279 service = "wait-for-usb";
1280 } else if (ttype == kTransportLocal) {
1281 service = "wait-for-local";
1282 } else {
1283 service = "wait-for-any";
1284 }
1285 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001286
Riley Andrewsc8514c82014-12-05 17:32:46 -08001287 format_host_command(buf, sizeof buf, service, ttype, serial);
1288
1289 if (adb_command(buf)) {
1290 D("failure: %s *\n",adb_error());
1291 fprintf(stderr,"error: %s\n", adb_error());
1292 return 1;
1293 }
1294
1295 /* Allow a command to be run after wait-for-device,
1296 * e.g. 'adb wait-for-device shell'.
1297 */
1298 if (argc == 1) {
1299 return 0;
1300 }
1301
1302 /* Fall through */
1303 argc--;
1304 argv++;
1305 }
1306
1307 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001308 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001309 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001310 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001311 if (argc < 2)
1312 listopt = "";
1313 else if (argc == 2 && !strcmp(argv[1], "-l"))
1314 listopt = argv[1];
1315 else {
1316 fprintf(stderr, "Usage: adb devices [-l]\n");
1317 return 1;
1318 }
1319 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001321 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001322 printf("List of devices attached \n");
1323 printf("%s\n", tmp);
1324 return 0;
1325 } else {
1326 return 1;
1327 }
1328 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001329 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001330 char *tmp;
1331 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001332 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001333 return 1;
1334 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001335 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1336 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001337 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001338 printf("%s\n", tmp);
1339 return 0;
1340 } else {
1341 return 1;
1342 }
1343 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001344 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001345 char *tmp;
1346 if (argc > 2) {
1347 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1348 return 1;
1349 }
1350 if (argc == 2) {
1351 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1352 } else {
1353 snprintf(buf, sizeof buf, "host:disconnect:");
1354 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001355 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001356 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001357 printf("%s\n", tmp);
1358 return 0;
1359 } else {
1360 return 1;
1361 }
1362 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001363 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 return adb_send_emulator_command(argc, argv);
1365 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001366 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001367 int r;
1368 int fd;
1369
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001370 char h = (argv[0][0] == 'h');
1371
1372 if (h) {
1373 printf("\x1b[41;33m");
1374 fflush(stdout);
1375 }
1376
Riley Andrews98f58e82014-12-05 17:37:24 -08001377 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001378 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001379 r = interactive_shell();
1380 if (h) {
1381 printf("\x1b[0m");
1382 fflush(stdout);
1383 }
1384 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385 }
1386
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001387 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001388 argc -= 2;
1389 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001390 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001391 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001392 strncat(buf, " ", sizeof(buf) - 1);
1393 strncat(buf, quoted, sizeof(buf) - 1);
1394 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001395 }
1396
1397 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001398 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001399 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001400 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001401 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001403 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001404 adb_close(fd);
1405 r = 0;
1406 } else {
1407 fprintf(stderr,"error: %s\n", adb_error());
1408 r = -1;
1409 }
1410
Riley Andrews98f58e82014-12-05 17:37:24 -08001411 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001412 fprintf(stderr,"\n- waiting for device -\n");
1413 adb_sleep_ms(1000);
1414 do_cmd(ttype, serial, "wait-for-device", 0);
1415 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001416 if (h) {
1417 printf("\x1b[0m");
1418 fflush(stdout);
1419 }
JP Abgrall408fa572011-03-16 15:57:42 -07001420 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001421 return r;
1422 }
1423 }
1424 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001425 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001426 int exec_in = !strcmp(argv[0], "exec-in");
1427 int fd;
1428
1429 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1430 argc -= 2;
1431 argv += 2;
1432 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001433 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001434 strncat(buf, " ", sizeof(buf) - 1);
1435 strncat(buf, quoted, sizeof(buf) - 1);
1436 free(quoted);
1437 }
1438
1439 fd = adb_connect(buf);
1440 if (fd < 0) {
1441 fprintf(stderr, "error: %s\n", adb_error());
1442 return -1;
1443 }
1444
1445 if (exec_in) {
1446 copy_to_file(STDIN_FILENO, fd);
1447 } else {
1448 copy_to_file(fd, STDOUT_FILENO);
1449 }
1450
1451 adb_close(fd);
1452 return 0;
1453 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001454 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001455 int fd;
1456 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001457 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001458 fprintf(stderr,"* server not running *\n");
1459 return 1;
1460 }
1461 return 0;
1462 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001463 else if (!strcmp(argv[0], "sideload")) {
1464 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001465 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001466 return 1;
1467 } else {
1468 return 0;
1469 }
1470 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001471 else if (!strcmp(argv[0], "remount") ||
1472 !strcmp(argv[0], "reboot") ||
1473 !strcmp(argv[0], "reboot-bootloader") ||
1474 !strcmp(argv[0], "tcpip") ||
1475 !strcmp(argv[0], "usb") ||
1476 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001477 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001478 !strcmp(argv[0], "disable-verity") ||
1479 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001480 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001481 if (!strcmp(argv[0], "reboot-bootloader"))
1482 snprintf(command, sizeof(command), "reboot:bootloader");
1483 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001484 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001485 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001486 snprintf(command, sizeof(command), "%s:", argv[0]);
1487 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001488 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001489 read_and_dump(fd);
1490 adb_close(fd);
1491 return 0;
1492 }
1493 fprintf(stderr,"error: %s\n", adb_error());
1494 return 1;
1495 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001496 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001497 if (argc != 1) return usage();
1498 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001499 return 0;
1500 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001501 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001502 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001503 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001504 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001505 char remove = 0;
1506 char remove_all = 0;
1507 char list = 0;
1508 char no_rebind = 0;
1509
1510 // Parse options here.
1511 while (argc > 1 && argv[1][0] == '-') {
1512 if (!strcmp(argv[1], "--list"))
1513 list = 1;
1514 else if (!strcmp(argv[1], "--remove"))
1515 remove = 1;
1516 else if (!strcmp(argv[1], "--remove-all"))
1517 remove_all = 1;
1518 else if (!strcmp(argv[1], "--no-rebind"))
1519 no_rebind = 1;
1520 else {
1521 return usage();
1522 }
1523 argc--;
1524 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001526
1527 // Ensure we can only use one option at a time.
1528 if (list + remove + remove_all + no_rebind > 1) {
1529 return usage();
1530 }
1531
1532 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001533 if (reverse) {
1534 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001535 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001536 if (serial) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1538 serial);
1539 } else if (ttype == kTransportUsb) {
1540 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1541 } else if (ttype == kTransportLocal) {
1542 snprintf(host_prefix, sizeof host_prefix, "host-local");
1543 } else {
1544 snprintf(host_prefix, sizeof host_prefix, "host");
1545 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001546 }
1547
1548 // Implement forward --list
1549 if (list) {
1550 if (argc != 1)
1551 return usage();
1552 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1553 char* forwards = adb_query(buf);
1554 if (forwards == NULL) {
1555 fprintf(stderr, "error: %s\n", adb_error());
1556 return 1;
1557 }
1558 printf("%s", forwards);
1559 free(forwards);
1560 return 0;
1561 }
1562
1563 // Implement forward --remove-all
1564 else if (remove_all) {
1565 if (argc != 1)
1566 return usage();
1567 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1568 }
1569
1570 // Implement forward --remove <local>
1571 else if (remove) {
1572 if (argc != 2)
1573 return usage();
1574 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1575 }
1576 // Or implement one of:
1577 // forward <local> <remote>
1578 // forward --no-rebind <local> <remote>
1579 else
1580 {
1581 if (argc != 3)
1582 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001583 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001584 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1585 }
1586
Riley Andrews98f58e82014-12-05 17:37:24 -08001587 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001588 fprintf(stderr,"error: %s\n", adb_error());
1589 return 1;
1590 }
1591 return 0;
1592 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001593 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001594 else if (!strcmp(argv[0], "ls")) {
1595 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001596 return do_sync_ls(argv[1]);
1597 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001598 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001599 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001600 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001601 const char* lpath = NULL, *rpath = NULL;
1602
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001603 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001604
1605 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001606 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001607 }
1608
1609 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001610 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001611 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001612 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001613 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001614 const char* rpath = NULL, *lpath = ".";
1615
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001616 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001617
1618 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001619 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001620 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001621
1622 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001624 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 if (argc < 2) return usage();
1626 return install_app(ttype, serial, argc, argv);
1627 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001628 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001629 if (argc < 2) return usage();
1630 return install_multiple_app(ttype, serial, argc, argv);
1631 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001632 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 if (argc < 2) return usage();
1634 return uninstall_app(ttype, serial, argc, argv);
1635 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001636 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001637 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001638 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1639
Anthony Newnam705c9442010-02-22 08:36:49 -06001640 int listonly = 0;
1641
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001642 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001643 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001644 /* No local path was specified. */
1645 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001646 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1647 listonly = 1;
1648 if (argc == 3) {
1649 srcarg = argv[2];
1650 } else {
1651 srcarg = NULL;
1652 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001653 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001654 /* A local path or "android"/"data" arg was specified. */
1655 srcarg = argv[1];
1656 } else {
1657 return usage();
1658 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001659 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1660 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001661 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001662
Elliott Hughesec7a6672015-03-16 21:58:32 +00001663 if (system_srcpath != NULL)
1664 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001665 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001666 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001667 if(ret == 0 && oem_srcpath != NULL)
1668 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001669 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001670 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001671
Elliott Hughesec7a6672015-03-16 21:58:32 +00001672 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001673 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001674 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001675 free(data_srcpath);
1676 return ret;
1677 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001678 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001679 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001680 !strcmp(argv[0],"get-serialno") ||
1681 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 {
1683 char *tmp;
1684
1685 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1686 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001687 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 printf("%s\n", tmp);
1689 return 0;
1690 } else {
1691 return 1;
1692 }
1693 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001694 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001696 status_window(ttype, serial);
1697 return 0;
1698 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001699 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001700 return logcat(ttype, serial, argc, argv);
1701 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001703 return ppp(argc, argv);
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001706 return adb_connect("host:start-server");
1707 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001709 return backup(argc, argv);
1710 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001712 return restore(argc, argv);
1713 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001714 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001715 if (argc < 2) return usage();
1716 return adb_auth_keygen(argv[1]);
1717 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001718 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001719 int fd = adb_connect("jdwp");
1720 if (fd >= 0) {
1721 read_and_dump(fd);
1722 adb_close(fd);
1723 return 0;
1724 } else {
1725 fprintf(stderr, "error: %s\n", adb_error());
1726 return -1;
1727 }
1728 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001729 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001730 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001731 help();
1732 return 0;
1733 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001734 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001735 version(stdout);
1736 return 0;
1737 }
1738
1739 usage();
1740 return 1;
1741}
1742
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001743#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001744static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001745{
Dan Albertbac34742015-02-25 17:51:28 -08001746 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001747 int argc;
1748 va_list ap;
1749
1750 va_start(ap, cmd);
1751 argc = 0;
1752
1753 if (serial) {
1754 argv[argc++] = "-s";
1755 argv[argc++] = serial;
1756 } else if (ttype == kTransportUsb) {
1757 argv[argc++] = "-d";
1758 } else if (ttype == kTransportLocal) {
1759 argv[argc++] = "-e";
1760 }
1761
1762 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001763 while(argc < MAX_ARGV_LENGTH &&
1764 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1765 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001766 va_end(ap);
1767
1768#if 0
1769 int n;
1770 fprintf(stderr,"argc = %d\n",argc);
1771 for(n = 0; n < argc; n++) {
1772 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1773 }
1774#endif
1775
1776 return adb_commandline(argc, argv);
1777}
1778
1779int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001780 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1781 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001782{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001783 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001784 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001785
1786 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001787 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001788 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001789 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001790 oem_srcdir = product_file("oem");
1791 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001792 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1793 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001794 // Check if oem partition exists.
1795 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1796 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001797 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001798 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1799 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001800 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001801 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001803 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001804 } else if(strcmp(srcarg, "vendor") == 0) {
1805 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001806 } else if(strcmp(srcarg, "oem") == 0) {
1807 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001808 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001809 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001810 return 1;
1811 }
1812 }
1813
Elliott Hughesec7a6672015-03-16 21:58:32 +00001814 if(system_srcdir_out != NULL)
1815 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001816 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001817 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001818
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001819 if(vendor_srcdir_out != NULL)
1820 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001821 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001822 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001823
Elliott Hughesec7a6672015-03-16 21:58:32 +00001824 if(oem_srcdir_out != NULL)
1825 *oem_srcdir_out = oem_srcdir;
1826 else
1827 free(oem_srcdir);
1828
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001829 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001830 *data_srcdir_out = data_srcdir;
1831 else
1832 free(data_srcdir);
1833
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001834 return 0;
1835}
1836
Dan Albertbac34742015-02-25 17:51:28 -08001837static int pm_command(transport_type transport, const char* serial,
1838 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001839{
1840 char buf[4096];
1841
1842 snprintf(buf, sizeof(buf), "shell:pm");
1843
1844 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001845 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001846 strncat(buf, " ", sizeof(buf) - 1);
1847 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001848 free(quoted);
1849 }
1850
1851 send_shellcommand(transport, serial, buf);
1852 return 0;
1853}
1854
Dan Albertbac34742015-02-25 17:51:28 -08001855int uninstall_app(transport_type transport, const char* serial, int argc,
1856 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001857{
1858 /* if the user choose the -k option, we refuse to do it until devices are
1859 out with the option to uninstall the remaining data somehow (adb/ui) */
1860 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1861 {
1862 printf(
1863 "The -k option uninstalls the application while retaining the data/cache.\n"
1864 "At the moment, there is no way to remove the remaining data.\n"
1865 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1866 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1867 return -1;
1868 }
1869
1870 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1871 return pm_command(transport, serial, argc, argv);
1872}
1873
Dan Albertbac34742015-02-25 17:51:28 -08001874static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001875{
1876 char buf[4096];
1877 char* quoted;
1878
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001879 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001880 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001881 strncat(buf, quoted, sizeof(buf)-1);
1882 free(quoted);
1883
1884 send_shellcommand(transport, serial, buf);
1885 return 0;
1886}
1887
Kenny Root597ea5b2011-08-05 11:19:45 -07001888static const char* get_basename(const char* filename)
1889{
1890 const char* basename = adb_dirstop(filename);
1891 if (basename) {
1892 basename++;
1893 return basename;
1894 } else {
1895 return filename;
1896 }
1897}
1898
Dan Albertbac34742015-02-25 17:51:28 -08001899int install_app(transport_type transport, const char* serial, int argc,
1900 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001901{
1902 static const char *const DATA_DEST = "/data/local/tmp/%s";
1903 static const char *const SD_DEST = "/sdcard/tmp/%s";
1904 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001905 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001906 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001907
1908 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001909 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001910 where = SD_DEST;
1911 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001912 }
1913
Jeff Sharkey960df972014-06-09 17:30:57 -07001914 // Find last APK argument.
1915 // All other arguments passed through verbatim.
1916 int last_apk = -1;
1917 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001918 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001919 char* dot = strrchr(file, '.');
1920 if (dot && !strcasecmp(dot, ".apk")) {
1921 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1922 fprintf(stderr, "Invalid APK file: %s\n", file);
1923 return -1;
1924 }
1925
1926 last_apk = i;
1927 break;
1928 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001929 }
1930
Jeff Sharkey960df972014-06-09 17:30:57 -07001931 if (last_apk == -1) {
1932 fprintf(stderr, "Missing APK file\n");
1933 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001934 }
1935
Dan Albertbac34742015-02-25 17:51:28 -08001936 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001937 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001938 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001939 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001940 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001941 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001942 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001943 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001944 }
1945
1946 pm_command(transport, serial, argc, argv);
1947
Kenny Root60733e92012-03-26 16:14:02 -07001948cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001949 delete_file(transport, serial, apk_dest);
1950 return err;
1951}
1952
Dan Albertbac34742015-02-25 17:51:28 -08001953int install_multiple_app(transport_type transport, const char* serial, int argc,
1954 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001955{
1956 char buf[1024];
1957 int i;
1958 struct stat sb;
1959 unsigned long long total_size = 0;
1960
1961 // Find all APK arguments starting at end.
1962 // All other arguments passed through verbatim.
1963 int first_apk = -1;
1964 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001965 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001966 char* dot = strrchr(file, '.');
1967 if (dot && !strcasecmp(dot, ".apk")) {
1968 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1969 fprintf(stderr, "Invalid APK file: %s\n", file);
1970 return -1;
1971 }
1972
1973 total_size += sb.st_size;
1974 first_apk = i;
1975 } else {
1976 break;
1977 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001978 }
1979
Jeff Sharkey960df972014-06-09 17:30:57 -07001980 if (first_apk == -1) {
1981 fprintf(stderr, "Missing APK file\n");
1982 return 1;
1983 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001984
Jeff Sharkey960df972014-06-09 17:30:57 -07001985 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1986 for (i = 1; i < first_apk; i++) {
1987 char *quoted = escape_arg(argv[i]);
1988 strncat(buf, " ", sizeof(buf) - 1);
1989 strncat(buf, quoted, sizeof(buf) - 1);
1990 free(quoted);
1991 }
1992
1993 // Create install session
1994 int fd = adb_connect(buf);
1995 if (fd < 0) {
1996 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1997 return -1;
1998 }
1999 read_status_line(fd, buf, sizeof(buf));
2000 adb_close(fd);
2001
2002 int session_id = -1;
2003 if (!strncmp("Success", buf, 7)) {
2004 char* start = strrchr(buf, '[');
2005 char* end = strrchr(buf, ']');
2006 if (start && end) {
2007 *end = '\0';
2008 session_id = strtol(start + 1, NULL, 10);
2009 }
2010 }
2011 if (session_id < 0) {
2012 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002013 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002014 return -1;
2015 }
2016
2017 // Valid session, now stream the APKs
2018 int success = 1;
2019 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002020 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002021 if (stat(file, &sb) == -1) {
2022 fprintf(stderr, "Failed to stat %s\n", file);
2023 success = 0;
2024 goto finalize_session;
2025 }
2026
2027 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002028 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002029
2030 int localFd = adb_open(file, O_RDONLY);
2031 if (localFd < 0) {
2032 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2033 success = 0;
2034 goto finalize_session;
2035 }
2036
2037 int remoteFd = adb_connect(buf);
2038 if (remoteFd < 0) {
2039 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2040 adb_close(localFd);
2041 success = 0;
2042 goto finalize_session;
2043 }
2044
2045 copy_to_file(localFd, remoteFd);
2046 read_status_line(remoteFd, buf, sizeof(buf));
2047
2048 adb_close(localFd);
2049 adb_close(remoteFd);
2050
2051 if (strncmp("Success", buf, 7)) {
2052 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002053 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002054 success = 0;
2055 goto finalize_session;
2056 }
2057 }
2058
2059finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002060 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002061 if (success) {
2062 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2063 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002064 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002065 }
2066
2067 fd = adb_connect(buf);
2068 if (fd < 0) {
2069 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2070 return -1;
2071 }
2072 read_status_line(fd, buf, sizeof(buf));
2073 adb_close(fd);
2074
2075 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002076 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002077 return 0;
2078 } else {
2079 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002080 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002081 return -1;
2082 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002083}