blob: 34efefeb56ba3adb5af300451e6b6bdbdf691f68 [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
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100259static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800260
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100261static void stdin_raw_init(int fd) {
262 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100264 termios tio;
265 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100267 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800268
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100269 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270 tio.c_cc[VTIME] = 0;
271 tio.c_cc[VMIN] = 1;
272
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100273 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274}
275
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100276static void stdin_raw_restore(int fd) {
277 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278}
279#endif
280
281static void read_and_dump(int fd)
282{
283 char buf[4096];
284 int len;
285
286 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700287 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 if(len == 0) {
291 break;
292 }
293
294 if(len < 0) {
295 if(errno == EINTR) continue;
296 break;
297 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400298 fwrite(buf, 1, len, stdout);
299 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 }
301}
302
Jeff Sharkey960df972014-06-09 17:30:57 -0700303static void read_status_line(int fd, char* buf, size_t count)
304{
305 count--;
306 while (count > 0) {
307 int len = adb_read(fd, buf, count);
308 if (len == 0) {
309 break;
310 } else if (len < 0) {
311 if (errno == EINTR) continue;
312 break;
313 }
314
315 buf += len;
316 count -= len;
317 }
318 *buf = '\0';
319}
320
Christopher Tated2f54152011-04-21 12:53:28 -0700321static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700322 const size_t BUFSIZE = 32 * 1024;
323 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700324 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700325 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700326
327 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800328
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700329 if (inFd == STDIN_FILENO) {
330 stdin_raw_init(STDIN_FILENO);
331 }
Yabin Cuid325e862014-11-17 14:48:25 -0800332
Christopher Tated2f54152011-04-21 12:53:28 -0700333 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700334 if (inFd == STDIN_FILENO) {
335 len = unix_read(inFd, buf, BUFSIZE);
336 } else {
337 len = adb_read(inFd, buf, BUFSIZE);
338 }
Christopher Tated2f54152011-04-21 12:53:28 -0700339 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700340 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700341 break;
342 }
343 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700344 if (errno == EINTR) {
345 D("copy_to_file() : EINTR, retrying\n");
346 continue;
347 }
Christopher Tated2f54152011-04-21 12:53:28 -0700348 D("copy_to_file() : error %d\n", errno);
349 break;
350 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700351 if (outFd == STDOUT_FILENO) {
352 fwrite(buf, 1, len, stdout);
353 fflush(stdout);
354 } else {
355 adb_write(outFd, buf, len);
356 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700357 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700358 }
Yabin Cuid325e862014-11-17 14:48:25 -0800359
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700360 if (inFd == STDIN_FILENO) {
361 stdin_raw_restore(STDIN_FILENO);
362 }
Yabin Cuid325e862014-11-17 14:48:25 -0800363
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700364 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700365 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700366}
367
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800368static void *stdin_read_thread(void *x)
369{
370 int fd, fdi;
371 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 int r, n;
373 int state = 0;
374
375 int *fds = (int*) x;
376 fd = fds[0];
377 fdi = fds[1];
378 free(fds);
379
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380 for(;;) {
381 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700382 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700384 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 if(r == 0) break;
386 if(r < 0) {
387 if(errno == EINTR) continue;
388 break;
389 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400390 for(n = 0; n < r; n++){
391 switch(buf[n]) {
392 case '\n':
393 state = 1;
394 break;
395 case '\r':
396 state = 1;
397 break;
398 case '~':
399 if(state == 1) state++;
400 break;
401 case '.':
402 if(state == 2) {
403 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400404 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400405 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800406 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 default:
408 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 r = adb_write(fd, buf, r);
412 if(r <= 0) {
413 break;
414 }
415 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800416 return 0;
417}
418
419int interactive_shell(void)
420{
421 adb_thread_t thr;
422 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423
424 fd = adb_connect("shell:");
425 if(fd < 0) {
426 fprintf(stderr,"error: %s\n", adb_error());
427 return 1;
428 }
429 fdi = 0; //dup(0);
430
Dan Albertbac34742015-02-25 17:51:28 -0800431 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800432 fds[0] = fd;
433 fds[1] = fdi;
434
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800435 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 adb_thread_create(&thr, stdin_read_thread, fds);
437 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 return 0;
440}
441
442
443static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
444{
445 if (serial) {
446 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
447 } else {
448 const char* prefix = "host";
449 if (ttype == kTransportUsb)
450 prefix = "host-usb";
451 else if (ttype == kTransportLocal)
452 prefix = "host-local";
453
454 snprintf(buffer, buflen, "%s:%s", prefix, command);
455 }
456}
457
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100458int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800459 unsigned progress)
460{
461 char buf[4096];
462 unsigned total;
463 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800464
465 sprintf(buf,"%s:%d", service, sz);
466 fd = adb_connect(buf);
467 if(fd < 0) {
468 fprintf(stderr,"error: %s\n", adb_error());
469 return -1;
470 }
471
472 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800473 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800474
475 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800476 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800477
478 if(progress) {
479 char *x = strrchr(service, ':');
480 if(x) service = x + 1;
481 }
482
483 while(sz > 0) {
484 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800485 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800486 adb_status(fd);
487 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
488 return -1;
489 }
490 sz -= xfer;
491 ptr += xfer;
492 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100493 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800494 fflush(stdout);
495 }
496 }
497 if(progress) {
498 printf("\n");
499 }
500
Dan Albertcc731cc2015-02-24 21:26:58 -0800501 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800502 fprintf(stderr,"* error reading response *\n");
503 adb_close(fd);
504 return -1;
505 }
506 if(memcmp(buf, "OKAY", 4)) {
507 buf[4] = 0;
508 fprintf(stderr,"* error response '%s' *\n", buf);
509 adb_close(fd);
510 return -1;
511 }
512
513 adb_close(fd);
514 return 0;
515}
516
517
518int adb_download(const char *service, const char *fn, unsigned progress)
519{
520 void *data;
521 unsigned sz;
522
523 data = load_file(fn, &sz);
524 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100525 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800526 return -1;
527 }
528
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100529 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800530 free(data);
531 return status;
532}
533
Doug Zongker71fe5842014-06-26 15:35:36 -0700534#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
535
536/*
537 * The sideload-host protocol serves the data in a file (given on the
538 * command line) to the client, using a simple protocol:
539 *
540 * - The connect message includes the total number of bytes in the
541 * file and a block size chosen by us.
542 *
543 * - The other side sends the desired block number as eight decimal
544 * digits (eg "00000023" for block 23). Blocks are numbered from
545 * zero.
546 *
547 * - We send back the data of the requested block. The last block is
548 * likely to be partial; when the last block is requested we only
549 * send the part of the block that exists, it's not padded up to the
550 * block size.
551 *
552 * - When the other side sends "DONEDONE" instead of a block number,
553 * we hang up.
554 */
555int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700556 unsigned sz;
557 size_t xfer = 0;
558 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800559 int last_percent = -1;
560 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700561
562 printf("loading: '%s'", fn);
563 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800564 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700565 if (data == 0) {
566 printf("\n");
567 fprintf(stderr, "* cannot read '%s' *\n", fn);
568 return -1;
569 }
570
571 char buf[100];
572 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
573 int fd = adb_connect(buf);
574 if (fd < 0) {
575 // Try falling back to the older sideload method. Maybe this
576 // is an older device that doesn't support sideload-host.
577 printf("\n");
578 status = adb_download_buffer("sideload", fn, data, sz, 1);
579 goto done;
580 }
581
Spencer Lowf055c192015-01-25 14:40:16 -0800582 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700583
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700584 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800585 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700586 fprintf(stderr, "* failed to read command: %s\n", adb_error());
587 status = -1;
588 goto done;
589 }
590
591 if (strncmp("DONEDONE", buf, 8) == 0) {
592 status = 0;
593 break;
594 }
595
596 buf[8] = '\0';
597 int block = strtol(buf, NULL, 10);
598
599 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
600 if (offset >= sz) {
601 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
602 status = -1;
603 goto done;
604 }
605 uint8_t* start = data + offset;
606 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
607 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
608 if (offset_end > sz) {
609 to_write = sz - offset;
610 }
611
Dan Albertcc731cc2015-02-24 21:26:58 -0800612 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700613 adb_status(fd);
614 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
615 status = -1;
616 goto done;
617 }
618 xfer += to_write;
619
620 // For normal OTA packages, we expect to transfer every byte
621 // twice, plus a bit of overhead (one read during
622 // verification, one read of each byte for installation, plus
623 // extra access to things like the zip central directory).
624 // This estimate of the completion becomes 100% when we've
625 // transferred ~2.13 (=100/47) times the package size.
626 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
627 if (percent != last_percent) {
628 printf("\rserving: '%s' (~%d%%) ", fn, percent);
629 fflush(stdout);
630 last_percent = percent;
631 }
632 }
633
Colin Cross6d6a8982014-07-07 14:12:41 -0700634 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700635
636 done:
637 if (fd >= 0) adb_close(fd);
638 free(data);
639 return status;
640}
641
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800642static void status_window(transport_type ttype, const char* serial)
643{
644 char command[4096];
645 char *state = 0;
646 char *laststate = 0;
647
648 /* silence stderr */
649#ifdef _WIN32
650 /* XXX: TODO */
651#else
652 int fd;
653 fd = unix_open("/dev/null", O_WRONLY);
654 dup2(fd, 2);
655 adb_close(fd);
656#endif
657
658 format_host_command(command, sizeof command, "get-state", ttype, serial);
659
660 for(;;) {
661 adb_sleep_ms(250);
662
663 if(state) {
664 free(state);
665 state = 0;
666 }
667
668 state = adb_query(command);
669
670 if(state) {
671 if(laststate && !strcmp(state,laststate)){
672 continue;
673 } else {
674 if(laststate) free(laststate);
675 laststate = strdup(state);
676 }
677 }
678
679 printf("%c[2J%c[2H", 27, 27);
680 printf("Android Debug Bridge\n");
681 printf("State: %s\n", state ? state : "offline");
682 fflush(stdout);
683 }
684}
685
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700686static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700687{
688 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
689}
690
691/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700692static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693{
694 const char *ts;
695 size_t alloc_len;
696 char *ret;
697 char *dest;
698
Jeff Sharkey7c460352014-06-10 16:22:17 -0700699 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700700 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700702 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 alloc_len++;
704 }
705 }
706
Jeff Sharkey7c460352014-06-10 16:22:17 -0700707 if (alloc_len == 0) {
708 // Preserve empty arguments
709 ret = (char *) malloc(3);
710 ret[0] = '\"';
711 ret[1] = '\"';
712 ret[2] = '\0';
713 return ret;
714 }
715
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700716 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800717 dest = ret;
718
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700719 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700720 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 *dest++ = '\\';
722 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800723 *dest++ = *ts;
724 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725 *dest++ = '\0';
726
727 return ret;
728}
729
730/**
731 * Run ppp in "notty" mode against a resource listed as the first parameter
732 * eg:
733 *
734 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
735 *
736 */
Dan Albertbac34742015-02-25 17:51:28 -0800737int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800738{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800739#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800740 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
741 return -1;
742#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800743 pid_t pid;
744 int fd;
745
746 if (argc < 2) {
747 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
748 argv[0]);
749
750 return 1;
751 }
752
Dan Albertbac34742015-02-25 17:51:28 -0800753 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800754 fd = adb_connect(adb_service_name);
755
756 if(fd < 0) {
757 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
758 adb_service_name, adb_error());
759 return 1;
760 }
761
762 pid = fork();
763
764 if (pid < 0) {
765 perror("from fork()");
766 return 1;
767 } else if (pid == 0) {
768 int err;
769 int i;
770 const char **ppp_args;
771
772 // copy args
773 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
774 ppp_args[0] = "pppd";
775 for (i = 2 ; i < argc ; i++) {
776 //argv[2] and beyond become ppp_args[1] and beyond
777 ppp_args[i - 1] = argv[i];
778 }
779 ppp_args[i-1] = NULL;
780
781 // child side
782
783 dup2(fd, STDIN_FILENO);
784 dup2(fd, STDOUT_FILENO);
785 adb_close(STDERR_FILENO);
786 adb_close(fd);
787
788 err = execvp("pppd", (char * const *)ppp_args);
789
790 if (err < 0) {
791 perror("execing pppd");
792 }
793 exit(-1);
794 } else {
795 // parent side
796
797 adb_close(fd);
798 return 0;
799 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800800#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800801}
802
Dan Albertbac34742015-02-25 17:51:28 -0800803static int send_shellcommand(transport_type transport, const char* serial,
804 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800805{
806 int fd, ret;
807
808 for(;;) {
809 fd = adb_connect(buf);
810 if(fd >= 0)
811 break;
812 fprintf(stderr,"- waiting for device -\n");
813 adb_sleep_ms(1000);
814 do_cmd(transport, serial, "wait-for-device", 0);
815 }
816
817 read_and_dump(fd);
818 ret = adb_close(fd);
819 if (ret)
820 perror("close");
821
822 return ret;
823}
824
Dan Albertbac34742015-02-25 17:51:28 -0800825static int logcat(transport_type transport, const char* serial, int argc,
826 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800827{
828 char buf[4096];
829
830 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700831 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800832
833 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700834 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700836 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700837 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800838
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700839 if (!strcmp(argv[0], "longcat")) {
840 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800841 }
842
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800843 argc -= 1;
844 argv += 1;
845 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700846 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700847 strncat(buf, " ", sizeof(buf) - 1);
848 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800849 free(quoted);
850 }
851
852 send_shellcommand(transport, serial, buf);
853 return 0;
854}
855
Mark Salyzyn60299df2014-04-30 09:10:31 -0700856static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800857{
858 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700859 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800860
861 for(;;) {
862 x = adb_dirstart(x);
863 if(x == 0) return 0;
864 *x = 0;
865 ret = adb_mkdir(path, 0775);
866 *x = OS_PATH_SEPARATOR;
867 if((ret < 0) && (errno != EEXIST)) {
868 return ret;
869 }
870 x++;
871 }
872 return 0;
873}
874
Dan Albertbac34742015-02-25 17:51:28 -0800875static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700876 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800877 char default_name[32];
878 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700879 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700880 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700881
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700882 /* find, extract, and use any -f argument */
883 for (i = 1; i < argc; i++) {
884 if (!strcmp("-f", argv[i])) {
885 if (i == argc-1) {
886 fprintf(stderr, "adb: -f passed with no filename\n");
887 return usage();
888 }
889 filename = argv[i+1];
890 for (j = i+2; j <= argc; ) {
891 argv[i++] = argv[j++];
892 }
893 argc -= 2;
894 argv[argc] = NULL;
895 }
Christopher Tated2f54152011-04-21 12:53:28 -0700896 }
897
Christopher Tatebb86bc52011-08-22 17:12:08 -0700898 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
899 if (argc < 2) return usage();
900
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800901 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700902 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800903 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700904 if (outFd < 0) {
905 fprintf(stderr, "adb: unable to open file %s\n", filename);
906 return -1;
907 }
908
909 snprintf(buf, sizeof(buf), "backup");
910 for (argc--, argv++; argc; argc--, argv++) {
911 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
912 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
913 }
914
915 D("backup. filename=%s buf=%s\n", filename, buf);
916 fd = adb_connect(buf);
917 if (fd < 0) {
918 fprintf(stderr, "adb: unable to connect for backup\n");
919 adb_close(outFd);
920 return -1;
921 }
922
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800923 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700924 copy_to_file(fd, outFd);
925
926 adb_close(fd);
927 adb_close(outFd);
928 return 0;
929}
930
Dan Albertbac34742015-02-25 17:51:28 -0800931static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700932 const char* filename;
933 int fd, tarFd;
934
935 if (argc != 2) return usage();
936
937 filename = argv[1];
938 tarFd = adb_open(filename, O_RDONLY);
939 if (tarFd < 0) {
940 fprintf(stderr, "adb: unable to open file %s\n", filename);
941 return -1;
942 }
943
944 fd = adb_connect("restore:");
945 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700946 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700947 adb_close(tarFd);
948 return -1;
949 }
950
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800951 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700952 copy_to_file(tarFd, fd);
953
954 adb_close(fd);
955 adb_close(tarFd);
956 return 0;
957}
958
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800959#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
960static int top_works(const char *top)
961{
962 if (top != NULL && adb_is_absolute_host_path(top)) {
963 char path_buf[PATH_MAX];
964 snprintf(path_buf, sizeof(path_buf),
965 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
966 return access(path_buf, F_OK) == 0;
967 }
968 return 0;
969}
970
971static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
972{
973 strcpy(path_buf, indir);
974 while (1) {
975 if (top_works(path_buf)) {
976 return path_buf;
977 }
978 char *s = adb_dirstop(path_buf);
979 if (s != NULL) {
980 *s = '\0';
981 } else {
982 path_buf[0] = '\0';
983 return NULL;
984 }
985 }
986}
987
988static char *find_top(char path_buf[PATH_MAX])
989{
990 char *top = getenv("ANDROID_BUILD_TOP");
991 if (top != NULL && top[0] != '\0') {
992 if (!top_works(top)) {
993 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
994 return NULL;
995 }
996 } else {
997 top = getenv("TOP");
998 if (top != NULL && top[0] != '\0') {
999 if (!top_works(top)) {
1000 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1001 return NULL;
1002 }
1003 } else {
1004 top = NULL;
1005 }
1006 }
1007
1008 if (top != NULL) {
1009 /* The environment pointed to a top directory that works.
1010 */
1011 strcpy(path_buf, top);
1012 return path_buf;
1013 }
1014
1015 /* The environment didn't help. Walk up the tree from the CWD
1016 * to see if we can find the top.
1017 */
1018 char dir[PATH_MAX];
1019 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1020 if (top == NULL) {
1021 /* If the CWD isn't under a good-looking top, see if the
1022 * executable is.
1023 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001024 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001025 top = find_top_from(dir, path_buf);
1026 }
1027 return top;
1028}
1029
1030/* <hint> may be:
1031 * - A simple product name
1032 * e.g., "sooner"
1033TODO: debug? sooner-debug, sooner:debug?
1034 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1035 * e.g., "out/target/product/sooner"
1036 * - An absolute path to the PRODUCT_OUT dir
1037 * e.g., "/src/device/out/target/product/sooner"
1038 *
1039 * Given <hint>, try to construct an absolute path to the
1040 * ANDROID_PRODUCT_OUT dir.
1041 */
1042static const char *find_product_out_path(const char *hint)
1043{
1044 static char path_buf[PATH_MAX];
1045
1046 if (hint == NULL || hint[0] == '\0') {
1047 return NULL;
1048 }
1049
1050 /* If it's already absolute, don't bother doing any work.
1051 */
1052 if (adb_is_absolute_host_path(hint)) {
1053 strcpy(path_buf, hint);
1054 return path_buf;
1055 }
1056
1057 /* If there are any slashes in it, assume it's a relative path;
1058 * make it absolute.
1059 */
1060 if (adb_dirstart(hint) != NULL) {
1061 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1062 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1063 return NULL;
1064 }
1065 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1066 fprintf(stderr, "adb: Couldn't assemble path\n");
1067 return NULL;
1068 }
1069 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1070 strcat(path_buf, hint);
1071 return path_buf;
1072 }
1073
1074 /* It's a string without any slashes. Try to do something with it.
1075 *
1076 * Try to find the root of the build tree, and build a PRODUCT_OUT
1077 * path from there.
1078 */
1079 char top_buf[PATH_MAX];
1080 const char *top = find_top(top_buf);
1081 if (top == NULL) {
1082 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1083 return NULL;
1084 }
1085//TODO: if we have a way to indicate debug, look in out/debug/target/...
1086 snprintf(path_buf, sizeof(path_buf),
1087 "%s" OS_PATH_SEPARATOR_STR
1088 "out" OS_PATH_SEPARATOR_STR
1089 "target" OS_PATH_SEPARATOR_STR
1090 "product" OS_PATH_SEPARATOR_STR
1091 "%s", top_buf, hint);
1092 if (access(path_buf, F_OK) < 0) {
1093 fprintf(stderr, "adb: Couldn't find a product dir "
1094 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1095 return NULL;
1096 }
1097 return path_buf;
1098}
1099
Dan Albertbac34742015-02-25 17:51:28 -08001100static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1101 char const **path2, int *show_progress,
1102 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001103 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001104 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001105
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001106 while (narg > 0) {
1107 if (!strcmp(*arg, "-p")) {
1108 *show_progress = 1;
1109 } else if (!strcmp(*arg, "-a")) {
1110 *copy_attrs = 1;
1111 } else {
1112 break;
1113 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001114 ++arg;
1115 --narg;
1116 }
1117
1118 if (narg > 0) {
1119 *path1 = *arg;
1120 ++arg;
1121 --narg;
1122 }
1123
1124 if (narg > 0) {
1125 *path2 = *arg;
1126 }
1127}
1128
Tao Bao175b7bb2015-03-29 11:22:34 -07001129static int adb_connect_command(const char* command) {
1130 int fd = adb_connect(command);
1131 if (fd != -1) {
1132 read_and_dump(fd);
1133 adb_close(fd);
1134 return 0;
1135 }
1136 fprintf(stderr, "Error: %s\n", adb_error());
1137 return 1;
1138}
1139
Dan Albertbac34742015-02-25 17:51:28 -08001140int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001141{
1142 char buf[4096];
1143 int no_daemon = 0;
1144 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001145 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001146 int persist = 0;
1147 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001149 const char* serial = NULL;
1150 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001151
1152 /* If defined, this should be an absolute path to
1153 * the directory containing all of the various system images
1154 * for a particular product. If not defined, and the adb
1155 * command requires this information, then the user must
1156 * specify the path using "-p".
1157 */
1158 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1159 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1160 gProductOutPath = NULL;
1161 }
1162 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1163
Nick Pellydb449262009-05-07 12:48:03 -07001164 serial = getenv("ANDROID_SERIAL");
1165
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001166 /* Validate and assign the server port */
1167 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1168 int server_port = DEFAULT_ADB_PORT;
1169 if (server_port_str && strlen(server_port_str) > 0) {
1170 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001171 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001172 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001173 "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 +01001174 server_port_str);
1175 return usage();
1176 }
1177 }
1178
1179 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001180 while (argc > 0) {
1181 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001182 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001183 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001184 no_daemon = 1;
1185 } else if (!strcmp(argv[0], "fork-server")) {
1186 /* this is a special flag used only when the ADB client launches the ADB Server */
1187 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001188 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001190 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191 const char *product = NULL;
1192 if (argv[0][2] == '\0') {
1193 if (argc < 2) return usage();
1194 product = argv[1];
1195 argc--;
1196 argv++;
1197 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001198 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001199 }
1200 gProductOutPath = find_product_out_path(product);
1201 if (gProductOutPath == NULL) {
1202 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1203 product);
1204 return usage();
1205 }
1206 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1207 if (isdigit(argv[0][2])) {
1208 serial = argv[0] + 2;
1209 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001210 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001211 serial = argv[1];
1212 argc--;
1213 argv++;
1214 }
1215 } else if (!strcmp(argv[0],"-d")) {
1216 ttype = kTransportUsb;
1217 } else if (!strcmp(argv[0],"-e")) {
1218 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001219 } else if (!strcmp(argv[0],"-a")) {
1220 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001221 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001222 const char *hostname = NULL;
1223 if (argv[0][2] == '\0') {
1224 if (argc < 2) return usage();
1225 hostname = argv[1];
1226 argc--;
1227 argv++;
1228 } else {
1229 hostname = argv[0] + 2;
1230 }
1231 adb_set_tcp_name(hostname);
1232
Riley Andrews98f58e82014-12-05 17:37:24 -08001233 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001234 if (argv[0][2] == '\0') {
1235 if (argc < 2) return usage();
1236 server_port_str = argv[1];
1237 argc--;
1238 argv++;
1239 } else {
1240 server_port_str = argv[0] + 2;
1241 }
1242 if (strlen(server_port_str) > 0) {
1243 server_port = (int) strtol(server_port_str, NULL, 0);
1244 if (server_port <= 0 || server_port > 65535) {
1245 fprintf(stderr,
1246 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1247 server_port_str);
1248 return usage();
1249 }
1250 } else {
1251 fprintf(stderr,
1252 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1253 return usage();
1254 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001255 } else {
1256 /* out of recognized modifiers and flags */
1257 break;
1258 }
1259 argc--;
1260 argv++;
1261 }
1262
1263 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001264 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001265
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001266 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001267 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001268 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001269 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001270 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001271 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001272 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001273 fprintf(stderr,"* could not start server *\n");
1274 }
1275 return r;
1276 }
1277
Riley Andrews98f58e82014-12-05 17:37:24 -08001278 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001279 return usage();
1280 }
1281
Riley Andrewsc8514c82014-12-05 17:32:46 -08001282 /* handle wait-for-* prefix */
1283 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001284 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001285 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1286 if (ttype == kTransportUsb) {
1287 service = "wait-for-usb";
1288 } else if (ttype == kTransportLocal) {
1289 service = "wait-for-local";
1290 } else {
1291 service = "wait-for-any";
1292 }
1293 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001294
Riley Andrewsc8514c82014-12-05 17:32:46 -08001295 format_host_command(buf, sizeof buf, service, ttype, serial);
1296
1297 if (adb_command(buf)) {
1298 D("failure: %s *\n",adb_error());
1299 fprintf(stderr,"error: %s\n", adb_error());
1300 return 1;
1301 }
1302
1303 /* Allow a command to be run after wait-for-device,
1304 * e.g. 'adb wait-for-device shell'.
1305 */
1306 if (argc == 1) {
1307 return 0;
1308 }
1309
1310 /* Fall through */
1311 argc--;
1312 argv++;
1313 }
1314
1315 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001316 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001317 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001318 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001319 if (argc < 2)
1320 listopt = "";
1321 else if (argc == 2 && !strcmp(argv[1], "-l"))
1322 listopt = argv[1];
1323 else {
1324 fprintf(stderr, "Usage: adb devices [-l]\n");
1325 return 1;
1326 }
1327 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001328 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001329 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 printf("List of devices attached \n");
1331 printf("%s\n", tmp);
1332 return 0;
1333 } else {
1334 return 1;
1335 }
1336 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001337 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001338 char *tmp;
1339 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001340 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001341 return 1;
1342 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001343 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1344 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001345 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001346 printf("%s\n", tmp);
1347 return 0;
1348 } else {
1349 return 1;
1350 }
1351 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001352 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001353 char *tmp;
1354 if (argc > 2) {
1355 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1356 return 1;
1357 }
1358 if (argc == 2) {
1359 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1360 } else {
1361 snprintf(buf, sizeof buf, "host:disconnect:");
1362 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001363 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001364 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001365 printf("%s\n", tmp);
1366 return 0;
1367 } else {
1368 return 1;
1369 }
1370 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001371 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001372 return adb_send_emulator_command(argc, argv);
1373 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001374 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001375 int r;
1376 int fd;
1377
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001378 char h = (argv[0][0] == 'h');
1379
1380 if (h) {
1381 printf("\x1b[41;33m");
1382 fflush(stdout);
1383 }
1384
Riley Andrews98f58e82014-12-05 17:37:24 -08001385 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001386 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001387 r = interactive_shell();
1388 if (h) {
1389 printf("\x1b[0m");
1390 fflush(stdout);
1391 }
1392 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001393 }
1394
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001395 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 argc -= 2;
1397 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001398 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001399 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001400 strncat(buf, " ", sizeof(buf) - 1);
1401 strncat(buf, quoted, sizeof(buf) - 1);
1402 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 }
1404
1405 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001406 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001407 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001408 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001409 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001411 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001412 adb_close(fd);
1413 r = 0;
1414 } else {
1415 fprintf(stderr,"error: %s\n", adb_error());
1416 r = -1;
1417 }
1418
Riley Andrews98f58e82014-12-05 17:37:24 -08001419 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001420 fprintf(stderr,"\n- waiting for device -\n");
1421 adb_sleep_ms(1000);
1422 do_cmd(ttype, serial, "wait-for-device", 0);
1423 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001424 if (h) {
1425 printf("\x1b[0m");
1426 fflush(stdout);
1427 }
JP Abgrall408fa572011-03-16 15:57:42 -07001428 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001429 return r;
1430 }
1431 }
1432 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001433 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001434 int exec_in = !strcmp(argv[0], "exec-in");
1435 int fd;
1436
1437 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1438 argc -= 2;
1439 argv += 2;
1440 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001441 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001442 strncat(buf, " ", sizeof(buf) - 1);
1443 strncat(buf, quoted, sizeof(buf) - 1);
1444 free(quoted);
1445 }
1446
1447 fd = adb_connect(buf);
1448 if (fd < 0) {
1449 fprintf(stderr, "error: %s\n", adb_error());
1450 return -1;
1451 }
1452
1453 if (exec_in) {
1454 copy_to_file(STDIN_FILENO, fd);
1455 } else {
1456 copy_to_file(fd, STDOUT_FILENO);
1457 }
1458
1459 adb_close(fd);
1460 return 0;
1461 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001462 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001463 int fd;
1464 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001465 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001466 fprintf(stderr,"* server not running *\n");
1467 return 1;
1468 }
1469 return 0;
1470 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001471 else if (!strcmp(argv[0], "sideload")) {
1472 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001473 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001474 return 1;
1475 } else {
1476 return 0;
1477 }
1478 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001479 else if (!strcmp(argv[0], "remount") ||
1480 !strcmp(argv[0], "reboot") ||
1481 !strcmp(argv[0], "reboot-bootloader") ||
1482 !strcmp(argv[0], "tcpip") ||
1483 !strcmp(argv[0], "usb") ||
1484 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001485 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001486 !strcmp(argv[0], "disable-verity") ||
1487 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001488 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001489 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001490 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001491 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001492 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001493 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001494 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001495 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001496 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001497 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001498 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001499 if (argc != 1) return usage();
1500 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001501 return 0;
1502 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001504 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001505 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001506 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001507 char remove = 0;
1508 char remove_all = 0;
1509 char list = 0;
1510 char no_rebind = 0;
1511
1512 // Parse options here.
1513 while (argc > 1 && argv[1][0] == '-') {
1514 if (!strcmp(argv[1], "--list"))
1515 list = 1;
1516 else if (!strcmp(argv[1], "--remove"))
1517 remove = 1;
1518 else if (!strcmp(argv[1], "--remove-all"))
1519 remove_all = 1;
1520 else if (!strcmp(argv[1], "--no-rebind"))
1521 no_rebind = 1;
1522 else {
1523 return usage();
1524 }
1525 argc--;
1526 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001527 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001528
1529 // Ensure we can only use one option at a time.
1530 if (list + remove + remove_all + no_rebind > 1) {
1531 return usage();
1532 }
1533
1534 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001535 if (reverse) {
1536 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001537 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001538 if (serial) {
1539 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1540 serial);
1541 } else if (ttype == kTransportUsb) {
1542 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1543 } else if (ttype == kTransportLocal) {
1544 snprintf(host_prefix, sizeof host_prefix, "host-local");
1545 } else {
1546 snprintf(host_prefix, sizeof host_prefix, "host");
1547 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001548 }
1549
1550 // Implement forward --list
1551 if (list) {
1552 if (argc != 1)
1553 return usage();
1554 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1555 char* forwards = adb_query(buf);
1556 if (forwards == NULL) {
1557 fprintf(stderr, "error: %s\n", adb_error());
1558 return 1;
1559 }
1560 printf("%s", forwards);
1561 free(forwards);
1562 return 0;
1563 }
1564
1565 // Implement forward --remove-all
1566 else if (remove_all) {
1567 if (argc != 1)
1568 return usage();
1569 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1570 }
1571
1572 // Implement forward --remove <local>
1573 else if (remove) {
1574 if (argc != 2)
1575 return usage();
1576 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1577 }
1578 // Or implement one of:
1579 // forward <local> <remote>
1580 // forward --no-rebind <local> <remote>
1581 else
1582 {
1583 if (argc != 3)
1584 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001585 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001586 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1587 }
1588
Riley Andrews98f58e82014-12-05 17:37:24 -08001589 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001590 fprintf(stderr,"error: %s\n", adb_error());
1591 return 1;
1592 }
1593 return 0;
1594 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001595 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001596 else if (!strcmp(argv[0], "ls")) {
1597 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001598 return do_sync_ls(argv[1]);
1599 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001600 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001601 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001602 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001603 const char* lpath = NULL, *rpath = NULL;
1604
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001605 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001606
1607 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001608 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001609 }
1610
1611 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001612 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001613 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001614 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001615 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001616 const char* rpath = NULL, *lpath = ".";
1617
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001618 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001619
1620 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001621 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001622 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001623
1624 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001626 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001627 if (argc < 2) return usage();
1628 return install_app(ttype, serial, argc, argv);
1629 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001630 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001631 if (argc < 2) return usage();
1632 return install_multiple_app(ttype, serial, argc, argv);
1633 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001634 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001635 if (argc < 2) return usage();
1636 return uninstall_app(ttype, serial, argc, argv);
1637 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001638 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001639 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001640 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1641
Anthony Newnam705c9442010-02-22 08:36:49 -06001642 int listonly = 0;
1643
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001644 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001645 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001646 /* No local path was specified. */
1647 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001648 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1649 listonly = 1;
1650 if (argc == 3) {
1651 srcarg = argv[2];
1652 } else {
1653 srcarg = NULL;
1654 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001655 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001656 /* A local path or "android"/"data" arg was specified. */
1657 srcarg = argv[1];
1658 } else {
1659 return usage();
1660 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001661 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1662 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001663 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001664
Elliott Hughesec7a6672015-03-16 21:58:32 +00001665 if (system_srcpath != NULL)
1666 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001667 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001668 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001669 if(ret == 0 && oem_srcpath != NULL)
1670 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001671 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001672 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001673
Elliott Hughesec7a6672015-03-16 21:58:32 +00001674 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001675 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001676 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001677 free(data_srcpath);
1678 return ret;
1679 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001681 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001682 !strcmp(argv[0],"get-serialno") ||
1683 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001684 {
1685 char *tmp;
1686
1687 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1688 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001689 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 printf("%s\n", tmp);
1691 return 0;
1692 } else {
1693 return 1;
1694 }
1695 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001696 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001697 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001698 status_window(ttype, serial);
1699 return 0;
1700 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001701 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001702 return logcat(ttype, serial, argc, argv);
1703 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001704 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001705 return ppp(argc, argv);
1706 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001707 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001708 return adb_connect("host:start-server");
1709 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001710 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001711 return backup(argc, argv);
1712 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001713 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001714 return restore(argc, argv);
1715 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001716 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001717 if (argc < 2) return usage();
1718 return adb_auth_keygen(argv[1]);
1719 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001720 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001721 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001722 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001723 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001724 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001725 help();
1726 return 0;
1727 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001728 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001729 version(stdout);
1730 return 0;
1731 }
1732
1733 usage();
1734 return 1;
1735}
1736
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001737#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001738static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001739{
Dan Albertbac34742015-02-25 17:51:28 -08001740 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001741 int argc;
1742 va_list ap;
1743
1744 va_start(ap, cmd);
1745 argc = 0;
1746
1747 if (serial) {
1748 argv[argc++] = "-s";
1749 argv[argc++] = serial;
1750 } else if (ttype == kTransportUsb) {
1751 argv[argc++] = "-d";
1752 } else if (ttype == kTransportLocal) {
1753 argv[argc++] = "-e";
1754 }
1755
1756 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001757 while(argc < MAX_ARGV_LENGTH &&
1758 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1759 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001760 va_end(ap);
1761
1762#if 0
1763 int n;
1764 fprintf(stderr,"argc = %d\n",argc);
1765 for(n = 0; n < argc; n++) {
1766 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1767 }
1768#endif
1769
1770 return adb_commandline(argc, argv);
1771}
1772
1773int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001774 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1775 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001776{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001777 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001778 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001779
1780 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001781 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001782 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001783 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001784 oem_srcdir = product_file("oem");
1785 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001786 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1787 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001788 // Check if oem partition exists.
1789 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1790 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001791 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001792 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1793 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001794 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001795 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001796 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001797 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001798 } else if(strcmp(srcarg, "vendor") == 0) {
1799 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001800 } else if(strcmp(srcarg, "oem") == 0) {
1801 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001803 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001804 return 1;
1805 }
1806 }
1807
Elliott Hughesec7a6672015-03-16 21:58:32 +00001808 if(system_srcdir_out != NULL)
1809 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001810 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001811 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001812
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001813 if(vendor_srcdir_out != NULL)
1814 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001816 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001817
Elliott Hughesec7a6672015-03-16 21:58:32 +00001818 if(oem_srcdir_out != NULL)
1819 *oem_srcdir_out = oem_srcdir;
1820 else
1821 free(oem_srcdir);
1822
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001823 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001824 *data_srcdir_out = data_srcdir;
1825 else
1826 free(data_srcdir);
1827
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001828 return 0;
1829}
1830
Dan Albertbac34742015-02-25 17:51:28 -08001831static int pm_command(transport_type transport, const char* serial,
1832 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001833{
1834 char buf[4096];
1835
1836 snprintf(buf, sizeof(buf), "shell:pm");
1837
1838 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001839 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001840 strncat(buf, " ", sizeof(buf) - 1);
1841 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001842 free(quoted);
1843 }
1844
1845 send_shellcommand(transport, serial, buf);
1846 return 0;
1847}
1848
Dan Albertbac34742015-02-25 17:51:28 -08001849int uninstall_app(transport_type transport, const char* serial, int argc,
1850 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001851{
1852 /* if the user choose the -k option, we refuse to do it until devices are
1853 out with the option to uninstall the remaining data somehow (adb/ui) */
1854 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1855 {
1856 printf(
1857 "The -k option uninstalls the application while retaining the data/cache.\n"
1858 "At the moment, there is no way to remove the remaining data.\n"
1859 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1860 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1861 return -1;
1862 }
1863
1864 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1865 return pm_command(transport, serial, argc, argv);
1866}
1867
Dan Albertbac34742015-02-25 17:51:28 -08001868static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001869{
1870 char buf[4096];
1871 char* quoted;
1872
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001873 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001874 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001875 strncat(buf, quoted, sizeof(buf)-1);
1876 free(quoted);
1877
1878 send_shellcommand(transport, serial, buf);
1879 return 0;
1880}
1881
Kenny Root597ea5b2011-08-05 11:19:45 -07001882static const char* get_basename(const char* filename)
1883{
1884 const char* basename = adb_dirstop(filename);
1885 if (basename) {
1886 basename++;
1887 return basename;
1888 } else {
1889 return filename;
1890 }
1891}
1892
Dan Albertbac34742015-02-25 17:51:28 -08001893int install_app(transport_type transport, const char* serial, int argc,
1894 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001895{
1896 static const char *const DATA_DEST = "/data/local/tmp/%s";
1897 static const char *const SD_DEST = "/sdcard/tmp/%s";
1898 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001899 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001900 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001901
1902 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001903 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001904 where = SD_DEST;
1905 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001906 }
1907
Jeff Sharkey960df972014-06-09 17:30:57 -07001908 // Find last APK argument.
1909 // All other arguments passed through verbatim.
1910 int last_apk = -1;
1911 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001912 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001913 char* dot = strrchr(file, '.');
1914 if (dot && !strcasecmp(dot, ".apk")) {
1915 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1916 fprintf(stderr, "Invalid APK file: %s\n", file);
1917 return -1;
1918 }
1919
1920 last_apk = i;
1921 break;
1922 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001923 }
1924
Jeff Sharkey960df972014-06-09 17:30:57 -07001925 if (last_apk == -1) {
1926 fprintf(stderr, "Missing APK file\n");
1927 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001928 }
1929
Dan Albertbac34742015-02-25 17:51:28 -08001930 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001931 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001932 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001933 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001934 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001935 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001937 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001938 }
1939
1940 pm_command(transport, serial, argc, argv);
1941
Kenny Root60733e92012-03-26 16:14:02 -07001942cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001943 delete_file(transport, serial, apk_dest);
1944 return err;
1945}
1946
Dan Albertbac34742015-02-25 17:51:28 -08001947int install_multiple_app(transport_type transport, const char* serial, int argc,
1948 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001949{
1950 char buf[1024];
1951 int i;
1952 struct stat sb;
1953 unsigned long long total_size = 0;
1954
1955 // Find all APK arguments starting at end.
1956 // All other arguments passed through verbatim.
1957 int first_apk = -1;
1958 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001959 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001960 char* dot = strrchr(file, '.');
1961 if (dot && !strcasecmp(dot, ".apk")) {
1962 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1963 fprintf(stderr, "Invalid APK file: %s\n", file);
1964 return -1;
1965 }
1966
1967 total_size += sb.st_size;
1968 first_apk = i;
1969 } else {
1970 break;
1971 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001972 }
1973
Jeff Sharkey960df972014-06-09 17:30:57 -07001974 if (first_apk == -1) {
1975 fprintf(stderr, "Missing APK file\n");
1976 return 1;
1977 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001978
Jeff Sharkey960df972014-06-09 17:30:57 -07001979 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1980 for (i = 1; i < first_apk; i++) {
1981 char *quoted = escape_arg(argv[i]);
1982 strncat(buf, " ", sizeof(buf) - 1);
1983 strncat(buf, quoted, sizeof(buf) - 1);
1984 free(quoted);
1985 }
1986
1987 // Create install session
1988 int fd = adb_connect(buf);
1989 if (fd < 0) {
1990 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1991 return -1;
1992 }
1993 read_status_line(fd, buf, sizeof(buf));
1994 adb_close(fd);
1995
1996 int session_id = -1;
1997 if (!strncmp("Success", buf, 7)) {
1998 char* start = strrchr(buf, '[');
1999 char* end = strrchr(buf, ']');
2000 if (start && end) {
2001 *end = '\0';
2002 session_id = strtol(start + 1, NULL, 10);
2003 }
2004 }
2005 if (session_id < 0) {
2006 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002007 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002008 return -1;
2009 }
2010
2011 // Valid session, now stream the APKs
2012 int success = 1;
2013 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002014 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002015 if (stat(file, &sb) == -1) {
2016 fprintf(stderr, "Failed to stat %s\n", file);
2017 success = 0;
2018 goto finalize_session;
2019 }
2020
2021 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002022 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002023
2024 int localFd = adb_open(file, O_RDONLY);
2025 if (localFd < 0) {
2026 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2027 success = 0;
2028 goto finalize_session;
2029 }
2030
2031 int remoteFd = adb_connect(buf);
2032 if (remoteFd < 0) {
2033 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2034 adb_close(localFd);
2035 success = 0;
2036 goto finalize_session;
2037 }
2038
2039 copy_to_file(localFd, remoteFd);
2040 read_status_line(remoteFd, buf, sizeof(buf));
2041
2042 adb_close(localFd);
2043 adb_close(remoteFd);
2044
2045 if (strncmp("Success", buf, 7)) {
2046 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002047 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002048 success = 0;
2049 goto finalize_session;
2050 }
2051 }
2052
2053finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002054 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002055 if (success) {
2056 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2057 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002058 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002059 }
2060
2061 fd = adb_connect(buf);
2062 if (fd < 0) {
2063 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2064 return -1;
2065 }
2066 read_status_line(fd, buf, sizeof(buf));
2067 adb_close(fd);
2068
2069 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002070 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002071 return 0;
2072 } else {
2073 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002074 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002075 return -1;
2076 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002077}