blob: f9ca5edb0696540efc2b63e386512c66059e3423 [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"
Tao Bao175b7bb2015-03-29 11:22:34 -0700212 " adb reboot [bootloader|recovery]\n"
213 " - reboots the device, optionally into the bootloader or recovery program.\n"
214 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
215 " adb reboot sideload-auto-reboot\n"
216 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800217 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700218 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500219 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800220 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000221 " 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 -0800222 "networking:\n"
223 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500224 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800225 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
226 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
227 "\n"
228 "adb sync notes: adb sync [ <directory> ]\n"
229 " <localdir> can be interpreted in several ways:\n"
230 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000231 " - 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 -0800232 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000233 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000235 "\n"
236 "environmental variables:\n"
237 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
238 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
239 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
240 " 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 -0800241 );
242}
243
244int usage()
245{
246 help();
247 return 1;
248}
249
Yabin Cuid325e862014-11-17 14:48:25 -0800250#if defined(_WIN32)
251
Spencer Low50184062015-03-01 15:06:21 -0800252// Implemented in sysdeps_win32.c.
253extern "C" {
254void stdin_raw_init(int fd);
255void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800256}
257
258#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259static struct termios tio_save;
260
261static void stdin_raw_init(int fd)
262{
263 struct termios tio;
264
265 if(tcgetattr(fd, &tio)) return;
266 if(tcgetattr(fd, &tio_save)) return;
267
268 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
269
270 /* no timeout but request at least one character per read */
271 tio.c_cc[VTIME] = 0;
272 tio.c_cc[VMIN] = 1;
273
274 tcsetattr(fd, TCSANOW, &tio);
275 tcflush(fd, TCIFLUSH);
276}
277
278static void stdin_raw_restore(int fd)
279{
280 tcsetattr(fd, TCSANOW, &tio_save);
281 tcflush(fd, TCIFLUSH);
282}
283#endif
284
285static void read_and_dump(int fd)
286{
287 char buf[4096];
288 int len;
289
290 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700291 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700293 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800294 if(len == 0) {
295 break;
296 }
297
298 if(len < 0) {
299 if(errno == EINTR) continue;
300 break;
301 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400302 fwrite(buf, 1, len, stdout);
303 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800304 }
305}
306
Jeff Sharkey960df972014-06-09 17:30:57 -0700307static void read_status_line(int fd, char* buf, size_t count)
308{
309 count--;
310 while (count > 0) {
311 int len = adb_read(fd, buf, count);
312 if (len == 0) {
313 break;
314 } else if (len < 0) {
315 if (errno == EINTR) continue;
316 break;
317 }
318
319 buf += len;
320 count -= len;
321 }
322 *buf = '\0';
323}
324
Christopher Tated2f54152011-04-21 12:53:28 -0700325static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700326 const size_t BUFSIZE = 32 * 1024;
327 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700328 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700329 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700330
331 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800332
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700333 if (inFd == STDIN_FILENO) {
334 stdin_raw_init(STDIN_FILENO);
335 }
Yabin Cuid325e862014-11-17 14:48:25 -0800336
Christopher Tated2f54152011-04-21 12:53:28 -0700337 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700338 if (inFd == STDIN_FILENO) {
339 len = unix_read(inFd, buf, BUFSIZE);
340 } else {
341 len = adb_read(inFd, buf, BUFSIZE);
342 }
Christopher Tated2f54152011-04-21 12:53:28 -0700343 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700344 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700345 break;
346 }
347 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700348 if (errno == EINTR) {
349 D("copy_to_file() : EINTR, retrying\n");
350 continue;
351 }
Christopher Tated2f54152011-04-21 12:53:28 -0700352 D("copy_to_file() : error %d\n", errno);
353 break;
354 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700355 if (outFd == STDOUT_FILENO) {
356 fwrite(buf, 1, len, stdout);
357 fflush(stdout);
358 } else {
359 adb_write(outFd, buf, len);
360 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700361 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700362 }
Yabin Cuid325e862014-11-17 14:48:25 -0800363
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700364 if (inFd == STDIN_FILENO) {
365 stdin_raw_restore(STDIN_FILENO);
366 }
Yabin Cuid325e862014-11-17 14:48:25 -0800367
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700368 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700369 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700370}
371
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372static void *stdin_read_thread(void *x)
373{
374 int fd, fdi;
375 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800376 int r, n;
377 int state = 0;
378
379 int *fds = (int*) x;
380 fd = fds[0];
381 fdi = fds[1];
382 free(fds);
383
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800384 for(;;) {
385 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700386 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800387 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700388 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800389 if(r == 0) break;
390 if(r < 0) {
391 if(errno == EINTR) continue;
392 break;
393 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400394 for(n = 0; n < r; n++){
395 switch(buf[n]) {
396 case '\n':
397 state = 1;
398 break;
399 case '\r':
400 state = 1;
401 break;
402 case '~':
403 if(state == 1) state++;
404 break;
405 case '.':
406 if(state == 2) {
407 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400408 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400409 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400411 default:
412 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800415 r = adb_write(fd, buf, r);
416 if(r <= 0) {
417 break;
418 }
419 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800420 return 0;
421}
422
423int interactive_shell(void)
424{
425 adb_thread_t thr;
426 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800427
428 fd = adb_connect("shell:");
429 if(fd < 0) {
430 fprintf(stderr,"error: %s\n", adb_error());
431 return 1;
432 }
433 fdi = 0; //dup(0);
434
Dan Albertbac34742015-02-25 17:51:28 -0800435 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 fds[0] = fd;
437 fds[1] = fdi;
438
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 adb_thread_create(&thr, stdin_read_thread, fds);
441 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800442 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800443 return 0;
444}
445
446
447static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
448{
449 if (serial) {
450 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
451 } else {
452 const char* prefix = "host";
453 if (ttype == kTransportUsb)
454 prefix = "host-usb";
455 else if (ttype == kTransportLocal)
456 prefix = "host-local";
457
458 snprintf(buffer, buflen, "%s:%s", prefix, command);
459 }
460}
461
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100462int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800463 unsigned progress)
464{
465 char buf[4096];
466 unsigned total;
467 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800468
469 sprintf(buf,"%s:%d", service, sz);
470 fd = adb_connect(buf);
471 if(fd < 0) {
472 fprintf(stderr,"error: %s\n", adb_error());
473 return -1;
474 }
475
476 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800477 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800478
479 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800480 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800481
482 if(progress) {
483 char *x = strrchr(service, ':');
484 if(x) service = x + 1;
485 }
486
487 while(sz > 0) {
488 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800489 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800490 adb_status(fd);
491 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
492 return -1;
493 }
494 sz -= xfer;
495 ptr += xfer;
496 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100497 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800498 fflush(stdout);
499 }
500 }
501 if(progress) {
502 printf("\n");
503 }
504
Dan Albertcc731cc2015-02-24 21:26:58 -0800505 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800506 fprintf(stderr,"* error reading response *\n");
507 adb_close(fd);
508 return -1;
509 }
510 if(memcmp(buf, "OKAY", 4)) {
511 buf[4] = 0;
512 fprintf(stderr,"* error response '%s' *\n", buf);
513 adb_close(fd);
514 return -1;
515 }
516
517 adb_close(fd);
518 return 0;
519}
520
521
522int adb_download(const char *service, const char *fn, unsigned progress)
523{
524 void *data;
525 unsigned sz;
526
527 data = load_file(fn, &sz);
528 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100529 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800530 return -1;
531 }
532
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100533 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800534 free(data);
535 return status;
536}
537
Doug Zongker71fe5842014-06-26 15:35:36 -0700538#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
539
540/*
541 * The sideload-host protocol serves the data in a file (given on the
542 * command line) to the client, using a simple protocol:
543 *
544 * - The connect message includes the total number of bytes in the
545 * file and a block size chosen by us.
546 *
547 * - The other side sends the desired block number as eight decimal
548 * digits (eg "00000023" for block 23). Blocks are numbered from
549 * zero.
550 *
551 * - We send back the data of the requested block. The last block is
552 * likely to be partial; when the last block is requested we only
553 * send the part of the block that exists, it's not padded up to the
554 * block size.
555 *
556 * - When the other side sends "DONEDONE" instead of a block number,
557 * we hang up.
558 */
559int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700560 unsigned sz;
561 size_t xfer = 0;
562 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800563 int last_percent = -1;
564 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700565
566 printf("loading: '%s'", fn);
567 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800568 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700569 if (data == 0) {
570 printf("\n");
571 fprintf(stderr, "* cannot read '%s' *\n", fn);
572 return -1;
573 }
574
575 char buf[100];
576 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
577 int fd = adb_connect(buf);
578 if (fd < 0) {
579 // Try falling back to the older sideload method. Maybe this
580 // is an older device that doesn't support sideload-host.
581 printf("\n");
582 status = adb_download_buffer("sideload", fn, data, sz, 1);
583 goto done;
584 }
585
Spencer Lowf055c192015-01-25 14:40:16 -0800586 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700587
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700588 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800589 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700590 fprintf(stderr, "* failed to read command: %s\n", adb_error());
591 status = -1;
592 goto done;
593 }
594
595 if (strncmp("DONEDONE", buf, 8) == 0) {
596 status = 0;
597 break;
598 }
599
600 buf[8] = '\0';
601 int block = strtol(buf, NULL, 10);
602
603 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
604 if (offset >= sz) {
605 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
606 status = -1;
607 goto done;
608 }
609 uint8_t* start = data + offset;
610 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
611 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
612 if (offset_end > sz) {
613 to_write = sz - offset;
614 }
615
Dan Albertcc731cc2015-02-24 21:26:58 -0800616 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700617 adb_status(fd);
618 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
619 status = -1;
620 goto done;
621 }
622 xfer += to_write;
623
624 // For normal OTA packages, we expect to transfer every byte
625 // twice, plus a bit of overhead (one read during
626 // verification, one read of each byte for installation, plus
627 // extra access to things like the zip central directory).
628 // This estimate of the completion becomes 100% when we've
629 // transferred ~2.13 (=100/47) times the package size.
630 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
631 if (percent != last_percent) {
632 printf("\rserving: '%s' (~%d%%) ", fn, percent);
633 fflush(stdout);
634 last_percent = percent;
635 }
636 }
637
Colin Cross6d6a8982014-07-07 14:12:41 -0700638 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700639
640 done:
641 if (fd >= 0) adb_close(fd);
642 free(data);
643 return status;
644}
645
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800646static void status_window(transport_type ttype, const char* serial)
647{
648 char command[4096];
649 char *state = 0;
650 char *laststate = 0;
651
652 /* silence stderr */
653#ifdef _WIN32
654 /* XXX: TODO */
655#else
656 int fd;
657 fd = unix_open("/dev/null", O_WRONLY);
658 dup2(fd, 2);
659 adb_close(fd);
660#endif
661
662 format_host_command(command, sizeof command, "get-state", ttype, serial);
663
664 for(;;) {
665 adb_sleep_ms(250);
666
667 if(state) {
668 free(state);
669 state = 0;
670 }
671
672 state = adb_query(command);
673
674 if(state) {
675 if(laststate && !strcmp(state,laststate)){
676 continue;
677 } else {
678 if(laststate) free(laststate);
679 laststate = strdup(state);
680 }
681 }
682
683 printf("%c[2J%c[2H", 27, 27);
684 printf("Android Debug Bridge\n");
685 printf("State: %s\n", state ? state : "offline");
686 fflush(stdout);
687 }
688}
689
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700690static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700691{
692 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
693}
694
695/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700696static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697{
698 const char *ts;
699 size_t alloc_len;
700 char *ret;
701 char *dest;
702
Jeff Sharkey7c460352014-06-10 16:22:17 -0700703 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700704 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800705 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700706 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800707 alloc_len++;
708 }
709 }
710
Jeff Sharkey7c460352014-06-10 16:22:17 -0700711 if (alloc_len == 0) {
712 // Preserve empty arguments
713 ret = (char *) malloc(3);
714 ret[0] = '\"';
715 ret[1] = '\"';
716 ret[2] = '\0';
717 return ret;
718 }
719
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700720 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 dest = ret;
722
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700723 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700724 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725 *dest++ = '\\';
726 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800727 *dest++ = *ts;
728 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800729 *dest++ = '\0';
730
731 return ret;
732}
733
734/**
735 * Run ppp in "notty" mode against a resource listed as the first parameter
736 * eg:
737 *
738 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
739 *
740 */
Dan Albertbac34742015-02-25 17:51:28 -0800741int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800742{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800743#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800744 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
745 return -1;
746#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800747 pid_t pid;
748 int fd;
749
750 if (argc < 2) {
751 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
752 argv[0]);
753
754 return 1;
755 }
756
Dan Albertbac34742015-02-25 17:51:28 -0800757 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800758 fd = adb_connect(adb_service_name);
759
760 if(fd < 0) {
761 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
762 adb_service_name, adb_error());
763 return 1;
764 }
765
766 pid = fork();
767
768 if (pid < 0) {
769 perror("from fork()");
770 return 1;
771 } else if (pid == 0) {
772 int err;
773 int i;
774 const char **ppp_args;
775
776 // copy args
777 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
778 ppp_args[0] = "pppd";
779 for (i = 2 ; i < argc ; i++) {
780 //argv[2] and beyond become ppp_args[1] and beyond
781 ppp_args[i - 1] = argv[i];
782 }
783 ppp_args[i-1] = NULL;
784
785 // child side
786
787 dup2(fd, STDIN_FILENO);
788 dup2(fd, STDOUT_FILENO);
789 adb_close(STDERR_FILENO);
790 adb_close(fd);
791
792 err = execvp("pppd", (char * const *)ppp_args);
793
794 if (err < 0) {
795 perror("execing pppd");
796 }
797 exit(-1);
798 } else {
799 // parent side
800
801 adb_close(fd);
802 return 0;
803 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800804#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800805}
806
Dan Albertbac34742015-02-25 17:51:28 -0800807static int send_shellcommand(transport_type transport, const char* serial,
808 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800809{
810 int fd, ret;
811
812 for(;;) {
813 fd = adb_connect(buf);
814 if(fd >= 0)
815 break;
816 fprintf(stderr,"- waiting for device -\n");
817 adb_sleep_ms(1000);
818 do_cmd(transport, serial, "wait-for-device", 0);
819 }
820
821 read_and_dump(fd);
822 ret = adb_close(fd);
823 if (ret)
824 perror("close");
825
826 return ret;
827}
828
Dan Albertbac34742015-02-25 17:51:28 -0800829static int logcat(transport_type transport, const char* serial, int argc,
830 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800831{
832 char buf[4096];
833
834 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700835 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836
837 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700838 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800839 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700840 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700841 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800842
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700843 if (!strcmp(argv[0], "longcat")) {
844 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800845 }
846
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800847 argc -= 1;
848 argv += 1;
849 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700850 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700851 strncat(buf, " ", sizeof(buf) - 1);
852 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853 free(quoted);
854 }
855
856 send_shellcommand(transport, serial, buf);
857 return 0;
858}
859
Mark Salyzyn60299df2014-04-30 09:10:31 -0700860static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800861{
862 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700863 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800864
865 for(;;) {
866 x = adb_dirstart(x);
867 if(x == 0) return 0;
868 *x = 0;
869 ret = adb_mkdir(path, 0775);
870 *x = OS_PATH_SEPARATOR;
871 if((ret < 0) && (errno != EEXIST)) {
872 return ret;
873 }
874 x++;
875 }
876 return 0;
877}
878
Dan Albertbac34742015-02-25 17:51:28 -0800879static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700880 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800881 char default_name[32];
882 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700883 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700884 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700885
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700886 /* find, extract, and use any -f argument */
887 for (i = 1; i < argc; i++) {
888 if (!strcmp("-f", argv[i])) {
889 if (i == argc-1) {
890 fprintf(stderr, "adb: -f passed with no filename\n");
891 return usage();
892 }
893 filename = argv[i+1];
894 for (j = i+2; j <= argc; ) {
895 argv[i++] = argv[j++];
896 }
897 argc -= 2;
898 argv[argc] = NULL;
899 }
Christopher Tated2f54152011-04-21 12:53:28 -0700900 }
901
Christopher Tatebb86bc52011-08-22 17:12:08 -0700902 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
903 if (argc < 2) return usage();
904
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800905 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700906 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800907 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700908 if (outFd < 0) {
909 fprintf(stderr, "adb: unable to open file %s\n", filename);
910 return -1;
911 }
912
913 snprintf(buf, sizeof(buf), "backup");
914 for (argc--, argv++; argc; argc--, argv++) {
915 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
916 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
917 }
918
919 D("backup. filename=%s buf=%s\n", filename, buf);
920 fd = adb_connect(buf);
921 if (fd < 0) {
922 fprintf(stderr, "adb: unable to connect for backup\n");
923 adb_close(outFd);
924 return -1;
925 }
926
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800927 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700928 copy_to_file(fd, outFd);
929
930 adb_close(fd);
931 adb_close(outFd);
932 return 0;
933}
934
Dan Albertbac34742015-02-25 17:51:28 -0800935static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700936 const char* filename;
937 int fd, tarFd;
938
939 if (argc != 2) return usage();
940
941 filename = argv[1];
942 tarFd = adb_open(filename, O_RDONLY);
943 if (tarFd < 0) {
944 fprintf(stderr, "adb: unable to open file %s\n", filename);
945 return -1;
946 }
947
948 fd = adb_connect("restore:");
949 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700950 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700951 adb_close(tarFd);
952 return -1;
953 }
954
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800955 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700956 copy_to_file(tarFd, fd);
957
958 adb_close(fd);
959 adb_close(tarFd);
960 return 0;
961}
962
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800963#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
964static int top_works(const char *top)
965{
966 if (top != NULL && adb_is_absolute_host_path(top)) {
967 char path_buf[PATH_MAX];
968 snprintf(path_buf, sizeof(path_buf),
969 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
970 return access(path_buf, F_OK) == 0;
971 }
972 return 0;
973}
974
975static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
976{
977 strcpy(path_buf, indir);
978 while (1) {
979 if (top_works(path_buf)) {
980 return path_buf;
981 }
982 char *s = adb_dirstop(path_buf);
983 if (s != NULL) {
984 *s = '\0';
985 } else {
986 path_buf[0] = '\0';
987 return NULL;
988 }
989 }
990}
991
992static char *find_top(char path_buf[PATH_MAX])
993{
994 char *top = getenv("ANDROID_BUILD_TOP");
995 if (top != NULL && top[0] != '\0') {
996 if (!top_works(top)) {
997 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
998 return NULL;
999 }
1000 } else {
1001 top = getenv("TOP");
1002 if (top != NULL && top[0] != '\0') {
1003 if (!top_works(top)) {
1004 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1005 return NULL;
1006 }
1007 } else {
1008 top = NULL;
1009 }
1010 }
1011
1012 if (top != NULL) {
1013 /* The environment pointed to a top directory that works.
1014 */
1015 strcpy(path_buf, top);
1016 return path_buf;
1017 }
1018
1019 /* The environment didn't help. Walk up the tree from the CWD
1020 * to see if we can find the top.
1021 */
1022 char dir[PATH_MAX];
1023 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1024 if (top == NULL) {
1025 /* If the CWD isn't under a good-looking top, see if the
1026 * executable is.
1027 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001028 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001029 top = find_top_from(dir, path_buf);
1030 }
1031 return top;
1032}
1033
1034/* <hint> may be:
1035 * - A simple product name
1036 * e.g., "sooner"
1037TODO: debug? sooner-debug, sooner:debug?
1038 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1039 * e.g., "out/target/product/sooner"
1040 * - An absolute path to the PRODUCT_OUT dir
1041 * e.g., "/src/device/out/target/product/sooner"
1042 *
1043 * Given <hint>, try to construct an absolute path to the
1044 * ANDROID_PRODUCT_OUT dir.
1045 */
1046static const char *find_product_out_path(const char *hint)
1047{
1048 static char path_buf[PATH_MAX];
1049
1050 if (hint == NULL || hint[0] == '\0') {
1051 return NULL;
1052 }
1053
1054 /* If it's already absolute, don't bother doing any work.
1055 */
1056 if (adb_is_absolute_host_path(hint)) {
1057 strcpy(path_buf, hint);
1058 return path_buf;
1059 }
1060
1061 /* If there are any slashes in it, assume it's a relative path;
1062 * make it absolute.
1063 */
1064 if (adb_dirstart(hint) != NULL) {
1065 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1066 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1067 return NULL;
1068 }
1069 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1070 fprintf(stderr, "adb: Couldn't assemble path\n");
1071 return NULL;
1072 }
1073 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1074 strcat(path_buf, hint);
1075 return path_buf;
1076 }
1077
1078 /* It's a string without any slashes. Try to do something with it.
1079 *
1080 * Try to find the root of the build tree, and build a PRODUCT_OUT
1081 * path from there.
1082 */
1083 char top_buf[PATH_MAX];
1084 const char *top = find_top(top_buf);
1085 if (top == NULL) {
1086 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1087 return NULL;
1088 }
1089//TODO: if we have a way to indicate debug, look in out/debug/target/...
1090 snprintf(path_buf, sizeof(path_buf),
1091 "%s" OS_PATH_SEPARATOR_STR
1092 "out" OS_PATH_SEPARATOR_STR
1093 "target" OS_PATH_SEPARATOR_STR
1094 "product" OS_PATH_SEPARATOR_STR
1095 "%s", top_buf, hint);
1096 if (access(path_buf, F_OK) < 0) {
1097 fprintf(stderr, "adb: Couldn't find a product dir "
1098 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1099 return NULL;
1100 }
1101 return path_buf;
1102}
1103
Dan Albertbac34742015-02-25 17:51:28 -08001104static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1105 char const **path2, int *show_progress,
1106 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001107 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001108 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001109
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001110 while (narg > 0) {
1111 if (!strcmp(*arg, "-p")) {
1112 *show_progress = 1;
1113 } else if (!strcmp(*arg, "-a")) {
1114 *copy_attrs = 1;
1115 } else {
1116 break;
1117 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001118 ++arg;
1119 --narg;
1120 }
1121
1122 if (narg > 0) {
1123 *path1 = *arg;
1124 ++arg;
1125 --narg;
1126 }
1127
1128 if (narg > 0) {
1129 *path2 = *arg;
1130 }
1131}
1132
Tao Bao175b7bb2015-03-29 11:22:34 -07001133static int adb_connect_command(const char* command) {
1134 int fd = adb_connect(command);
1135 if (fd != -1) {
1136 read_and_dump(fd);
1137 adb_close(fd);
1138 return 0;
1139 }
1140 fprintf(stderr, "Error: %s\n", adb_error());
1141 return 1;
1142}
1143
Dan Albertbac34742015-02-25 17:51:28 -08001144int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001145{
1146 char buf[4096];
1147 int no_daemon = 0;
1148 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001149 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001150 int persist = 0;
1151 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001152 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001153 const char* serial = NULL;
1154 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001155
1156 /* If defined, this should be an absolute path to
1157 * the directory containing all of the various system images
1158 * for a particular product. If not defined, and the adb
1159 * command requires this information, then the user must
1160 * specify the path using "-p".
1161 */
1162 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1163 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1164 gProductOutPath = NULL;
1165 }
1166 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1167
Nick Pellydb449262009-05-07 12:48:03 -07001168 serial = getenv("ANDROID_SERIAL");
1169
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001170 /* Validate and assign the server port */
1171 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1172 int server_port = DEFAULT_ADB_PORT;
1173 if (server_port_str && strlen(server_port_str) > 0) {
1174 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001175 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001176 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001177 "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 +01001178 server_port_str);
1179 return usage();
1180 }
1181 }
1182
1183 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001184 while (argc > 0) {
1185 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001186 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001187 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001188 no_daemon = 1;
1189 } else if (!strcmp(argv[0], "fork-server")) {
1190 /* this is a special flag used only when the ADB client launches the ADB Server */
1191 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001192 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001193 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001194 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001195 const char *product = NULL;
1196 if (argv[0][2] == '\0') {
1197 if (argc < 2) return usage();
1198 product = argv[1];
1199 argc--;
1200 argv++;
1201 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001202 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001203 }
1204 gProductOutPath = find_product_out_path(product);
1205 if (gProductOutPath == NULL) {
1206 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1207 product);
1208 return usage();
1209 }
1210 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1211 if (isdigit(argv[0][2])) {
1212 serial = argv[0] + 2;
1213 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001214 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001215 serial = argv[1];
1216 argc--;
1217 argv++;
1218 }
1219 } else if (!strcmp(argv[0],"-d")) {
1220 ttype = kTransportUsb;
1221 } else if (!strcmp(argv[0],"-e")) {
1222 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001223 } else if (!strcmp(argv[0],"-a")) {
1224 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001225 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001226 const char *hostname = NULL;
1227 if (argv[0][2] == '\0') {
1228 if (argc < 2) return usage();
1229 hostname = argv[1];
1230 argc--;
1231 argv++;
1232 } else {
1233 hostname = argv[0] + 2;
1234 }
1235 adb_set_tcp_name(hostname);
1236
Riley Andrews98f58e82014-12-05 17:37:24 -08001237 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001238 if (argv[0][2] == '\0') {
1239 if (argc < 2) return usage();
1240 server_port_str = argv[1];
1241 argc--;
1242 argv++;
1243 } else {
1244 server_port_str = argv[0] + 2;
1245 }
1246 if (strlen(server_port_str) > 0) {
1247 server_port = (int) strtol(server_port_str, NULL, 0);
1248 if (server_port <= 0 || server_port > 65535) {
1249 fprintf(stderr,
1250 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1251 server_port_str);
1252 return usage();
1253 }
1254 } else {
1255 fprintf(stderr,
1256 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1257 return usage();
1258 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001259 } else {
1260 /* out of recognized modifiers and flags */
1261 break;
1262 }
1263 argc--;
1264 argv++;
1265 }
1266
1267 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001268 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001269
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001270 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001271 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001272 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001273 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001274 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001275 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001276 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001277 fprintf(stderr,"* could not start server *\n");
1278 }
1279 return r;
1280 }
1281
Riley Andrews98f58e82014-12-05 17:37:24 -08001282 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001283 return usage();
1284 }
1285
Riley Andrewsc8514c82014-12-05 17:32:46 -08001286 /* handle wait-for-* prefix */
1287 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001288 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001289 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1290 if (ttype == kTransportUsb) {
1291 service = "wait-for-usb";
1292 } else if (ttype == kTransportLocal) {
1293 service = "wait-for-local";
1294 } else {
1295 service = "wait-for-any";
1296 }
1297 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001298
Riley Andrewsc8514c82014-12-05 17:32:46 -08001299 format_host_command(buf, sizeof buf, service, ttype, serial);
1300
1301 if (adb_command(buf)) {
1302 D("failure: %s *\n",adb_error());
1303 fprintf(stderr,"error: %s\n", adb_error());
1304 return 1;
1305 }
1306
1307 /* Allow a command to be run after wait-for-device,
1308 * e.g. 'adb wait-for-device shell'.
1309 */
1310 if (argc == 1) {
1311 return 0;
1312 }
1313
1314 /* Fall through */
1315 argc--;
1316 argv++;
1317 }
1318
1319 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001320 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001321 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001322 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001323 if (argc < 2)
1324 listopt = "";
1325 else if (argc == 2 && !strcmp(argv[1], "-l"))
1326 listopt = argv[1];
1327 else {
1328 fprintf(stderr, "Usage: adb devices [-l]\n");
1329 return 1;
1330 }
1331 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001332 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001333 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001334 printf("List of devices attached \n");
1335 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], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001342 char *tmp;
1343 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001344 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001345 return 1;
1346 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001347 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1348 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001349 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001350 printf("%s\n", tmp);
1351 return 0;
1352 } else {
1353 return 1;
1354 }
1355 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001356 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001357 char *tmp;
1358 if (argc > 2) {
1359 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1360 return 1;
1361 }
1362 if (argc == 2) {
1363 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1364 } else {
1365 snprintf(buf, sizeof buf, "host:disconnect:");
1366 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001367 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001368 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001369 printf("%s\n", tmp);
1370 return 0;
1371 } else {
1372 return 1;
1373 }
1374 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001375 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001376 return adb_send_emulator_command(argc, argv);
1377 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001378 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001379 int r;
1380 int fd;
1381
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001382 char h = (argv[0][0] == 'h');
1383
1384 if (h) {
1385 printf("\x1b[41;33m");
1386 fflush(stdout);
1387 }
1388
Riley Andrews98f58e82014-12-05 17:37:24 -08001389 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001390 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001391 r = interactive_shell();
1392 if (h) {
1393 printf("\x1b[0m");
1394 fflush(stdout);
1395 }
1396 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001397 }
1398
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001399 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001400 argc -= 2;
1401 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001402 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001403 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001404 strncat(buf, " ", sizeof(buf) - 1);
1405 strncat(buf, quoted, sizeof(buf) - 1);
1406 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001407 }
1408
1409 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001410 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001412 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001413 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001414 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001415 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001416 adb_close(fd);
1417 r = 0;
1418 } else {
1419 fprintf(stderr,"error: %s\n", adb_error());
1420 r = -1;
1421 }
1422
Riley Andrews98f58e82014-12-05 17:37:24 -08001423 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001424 fprintf(stderr,"\n- waiting for device -\n");
1425 adb_sleep_ms(1000);
1426 do_cmd(ttype, serial, "wait-for-device", 0);
1427 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001428 if (h) {
1429 printf("\x1b[0m");
1430 fflush(stdout);
1431 }
JP Abgrall408fa572011-03-16 15:57:42 -07001432 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001433 return r;
1434 }
1435 }
1436 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001437 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001438 int exec_in = !strcmp(argv[0], "exec-in");
1439 int fd;
1440
1441 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1442 argc -= 2;
1443 argv += 2;
1444 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001445 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001446 strncat(buf, " ", sizeof(buf) - 1);
1447 strncat(buf, quoted, sizeof(buf) - 1);
1448 free(quoted);
1449 }
1450
1451 fd = adb_connect(buf);
1452 if (fd < 0) {
1453 fprintf(stderr, "error: %s\n", adb_error());
1454 return -1;
1455 }
1456
1457 if (exec_in) {
1458 copy_to_file(STDIN_FILENO, fd);
1459 } else {
1460 copy_to_file(fd, STDOUT_FILENO);
1461 }
1462
1463 adb_close(fd);
1464 return 0;
1465 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001466 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001467 int fd;
1468 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001469 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001470 fprintf(stderr,"* server not running *\n");
1471 return 1;
1472 }
1473 return 0;
1474 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001475 else if (!strcmp(argv[0], "sideload")) {
1476 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001477 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001478 return 1;
1479 } else {
1480 return 0;
1481 }
1482 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001483 else if (!strcmp(argv[0], "remount") ||
1484 !strcmp(argv[0], "reboot") ||
1485 !strcmp(argv[0], "reboot-bootloader") ||
1486 !strcmp(argv[0], "tcpip") ||
1487 !strcmp(argv[0], "usb") ||
1488 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001489 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001490 !strcmp(argv[0], "disable-verity") ||
1491 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001492 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001493 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001494 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001495 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001496 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001497 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001498 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001499 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001500 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001501 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001502 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001503 if (argc != 1) return usage();
1504 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001505 return 0;
1506 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001507 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001508 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001509 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001510 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001511 char remove = 0;
1512 char remove_all = 0;
1513 char list = 0;
1514 char no_rebind = 0;
1515
1516 // Parse options here.
1517 while (argc > 1 && argv[1][0] == '-') {
1518 if (!strcmp(argv[1], "--list"))
1519 list = 1;
1520 else if (!strcmp(argv[1], "--remove"))
1521 remove = 1;
1522 else if (!strcmp(argv[1], "--remove-all"))
1523 remove_all = 1;
1524 else if (!strcmp(argv[1], "--no-rebind"))
1525 no_rebind = 1;
1526 else {
1527 return usage();
1528 }
1529 argc--;
1530 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001532
1533 // Ensure we can only use one option at a time.
1534 if (list + remove + remove_all + no_rebind > 1) {
1535 return usage();
1536 }
1537
1538 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001539 if (reverse) {
1540 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001541 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001542 if (serial) {
1543 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1544 serial);
1545 } else if (ttype == kTransportUsb) {
1546 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1547 } else if (ttype == kTransportLocal) {
1548 snprintf(host_prefix, sizeof host_prefix, "host-local");
1549 } else {
1550 snprintf(host_prefix, sizeof host_prefix, "host");
1551 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001552 }
1553
1554 // Implement forward --list
1555 if (list) {
1556 if (argc != 1)
1557 return usage();
1558 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1559 char* forwards = adb_query(buf);
1560 if (forwards == NULL) {
1561 fprintf(stderr, "error: %s\n", adb_error());
1562 return 1;
1563 }
1564 printf("%s", forwards);
1565 free(forwards);
1566 return 0;
1567 }
1568
1569 // Implement forward --remove-all
1570 else if (remove_all) {
1571 if (argc != 1)
1572 return usage();
1573 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1574 }
1575
1576 // Implement forward --remove <local>
1577 else if (remove) {
1578 if (argc != 2)
1579 return usage();
1580 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1581 }
1582 // Or implement one of:
1583 // forward <local> <remote>
1584 // forward --no-rebind <local> <remote>
1585 else
1586 {
1587 if (argc != 3)
1588 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001589 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001590 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1591 }
1592
Riley Andrews98f58e82014-12-05 17:37:24 -08001593 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001594 fprintf(stderr,"error: %s\n", adb_error());
1595 return 1;
1596 }
1597 return 0;
1598 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001599 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001600 else if (!strcmp(argv[0], "ls")) {
1601 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001602 return do_sync_ls(argv[1]);
1603 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001604 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001605 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001606 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001607 const char* lpath = NULL, *rpath = NULL;
1608
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001609 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001610
1611 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001612 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001613 }
1614
1615 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001616 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001617 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001618 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001619 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001620 const char* rpath = NULL, *lpath = ".";
1621
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001622 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001623
1624 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001625 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001626 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001627
1628 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001629 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001630 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001631 if (argc < 2) return usage();
1632 return install_app(ttype, serial, argc, argv);
1633 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001634 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001635 if (argc < 2) return usage();
1636 return install_multiple_app(ttype, serial, argc, argv);
1637 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001638 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001639 if (argc < 2) return usage();
1640 return uninstall_app(ttype, serial, argc, argv);
1641 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001642 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001643 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001644 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1645
Anthony Newnam705c9442010-02-22 08:36:49 -06001646 int listonly = 0;
1647
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001648 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001649 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001650 /* No local path was specified. */
1651 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001652 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1653 listonly = 1;
1654 if (argc == 3) {
1655 srcarg = argv[2];
1656 } else {
1657 srcarg = NULL;
1658 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001659 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001660 /* A local path or "android"/"data" arg was specified. */
1661 srcarg = argv[1];
1662 } else {
1663 return usage();
1664 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001665 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1666 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001667 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001668
Elliott Hughesec7a6672015-03-16 21:58:32 +00001669 if (system_srcpath != NULL)
1670 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001671 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001672 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001673 if(ret == 0 && oem_srcpath != NULL)
1674 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001675 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001676 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001677
Elliott Hughesec7a6672015-03-16 21:58:32 +00001678 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001679 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001680 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001681 free(data_srcpath);
1682 return ret;
1683 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001684 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001685 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001686 !strcmp(argv[0],"get-serialno") ||
1687 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 {
1689 char *tmp;
1690
1691 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1692 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001693 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001694 printf("%s\n", tmp);
1695 return 0;
1696 } else {
1697 return 1;
1698 }
1699 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001700 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001701 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001702 status_window(ttype, serial);
1703 return 0;
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001706 return logcat(ttype, serial, argc, argv);
1707 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001709 return ppp(argc, argv);
1710 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001712 return adb_connect("host:start-server");
1713 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001714 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001715 return backup(argc, argv);
1716 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001717 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001718 return restore(argc, argv);
1719 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001720 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001721 if (argc < 2) return usage();
1722 return adb_auth_keygen(argv[1]);
1723 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001724 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001725 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001726 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001727 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001728 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001729 help();
1730 return 0;
1731 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001732 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001733 version(stdout);
1734 return 0;
1735 }
1736
1737 usage();
1738 return 1;
1739}
1740
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001741#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001742static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001743{
Dan Albertbac34742015-02-25 17:51:28 -08001744 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001745 int argc;
1746 va_list ap;
1747
1748 va_start(ap, cmd);
1749 argc = 0;
1750
1751 if (serial) {
1752 argv[argc++] = "-s";
1753 argv[argc++] = serial;
1754 } else if (ttype == kTransportUsb) {
1755 argv[argc++] = "-d";
1756 } else if (ttype == kTransportLocal) {
1757 argv[argc++] = "-e";
1758 }
1759
1760 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001761 while(argc < MAX_ARGV_LENGTH &&
1762 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1763 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001764 va_end(ap);
1765
1766#if 0
1767 int n;
1768 fprintf(stderr,"argc = %d\n",argc);
1769 for(n = 0; n < argc; n++) {
1770 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1771 }
1772#endif
1773
1774 return adb_commandline(argc, argv);
1775}
1776
1777int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001778 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1779 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001780{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001781 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001782 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001783
1784 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001785 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001786 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001787 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001788 oem_srcdir = product_file("oem");
1789 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001790 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1791 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001792 // Check if oem partition exists.
1793 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1794 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001795 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001796 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1797 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001798 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001799 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001800 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001801 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001802 } else if(strcmp(srcarg, "vendor") == 0) {
1803 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001804 } else if(strcmp(srcarg, "oem") == 0) {
1805 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001806 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001807 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001808 return 1;
1809 }
1810 }
1811
Elliott Hughesec7a6672015-03-16 21:58:32 +00001812 if(system_srcdir_out != NULL)
1813 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001814 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001815 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001816
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001817 if(vendor_srcdir_out != NULL)
1818 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001819 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001820 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001821
Elliott Hughesec7a6672015-03-16 21:58:32 +00001822 if(oem_srcdir_out != NULL)
1823 *oem_srcdir_out = oem_srcdir;
1824 else
1825 free(oem_srcdir);
1826
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001827 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001828 *data_srcdir_out = data_srcdir;
1829 else
1830 free(data_srcdir);
1831
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001832 return 0;
1833}
1834
Dan Albertbac34742015-02-25 17:51:28 -08001835static int pm_command(transport_type transport, const char* serial,
1836 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001837{
1838 char buf[4096];
1839
1840 snprintf(buf, sizeof(buf), "shell:pm");
1841
1842 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001843 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001844 strncat(buf, " ", sizeof(buf) - 1);
1845 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001846 free(quoted);
1847 }
1848
1849 send_shellcommand(transport, serial, buf);
1850 return 0;
1851}
1852
Dan Albertbac34742015-02-25 17:51:28 -08001853int uninstall_app(transport_type transport, const char* serial, int argc,
1854 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001855{
1856 /* if the user choose the -k option, we refuse to do it until devices are
1857 out with the option to uninstall the remaining data somehow (adb/ui) */
1858 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1859 {
1860 printf(
1861 "The -k option uninstalls the application while retaining the data/cache.\n"
1862 "At the moment, there is no way to remove the remaining data.\n"
1863 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1864 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1865 return -1;
1866 }
1867
1868 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1869 return pm_command(transport, serial, argc, argv);
1870}
1871
Dan Albertbac34742015-02-25 17:51:28 -08001872static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001873{
1874 char buf[4096];
1875 char* quoted;
1876
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001877 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001878 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001879 strncat(buf, quoted, sizeof(buf)-1);
1880 free(quoted);
1881
1882 send_shellcommand(transport, serial, buf);
1883 return 0;
1884}
1885
Kenny Root597ea5b2011-08-05 11:19:45 -07001886static const char* get_basename(const char* filename)
1887{
1888 const char* basename = adb_dirstop(filename);
1889 if (basename) {
1890 basename++;
1891 return basename;
1892 } else {
1893 return filename;
1894 }
1895}
1896
Dan Albertbac34742015-02-25 17:51:28 -08001897int install_app(transport_type transport, const char* serial, int argc,
1898 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001899{
1900 static const char *const DATA_DEST = "/data/local/tmp/%s";
1901 static const char *const SD_DEST = "/sdcard/tmp/%s";
1902 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001903 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001904 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001905
1906 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001907 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001908 where = SD_DEST;
1909 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001910 }
1911
Jeff Sharkey960df972014-06-09 17:30:57 -07001912 // Find last APK argument.
1913 // All other arguments passed through verbatim.
1914 int last_apk = -1;
1915 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001916 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001917 char* dot = strrchr(file, '.');
1918 if (dot && !strcasecmp(dot, ".apk")) {
1919 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1920 fprintf(stderr, "Invalid APK file: %s\n", file);
1921 return -1;
1922 }
1923
1924 last_apk = i;
1925 break;
1926 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001927 }
1928
Jeff Sharkey960df972014-06-09 17:30:57 -07001929 if (last_apk == -1) {
1930 fprintf(stderr, "Missing APK file\n");
1931 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001932 }
1933
Dan Albertbac34742015-02-25 17:51:28 -08001934 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001935 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001937 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001938 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001939 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001940 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001941 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001942 }
1943
1944 pm_command(transport, serial, argc, argv);
1945
Kenny Root60733e92012-03-26 16:14:02 -07001946cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001947 delete_file(transport, serial, apk_dest);
1948 return err;
1949}
1950
Dan Albertbac34742015-02-25 17:51:28 -08001951int install_multiple_app(transport_type transport, const char* serial, int argc,
1952 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001953{
1954 char buf[1024];
1955 int i;
1956 struct stat sb;
1957 unsigned long long total_size = 0;
1958
1959 // Find all APK arguments starting at end.
1960 // All other arguments passed through verbatim.
1961 int first_apk = -1;
1962 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001963 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001964 char* dot = strrchr(file, '.');
1965 if (dot && !strcasecmp(dot, ".apk")) {
1966 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1967 fprintf(stderr, "Invalid APK file: %s\n", file);
1968 return -1;
1969 }
1970
1971 total_size += sb.st_size;
1972 first_apk = i;
1973 } else {
1974 break;
1975 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001976 }
1977
Jeff Sharkey960df972014-06-09 17:30:57 -07001978 if (first_apk == -1) {
1979 fprintf(stderr, "Missing APK file\n");
1980 return 1;
1981 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001982
Jeff Sharkey960df972014-06-09 17:30:57 -07001983 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1984 for (i = 1; i < first_apk; i++) {
1985 char *quoted = escape_arg(argv[i]);
1986 strncat(buf, " ", sizeof(buf) - 1);
1987 strncat(buf, quoted, sizeof(buf) - 1);
1988 free(quoted);
1989 }
1990
1991 // Create install session
1992 int fd = adb_connect(buf);
1993 if (fd < 0) {
1994 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1995 return -1;
1996 }
1997 read_status_line(fd, buf, sizeof(buf));
1998 adb_close(fd);
1999
2000 int session_id = -1;
2001 if (!strncmp("Success", buf, 7)) {
2002 char* start = strrchr(buf, '[');
2003 char* end = strrchr(buf, ']');
2004 if (start && end) {
2005 *end = '\0';
2006 session_id = strtol(start + 1, NULL, 10);
2007 }
2008 }
2009 if (session_id < 0) {
2010 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002011 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002012 return -1;
2013 }
2014
2015 // Valid session, now stream the APKs
2016 int success = 1;
2017 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002018 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002019 if (stat(file, &sb) == -1) {
2020 fprintf(stderr, "Failed to stat %s\n", file);
2021 success = 0;
2022 goto finalize_session;
2023 }
2024
2025 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002026 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002027
2028 int localFd = adb_open(file, O_RDONLY);
2029 if (localFd < 0) {
2030 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2031 success = 0;
2032 goto finalize_session;
2033 }
2034
2035 int remoteFd = adb_connect(buf);
2036 if (remoteFd < 0) {
2037 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2038 adb_close(localFd);
2039 success = 0;
2040 goto finalize_session;
2041 }
2042
2043 copy_to_file(localFd, remoteFd);
2044 read_status_line(remoteFd, buf, sizeof(buf));
2045
2046 adb_close(localFd);
2047 adb_close(remoteFd);
2048
2049 if (strncmp("Success", buf, 7)) {
2050 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002051 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002052 success = 0;
2053 goto finalize_session;
2054 }
2055 }
2056
2057finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002058 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002059 if (success) {
2060 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2061 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002062 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002063 }
2064
2065 fd = adb_connect(buf);
2066 if (fd < 0) {
2067 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2068 return -1;
2069 }
2070 read_status_line(fd, buf, sizeof(buf));
2071 adb_close(fd);
2072
2073 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002074 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002075 return 0;
2076 } else {
2077 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002078 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002079 return -1;
2080 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002081}