blob: 19a2fee87c65925ea4820be17566394c18a3c983 [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
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700252// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800253void stdin_raw_init(int fd);
254void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800255
256#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100257static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100259static void stdin_raw_init(int fd) {
260 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100262 termios tio;
263 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800264
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100265 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100267 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800268 tio.c_cc[VTIME] = 0;
269 tio.c_cc[VMIN] = 1;
270
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100271 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272}
273
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100274static void stdin_raw_restore(int fd) {
275 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276}
277#endif
278
279static void read_and_dump(int fd)
280{
281 char buf[4096];
282 int len;
283
284 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700285 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800286 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700287 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 if(len == 0) {
289 break;
290 }
291
292 if(len < 0) {
293 if(errno == EINTR) continue;
294 break;
295 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400296 fwrite(buf, 1, len, stdout);
297 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800298 }
299}
300
Jeff Sharkey960df972014-06-09 17:30:57 -0700301static void read_status_line(int fd, char* buf, size_t count)
302{
303 count--;
304 while (count > 0) {
305 int len = adb_read(fd, buf, count);
306 if (len == 0) {
307 break;
308 } else if (len < 0) {
309 if (errno == EINTR) continue;
310 break;
311 }
312
313 buf += len;
314 count -= len;
315 }
316 *buf = '\0';
317}
318
Christopher Tated2f54152011-04-21 12:53:28 -0700319static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700320 const size_t BUFSIZE = 32 * 1024;
321 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700322 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700323 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700324
325 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800326
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700327 if (inFd == STDIN_FILENO) {
328 stdin_raw_init(STDIN_FILENO);
329 }
Yabin Cuid325e862014-11-17 14:48:25 -0800330
Christopher Tated2f54152011-04-21 12:53:28 -0700331 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700332 if (inFd == STDIN_FILENO) {
333 len = unix_read(inFd, buf, BUFSIZE);
334 } else {
335 len = adb_read(inFd, buf, BUFSIZE);
336 }
Christopher Tated2f54152011-04-21 12:53:28 -0700337 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700338 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700339 break;
340 }
341 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700342 if (errno == EINTR) {
343 D("copy_to_file() : EINTR, retrying\n");
344 continue;
345 }
Christopher Tated2f54152011-04-21 12:53:28 -0700346 D("copy_to_file() : error %d\n", errno);
347 break;
348 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700349 if (outFd == STDOUT_FILENO) {
350 fwrite(buf, 1, len, stdout);
351 fflush(stdout);
352 } else {
353 adb_write(outFd, buf, len);
354 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700355 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700356 }
Yabin Cuid325e862014-11-17 14:48:25 -0800357
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700358 if (inFd == STDIN_FILENO) {
359 stdin_raw_restore(STDIN_FILENO);
360 }
Yabin Cuid325e862014-11-17 14:48:25 -0800361
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700362 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700363 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700364}
365
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800366static void *stdin_read_thread(void *x)
367{
368 int fd, fdi;
369 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370 int r, n;
371 int state = 0;
372
373 int *fds = (int*) x;
374 fd = fds[0];
375 fdi = fds[1];
376 free(fds);
377
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800378 for(;;) {
379 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700380 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800381 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700382 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 if(r == 0) break;
384 if(r < 0) {
385 if(errno == EINTR) continue;
386 break;
387 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400388 for(n = 0; n < r; n++){
389 switch(buf[n]) {
390 case '\n':
391 state = 1;
392 break;
393 case '\r':
394 state = 1;
395 break;
396 case '~':
397 if(state == 1) state++;
398 break;
399 case '.':
400 if(state == 2) {
401 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400402 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400403 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800404 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400405 default:
406 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 r = adb_write(fd, buf, r);
410 if(r <= 0) {
411 break;
412 }
413 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800414 return 0;
415}
416
417int interactive_shell(void)
418{
419 adb_thread_t thr;
420 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800421
422 fd = adb_connect("shell:");
423 if(fd < 0) {
424 fprintf(stderr,"error: %s\n", adb_error());
425 return 1;
426 }
427 fdi = 0; //dup(0);
428
Dan Albertbac34742015-02-25 17:51:28 -0800429 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430 fds[0] = fd;
431 fds[1] = fdi;
432
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800433 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434 adb_thread_create(&thr, stdin_read_thread, fds);
435 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 return 0;
438}
439
440
441static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
442{
443 if (serial) {
444 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
445 } else {
446 const char* prefix = "host";
447 if (ttype == kTransportUsb)
448 prefix = "host-usb";
449 else if (ttype == kTransportLocal)
450 prefix = "host-local";
451
452 snprintf(buffer, buflen, "%s:%s", prefix, command);
453 }
454}
455
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100456int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800457 unsigned progress)
458{
459 char buf[4096];
460 unsigned total;
461 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800462
463 sprintf(buf,"%s:%d", service, sz);
464 fd = adb_connect(buf);
465 if(fd < 0) {
466 fprintf(stderr,"error: %s\n", adb_error());
467 return -1;
468 }
469
470 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800471 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800472
473 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800474 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800475
476 if(progress) {
477 char *x = strrchr(service, ':');
478 if(x) service = x + 1;
479 }
480
481 while(sz > 0) {
482 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800483 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800484 adb_status(fd);
485 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
486 return -1;
487 }
488 sz -= xfer;
489 ptr += xfer;
490 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100491 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800492 fflush(stdout);
493 }
494 }
495 if(progress) {
496 printf("\n");
497 }
498
Dan Albertcc731cc2015-02-24 21:26:58 -0800499 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800500 fprintf(stderr,"* error reading response *\n");
501 adb_close(fd);
502 return -1;
503 }
504 if(memcmp(buf, "OKAY", 4)) {
505 buf[4] = 0;
506 fprintf(stderr,"* error response '%s' *\n", buf);
507 adb_close(fd);
508 return -1;
509 }
510
511 adb_close(fd);
512 return 0;
513}
514
515
516int adb_download(const char *service, const char *fn, unsigned progress)
517{
518 void *data;
519 unsigned sz;
520
521 data = load_file(fn, &sz);
522 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100523 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800524 return -1;
525 }
526
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100527 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800528 free(data);
529 return status;
530}
531
Doug Zongker71fe5842014-06-26 15:35:36 -0700532#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
533
534/*
535 * The sideload-host protocol serves the data in a file (given on the
536 * command line) to the client, using a simple protocol:
537 *
538 * - The connect message includes the total number of bytes in the
539 * file and a block size chosen by us.
540 *
541 * - The other side sends the desired block number as eight decimal
542 * digits (eg "00000023" for block 23). Blocks are numbered from
543 * zero.
544 *
545 * - We send back the data of the requested block. The last block is
546 * likely to be partial; when the last block is requested we only
547 * send the part of the block that exists, it's not padded up to the
548 * block size.
549 *
550 * - When the other side sends "DONEDONE" instead of a block number,
551 * we hang up.
552 */
553int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700554 unsigned sz;
555 size_t xfer = 0;
556 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800557 int last_percent = -1;
558 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700559
560 printf("loading: '%s'", fn);
561 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800562 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700563 if (data == 0) {
564 printf("\n");
565 fprintf(stderr, "* cannot read '%s' *\n", fn);
566 return -1;
567 }
568
569 char buf[100];
570 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
571 int fd = adb_connect(buf);
572 if (fd < 0) {
573 // Try falling back to the older sideload method. Maybe this
574 // is an older device that doesn't support sideload-host.
575 printf("\n");
576 status = adb_download_buffer("sideload", fn, data, sz, 1);
577 goto done;
578 }
579
Spencer Lowf055c192015-01-25 14:40:16 -0800580 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700581
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700582 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800583 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700584 fprintf(stderr, "* failed to read command: %s\n", adb_error());
585 status = -1;
586 goto done;
587 }
588
589 if (strncmp("DONEDONE", buf, 8) == 0) {
590 status = 0;
591 break;
592 }
593
594 buf[8] = '\0';
595 int block = strtol(buf, NULL, 10);
596
597 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
598 if (offset >= sz) {
599 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
600 status = -1;
601 goto done;
602 }
603 uint8_t* start = data + offset;
604 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
605 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
606 if (offset_end > sz) {
607 to_write = sz - offset;
608 }
609
Dan Albertcc731cc2015-02-24 21:26:58 -0800610 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700611 adb_status(fd);
612 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
613 status = -1;
614 goto done;
615 }
616 xfer += to_write;
617
618 // For normal OTA packages, we expect to transfer every byte
619 // twice, plus a bit of overhead (one read during
620 // verification, one read of each byte for installation, plus
621 // extra access to things like the zip central directory).
622 // This estimate of the completion becomes 100% when we've
623 // transferred ~2.13 (=100/47) times the package size.
624 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
625 if (percent != last_percent) {
626 printf("\rserving: '%s' (~%d%%) ", fn, percent);
627 fflush(stdout);
628 last_percent = percent;
629 }
630 }
631
Colin Cross6d6a8982014-07-07 14:12:41 -0700632 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700633
634 done:
635 if (fd >= 0) adb_close(fd);
636 free(data);
637 return status;
638}
639
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800640static void status_window(transport_type ttype, const char* serial)
641{
642 char command[4096];
643 char *state = 0;
644 char *laststate = 0;
645
646 /* silence stderr */
647#ifdef _WIN32
648 /* XXX: TODO */
649#else
650 int fd;
651 fd = unix_open("/dev/null", O_WRONLY);
652 dup2(fd, 2);
653 adb_close(fd);
654#endif
655
656 format_host_command(command, sizeof command, "get-state", ttype, serial);
657
658 for(;;) {
659 adb_sleep_ms(250);
660
661 if(state) {
662 free(state);
663 state = 0;
664 }
665
666 state = adb_query(command);
667
668 if(state) {
669 if(laststate && !strcmp(state,laststate)){
670 continue;
671 } else {
672 if(laststate) free(laststate);
673 laststate = strdup(state);
674 }
675 }
676
677 printf("%c[2J%c[2H", 27, 27);
678 printf("Android Debug Bridge\n");
679 printf("State: %s\n", state ? state : "offline");
680 fflush(stdout);
681 }
682}
683
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700684static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700685{
686 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
687}
688
689/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700690static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800691{
692 const char *ts;
693 size_t alloc_len;
694 char *ret;
695 char *dest;
696
Jeff Sharkey7c460352014-06-10 16:22:17 -0700697 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700698 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800699 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700700 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 alloc_len++;
702 }
703 }
704
Jeff Sharkey7c460352014-06-10 16:22:17 -0700705 if (alloc_len == 0) {
706 // Preserve empty arguments
707 ret = (char *) malloc(3);
708 ret[0] = '\"';
709 ret[1] = '\"';
710 ret[2] = '\0';
711 return ret;
712 }
713
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700714 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715 dest = ret;
716
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700717 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700718 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800719 *dest++ = '\\';
720 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 *dest++ = *ts;
722 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800723 *dest++ = '\0';
724
725 return ret;
726}
727
728/**
729 * Run ppp in "notty" mode against a resource listed as the first parameter
730 * eg:
731 *
732 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
733 *
734 */
Dan Albertbac34742015-02-25 17:51:28 -0800735int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800736{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800737#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800738 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
739 return -1;
740#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800741 pid_t pid;
742 int fd;
743
744 if (argc < 2) {
745 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
746 argv[0]);
747
748 return 1;
749 }
750
Dan Albertbac34742015-02-25 17:51:28 -0800751 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800752 fd = adb_connect(adb_service_name);
753
754 if(fd < 0) {
755 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
756 adb_service_name, adb_error());
757 return 1;
758 }
759
760 pid = fork();
761
762 if (pid < 0) {
763 perror("from fork()");
764 return 1;
765 } else if (pid == 0) {
766 int err;
767 int i;
768 const char **ppp_args;
769
770 // copy args
771 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
772 ppp_args[0] = "pppd";
773 for (i = 2 ; i < argc ; i++) {
774 //argv[2] and beyond become ppp_args[1] and beyond
775 ppp_args[i - 1] = argv[i];
776 }
777 ppp_args[i-1] = NULL;
778
779 // child side
780
781 dup2(fd, STDIN_FILENO);
782 dup2(fd, STDOUT_FILENO);
783 adb_close(STDERR_FILENO);
784 adb_close(fd);
785
786 err = execvp("pppd", (char * const *)ppp_args);
787
788 if (err < 0) {
789 perror("execing pppd");
790 }
791 exit(-1);
792 } else {
793 // parent side
794
795 adb_close(fd);
796 return 0;
797 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800798#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800799}
800
Dan Albertbac34742015-02-25 17:51:28 -0800801static int send_shellcommand(transport_type transport, const char* serial,
802 char* buf)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800803{
804 int fd, ret;
805
806 for(;;) {
807 fd = adb_connect(buf);
808 if(fd >= 0)
809 break;
810 fprintf(stderr,"- waiting for device -\n");
811 adb_sleep_ms(1000);
812 do_cmd(transport, serial, "wait-for-device", 0);
813 }
814
815 read_and_dump(fd);
816 ret = adb_close(fd);
817 if (ret)
818 perror("close");
819
820 return ret;
821}
822
Dan Albertbac34742015-02-25 17:51:28 -0800823static int logcat(transport_type transport, const char* serial, int argc,
824 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800825{
826 char buf[4096];
827
828 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700829 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800830
831 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700832 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800833 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700834 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700835 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700837 if (!strcmp(argv[0], "longcat")) {
838 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800839 }
840
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841 argc -= 1;
842 argv += 1;
843 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700844 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700845 strncat(buf, " ", sizeof(buf) - 1);
846 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800847 free(quoted);
848 }
849
850 send_shellcommand(transport, serial, buf);
851 return 0;
852}
853
Mark Salyzyn60299df2014-04-30 09:10:31 -0700854static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800855{
856 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700857 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800858
859 for(;;) {
860 x = adb_dirstart(x);
861 if(x == 0) return 0;
862 *x = 0;
863 ret = adb_mkdir(path, 0775);
864 *x = OS_PATH_SEPARATOR;
865 if((ret < 0) && (errno != EEXIST)) {
866 return ret;
867 }
868 x++;
869 }
870 return 0;
871}
872
Dan Albertbac34742015-02-25 17:51:28 -0800873static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700874 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800875 char default_name[32];
876 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700877 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700878 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700879
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700880 /* find, extract, and use any -f argument */
881 for (i = 1; i < argc; i++) {
882 if (!strcmp("-f", argv[i])) {
883 if (i == argc-1) {
884 fprintf(stderr, "adb: -f passed with no filename\n");
885 return usage();
886 }
887 filename = argv[i+1];
888 for (j = i+2; j <= argc; ) {
889 argv[i++] = argv[j++];
890 }
891 argc -= 2;
892 argv[argc] = NULL;
893 }
Christopher Tated2f54152011-04-21 12:53:28 -0700894 }
895
Christopher Tatebb86bc52011-08-22 17:12:08 -0700896 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
897 if (argc < 2) return usage();
898
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800899 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700900 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800901 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700902 if (outFd < 0) {
903 fprintf(stderr, "adb: unable to open file %s\n", filename);
904 return -1;
905 }
906
907 snprintf(buf, sizeof(buf), "backup");
908 for (argc--, argv++; argc; argc--, argv++) {
909 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
910 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
911 }
912
913 D("backup. filename=%s buf=%s\n", filename, buf);
914 fd = adb_connect(buf);
915 if (fd < 0) {
916 fprintf(stderr, "adb: unable to connect for backup\n");
917 adb_close(outFd);
918 return -1;
919 }
920
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800921 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700922 copy_to_file(fd, outFd);
923
924 adb_close(fd);
925 adb_close(outFd);
926 return 0;
927}
928
Dan Albertbac34742015-02-25 17:51:28 -0800929static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700930 const char* filename;
931 int fd, tarFd;
932
933 if (argc != 2) return usage();
934
935 filename = argv[1];
936 tarFd = adb_open(filename, O_RDONLY);
937 if (tarFd < 0) {
938 fprintf(stderr, "adb: unable to open file %s\n", filename);
939 return -1;
940 }
941
942 fd = adb_connect("restore:");
943 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700944 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700945 adb_close(tarFd);
946 return -1;
947 }
948
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800949 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700950 copy_to_file(tarFd, fd);
951
952 adb_close(fd);
953 adb_close(tarFd);
954 return 0;
955}
956
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800957#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
958static int top_works(const char *top)
959{
960 if (top != NULL && adb_is_absolute_host_path(top)) {
961 char path_buf[PATH_MAX];
962 snprintf(path_buf, sizeof(path_buf),
963 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
964 return access(path_buf, F_OK) == 0;
965 }
966 return 0;
967}
968
969static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
970{
971 strcpy(path_buf, indir);
972 while (1) {
973 if (top_works(path_buf)) {
974 return path_buf;
975 }
976 char *s = adb_dirstop(path_buf);
977 if (s != NULL) {
978 *s = '\0';
979 } else {
980 path_buf[0] = '\0';
981 return NULL;
982 }
983 }
984}
985
986static char *find_top(char path_buf[PATH_MAX])
987{
988 char *top = getenv("ANDROID_BUILD_TOP");
989 if (top != NULL && top[0] != '\0') {
990 if (!top_works(top)) {
991 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
992 return NULL;
993 }
994 } else {
995 top = getenv("TOP");
996 if (top != NULL && top[0] != '\0') {
997 if (!top_works(top)) {
998 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
999 return NULL;
1000 }
1001 } else {
1002 top = NULL;
1003 }
1004 }
1005
1006 if (top != NULL) {
1007 /* The environment pointed to a top directory that works.
1008 */
1009 strcpy(path_buf, top);
1010 return path_buf;
1011 }
1012
1013 /* The environment didn't help. Walk up the tree from the CWD
1014 * to see if we can find the top.
1015 */
1016 char dir[PATH_MAX];
1017 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1018 if (top == NULL) {
1019 /* If the CWD isn't under a good-looking top, see if the
1020 * executable is.
1021 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001022 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 top = find_top_from(dir, path_buf);
1024 }
1025 return top;
1026}
1027
1028/* <hint> may be:
1029 * - A simple product name
1030 * e.g., "sooner"
1031TODO: debug? sooner-debug, sooner:debug?
1032 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1033 * e.g., "out/target/product/sooner"
1034 * - An absolute path to the PRODUCT_OUT dir
1035 * e.g., "/src/device/out/target/product/sooner"
1036 *
1037 * Given <hint>, try to construct an absolute path to the
1038 * ANDROID_PRODUCT_OUT dir.
1039 */
1040static const char *find_product_out_path(const char *hint)
1041{
1042 static char path_buf[PATH_MAX];
1043
1044 if (hint == NULL || hint[0] == '\0') {
1045 return NULL;
1046 }
1047
1048 /* If it's already absolute, don't bother doing any work.
1049 */
1050 if (adb_is_absolute_host_path(hint)) {
1051 strcpy(path_buf, hint);
1052 return path_buf;
1053 }
1054
1055 /* If there are any slashes in it, assume it's a relative path;
1056 * make it absolute.
1057 */
1058 if (adb_dirstart(hint) != NULL) {
1059 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1060 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1061 return NULL;
1062 }
1063 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1064 fprintf(stderr, "adb: Couldn't assemble path\n");
1065 return NULL;
1066 }
1067 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1068 strcat(path_buf, hint);
1069 return path_buf;
1070 }
1071
1072 /* It's a string without any slashes. Try to do something with it.
1073 *
1074 * Try to find the root of the build tree, and build a PRODUCT_OUT
1075 * path from there.
1076 */
1077 char top_buf[PATH_MAX];
1078 const char *top = find_top(top_buf);
1079 if (top == NULL) {
1080 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1081 return NULL;
1082 }
1083//TODO: if we have a way to indicate debug, look in out/debug/target/...
1084 snprintf(path_buf, sizeof(path_buf),
1085 "%s" OS_PATH_SEPARATOR_STR
1086 "out" OS_PATH_SEPARATOR_STR
1087 "target" OS_PATH_SEPARATOR_STR
1088 "product" OS_PATH_SEPARATOR_STR
1089 "%s", top_buf, hint);
1090 if (access(path_buf, F_OK) < 0) {
1091 fprintf(stderr, "adb: Couldn't find a product dir "
1092 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1093 return NULL;
1094 }
1095 return path_buf;
1096}
1097
Dan Albertbac34742015-02-25 17:51:28 -08001098static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1099 char const **path2, int *show_progress,
1100 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001101 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001102 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001103
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001104 while (narg > 0) {
1105 if (!strcmp(*arg, "-p")) {
1106 *show_progress = 1;
1107 } else if (!strcmp(*arg, "-a")) {
1108 *copy_attrs = 1;
1109 } else {
1110 break;
1111 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001112 ++arg;
1113 --narg;
1114 }
1115
1116 if (narg > 0) {
1117 *path1 = *arg;
1118 ++arg;
1119 --narg;
1120 }
1121
1122 if (narg > 0) {
1123 *path2 = *arg;
1124 }
1125}
1126
Tao Bao175b7bb2015-03-29 11:22:34 -07001127static int adb_connect_command(const char* command) {
1128 int fd = adb_connect(command);
1129 if (fd != -1) {
1130 read_and_dump(fd);
1131 adb_close(fd);
1132 return 0;
1133 }
1134 fprintf(stderr, "Error: %s\n", adb_error());
1135 return 1;
1136}
1137
Dan Albertbac34742015-02-25 17:51:28 -08001138int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139{
1140 char buf[4096];
1141 int no_daemon = 0;
1142 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001143 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001144 int persist = 0;
1145 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001146 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001147 const char* serial = NULL;
1148 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001149
1150 /* If defined, this should be an absolute path to
1151 * the directory containing all of the various system images
1152 * for a particular product. If not defined, and the adb
1153 * command requires this information, then the user must
1154 * specify the path using "-p".
1155 */
1156 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1157 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1158 gProductOutPath = NULL;
1159 }
1160 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1161
Nick Pellydb449262009-05-07 12:48:03 -07001162 serial = getenv("ANDROID_SERIAL");
1163
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001164 /* Validate and assign the server port */
1165 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1166 int server_port = DEFAULT_ADB_PORT;
1167 if (server_port_str && strlen(server_port_str) > 0) {
1168 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001169 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001170 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001171 "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 +01001172 server_port_str);
1173 return usage();
1174 }
1175 }
1176
1177 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001178 while (argc > 0) {
1179 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001180 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001181 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001182 no_daemon = 1;
1183 } else if (!strcmp(argv[0], "fork-server")) {
1184 /* this is a special flag used only when the ADB client launches the ADB Server */
1185 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001186 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001187 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001188 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 const char *product = NULL;
1190 if (argv[0][2] == '\0') {
1191 if (argc < 2) return usage();
1192 product = argv[1];
1193 argc--;
1194 argv++;
1195 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001196 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001197 }
1198 gProductOutPath = find_product_out_path(product);
1199 if (gProductOutPath == NULL) {
1200 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1201 product);
1202 return usage();
1203 }
1204 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1205 if (isdigit(argv[0][2])) {
1206 serial = argv[0] + 2;
1207 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001208 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001209 serial = argv[1];
1210 argc--;
1211 argv++;
1212 }
1213 } else if (!strcmp(argv[0],"-d")) {
1214 ttype = kTransportUsb;
1215 } else if (!strcmp(argv[0],"-e")) {
1216 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001217 } else if (!strcmp(argv[0],"-a")) {
1218 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001219 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001220 const char *hostname = NULL;
1221 if (argv[0][2] == '\0') {
1222 if (argc < 2) return usage();
1223 hostname = argv[1];
1224 argc--;
1225 argv++;
1226 } else {
1227 hostname = argv[0] + 2;
1228 }
1229 adb_set_tcp_name(hostname);
1230
Riley Andrews98f58e82014-12-05 17:37:24 -08001231 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001232 if (argv[0][2] == '\0') {
1233 if (argc < 2) return usage();
1234 server_port_str = argv[1];
1235 argc--;
1236 argv++;
1237 } else {
1238 server_port_str = argv[0] + 2;
1239 }
1240 if (strlen(server_port_str) > 0) {
1241 server_port = (int) strtol(server_port_str, NULL, 0);
1242 if (server_port <= 0 || server_port > 65535) {
1243 fprintf(stderr,
1244 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1245 server_port_str);
1246 return usage();
1247 }
1248 } else {
1249 fprintf(stderr,
1250 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1251 return usage();
1252 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001253 } else {
1254 /* out of recognized modifiers and flags */
1255 break;
1256 }
1257 argc--;
1258 argv++;
1259 }
1260
1261 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001262 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001264 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001265 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001266 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001267 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001268 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001269 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001270 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001271 fprintf(stderr,"* could not start server *\n");
1272 }
1273 return r;
1274 }
1275
Riley Andrews98f58e82014-12-05 17:37:24 -08001276 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001277 return usage();
1278 }
1279
Riley Andrewsc8514c82014-12-05 17:32:46 -08001280 /* handle wait-for-* prefix */
1281 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001282 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001283 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1284 if (ttype == kTransportUsb) {
1285 service = "wait-for-usb";
1286 } else if (ttype == kTransportLocal) {
1287 service = "wait-for-local";
1288 } else {
1289 service = "wait-for-any";
1290 }
1291 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001292
Riley Andrewsc8514c82014-12-05 17:32:46 -08001293 format_host_command(buf, sizeof buf, service, ttype, serial);
1294
1295 if (adb_command(buf)) {
1296 D("failure: %s *\n",adb_error());
1297 fprintf(stderr,"error: %s\n", adb_error());
1298 return 1;
1299 }
1300
1301 /* Allow a command to be run after wait-for-device,
1302 * e.g. 'adb wait-for-device shell'.
1303 */
1304 if (argc == 1) {
1305 return 0;
1306 }
1307
1308 /* Fall through */
1309 argc--;
1310 argv++;
1311 }
1312
1313 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001314 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001315 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001316 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001317 if (argc < 2)
1318 listopt = "";
1319 else if (argc == 2 && !strcmp(argv[1], "-l"))
1320 listopt = argv[1];
1321 else {
1322 fprintf(stderr, "Usage: adb devices [-l]\n");
1323 return 1;
1324 }
1325 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001326 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001327 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001328 printf("List of devices attached \n");
1329 printf("%s\n", tmp);
1330 return 0;
1331 } else {
1332 return 1;
1333 }
1334 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001335 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001336 char *tmp;
1337 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001338 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001339 return 1;
1340 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001341 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1342 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001343 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001344 printf("%s\n", tmp);
1345 return 0;
1346 } else {
1347 return 1;
1348 }
1349 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001350 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001351 char *tmp;
1352 if (argc > 2) {
1353 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1354 return 1;
1355 }
1356 if (argc == 2) {
1357 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1358 } else {
1359 snprintf(buf, sizeof buf, "host:disconnect:");
1360 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001361 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001362 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001363 printf("%s\n", tmp);
1364 return 0;
1365 } else {
1366 return 1;
1367 }
1368 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001369 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001370 return adb_send_emulator_command(argc, argv);
1371 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001372 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001373 int r;
1374 int fd;
1375
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001376 char h = (argv[0][0] == 'h');
1377
1378 if (h) {
1379 printf("\x1b[41;33m");
1380 fflush(stdout);
1381 }
1382
Riley Andrews98f58e82014-12-05 17:37:24 -08001383 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001384 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001385 r = interactive_shell();
1386 if (h) {
1387 printf("\x1b[0m");
1388 fflush(stdout);
1389 }
1390 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001391 }
1392
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001393 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001394 argc -= 2;
1395 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001396 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001397 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001398 strncat(buf, " ", sizeof(buf) - 1);
1399 strncat(buf, quoted, sizeof(buf) - 1);
1400 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001401 }
1402
1403 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001404 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001405 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001406 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001407 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001408 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001409 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 adb_close(fd);
1411 r = 0;
1412 } else {
1413 fprintf(stderr,"error: %s\n", adb_error());
1414 r = -1;
1415 }
1416
Riley Andrews98f58e82014-12-05 17:37:24 -08001417 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418 fprintf(stderr,"\n- waiting for device -\n");
1419 adb_sleep_ms(1000);
1420 do_cmd(ttype, serial, "wait-for-device", 0);
1421 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001422 if (h) {
1423 printf("\x1b[0m");
1424 fflush(stdout);
1425 }
JP Abgrall408fa572011-03-16 15:57:42 -07001426 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001427 return r;
1428 }
1429 }
1430 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001431 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001432 int exec_in = !strcmp(argv[0], "exec-in");
1433 int fd;
1434
1435 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1436 argc -= 2;
1437 argv += 2;
1438 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001439 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001440 strncat(buf, " ", sizeof(buf) - 1);
1441 strncat(buf, quoted, sizeof(buf) - 1);
1442 free(quoted);
1443 }
1444
1445 fd = adb_connect(buf);
1446 if (fd < 0) {
1447 fprintf(stderr, "error: %s\n", adb_error());
1448 return -1;
1449 }
1450
1451 if (exec_in) {
1452 copy_to_file(STDIN_FILENO, fd);
1453 } else {
1454 copy_to_file(fd, STDOUT_FILENO);
1455 }
1456
1457 adb_close(fd);
1458 return 0;
1459 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001460 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001461 int fd;
1462 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001463 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001464 fprintf(stderr,"* server not running *\n");
1465 return 1;
1466 }
1467 return 0;
1468 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001469 else if (!strcmp(argv[0], "sideload")) {
1470 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001471 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001472 return 1;
1473 } else {
1474 return 0;
1475 }
1476 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001477 else if (!strcmp(argv[0], "remount") ||
1478 !strcmp(argv[0], "reboot") ||
1479 !strcmp(argv[0], "reboot-bootloader") ||
1480 !strcmp(argv[0], "tcpip") ||
1481 !strcmp(argv[0], "usb") ||
1482 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001483 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001484 !strcmp(argv[0], "disable-verity") ||
1485 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001486 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001487 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001488 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001489 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001490 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001491 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001492 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001493 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001494 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001495 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001496 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001497 if (argc != 1) return usage();
1498 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001499 return 0;
1500 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001501 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001502 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001503 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001504 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001505 char remove = 0;
1506 char remove_all = 0;
1507 char list = 0;
1508 char no_rebind = 0;
1509
1510 // Parse options here.
1511 while (argc > 1 && argv[1][0] == '-') {
1512 if (!strcmp(argv[1], "--list"))
1513 list = 1;
1514 else if (!strcmp(argv[1], "--remove"))
1515 remove = 1;
1516 else if (!strcmp(argv[1], "--remove-all"))
1517 remove_all = 1;
1518 else if (!strcmp(argv[1], "--no-rebind"))
1519 no_rebind = 1;
1520 else {
1521 return usage();
1522 }
1523 argc--;
1524 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001526
1527 // Ensure we can only use one option at a time.
1528 if (list + remove + remove_all + no_rebind > 1) {
1529 return usage();
1530 }
1531
1532 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001533 if (reverse) {
1534 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001535 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001536 if (serial) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1538 serial);
1539 } else if (ttype == kTransportUsb) {
1540 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1541 } else if (ttype == kTransportLocal) {
1542 snprintf(host_prefix, sizeof host_prefix, "host-local");
1543 } else {
1544 snprintf(host_prefix, sizeof host_prefix, "host");
1545 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001546 }
1547
1548 // Implement forward --list
1549 if (list) {
1550 if (argc != 1)
1551 return usage();
1552 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1553 char* forwards = adb_query(buf);
1554 if (forwards == NULL) {
1555 fprintf(stderr, "error: %s\n", adb_error());
1556 return 1;
1557 }
1558 printf("%s", forwards);
1559 free(forwards);
1560 return 0;
1561 }
1562
1563 // Implement forward --remove-all
1564 else if (remove_all) {
1565 if (argc != 1)
1566 return usage();
1567 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1568 }
1569
1570 // Implement forward --remove <local>
1571 else if (remove) {
1572 if (argc != 2)
1573 return usage();
1574 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1575 }
1576 // Or implement one of:
1577 // forward <local> <remote>
1578 // forward --no-rebind <local> <remote>
1579 else
1580 {
1581 if (argc != 3)
1582 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001583 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001584 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1585 }
1586
Riley Andrews98f58e82014-12-05 17:37:24 -08001587 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001588 fprintf(stderr,"error: %s\n", adb_error());
1589 return 1;
1590 }
1591 return 0;
1592 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001593 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001594 else if (!strcmp(argv[0], "ls")) {
1595 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001596 return do_sync_ls(argv[1]);
1597 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001598 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001599 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001600 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001601 const char* lpath = NULL, *rpath = NULL;
1602
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001603 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001604
1605 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001606 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001607 }
1608
1609 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001610 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001611 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001612 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001613 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001614 const char* rpath = NULL, *lpath = ".";
1615
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001616 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001617
1618 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001619 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001620 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001621
1622 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001624 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 if (argc < 2) return usage();
1626 return install_app(ttype, serial, argc, argv);
1627 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001628 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001629 if (argc < 2) return usage();
1630 return install_multiple_app(ttype, serial, argc, argv);
1631 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001632 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 if (argc < 2) return usage();
1634 return uninstall_app(ttype, serial, argc, argv);
1635 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001636 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001637 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001638 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1639
Anthony Newnam705c9442010-02-22 08:36:49 -06001640 int listonly = 0;
1641
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001642 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001643 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001644 /* No local path was specified. */
1645 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001646 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1647 listonly = 1;
1648 if (argc == 3) {
1649 srcarg = argv[2];
1650 } else {
1651 srcarg = NULL;
1652 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001653 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001654 /* A local path or "android"/"data" arg was specified. */
1655 srcarg = argv[1];
1656 } else {
1657 return usage();
1658 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001659 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1660 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001661 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001662
Elliott Hughesec7a6672015-03-16 21:58:32 +00001663 if (system_srcpath != NULL)
1664 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001665 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001666 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001667 if(ret == 0 && oem_srcpath != NULL)
1668 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001669 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001670 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001671
Elliott Hughesec7a6672015-03-16 21:58:32 +00001672 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001673 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001674 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001675 free(data_srcpath);
1676 return ret;
1677 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001678 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001679 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001680 !strcmp(argv[0],"get-serialno") ||
1681 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 {
1683 char *tmp;
1684
1685 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1686 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001687 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 printf("%s\n", tmp);
1689 return 0;
1690 } else {
1691 return 1;
1692 }
1693 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001694 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001696 status_window(ttype, serial);
1697 return 0;
1698 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001699 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001700 return logcat(ttype, serial, argc, argv);
1701 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001703 return ppp(argc, argv);
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001706 return adb_connect("host:start-server");
1707 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001709 return backup(argc, argv);
1710 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001711 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001712 return restore(argc, argv);
1713 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001714 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001715 if (argc < 2) return usage();
1716 return adb_auth_keygen(argv[1]);
1717 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001718 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001719 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001720 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001721 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001722 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001723 help();
1724 return 0;
1725 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001726 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001727 version(stdout);
1728 return 0;
1729 }
1730
1731 usage();
1732 return 1;
1733}
1734
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001735#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001736static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001737{
Dan Albertbac34742015-02-25 17:51:28 -08001738 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001739 int argc;
1740 va_list ap;
1741
1742 va_start(ap, cmd);
1743 argc = 0;
1744
1745 if (serial) {
1746 argv[argc++] = "-s";
1747 argv[argc++] = serial;
1748 } else if (ttype == kTransportUsb) {
1749 argv[argc++] = "-d";
1750 } else if (ttype == kTransportLocal) {
1751 argv[argc++] = "-e";
1752 }
1753
1754 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001755 while(argc < MAX_ARGV_LENGTH &&
1756 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1757 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001758 va_end(ap);
1759
1760#if 0
1761 int n;
1762 fprintf(stderr,"argc = %d\n",argc);
1763 for(n = 0; n < argc; n++) {
1764 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1765 }
1766#endif
1767
1768 return adb_commandline(argc, argv);
1769}
1770
1771int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001772 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1773 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001774{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001775 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001776 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001777
1778 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001779 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001780 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001781 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001782 oem_srcdir = product_file("oem");
1783 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001784 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1785 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001786 // Check if oem partition exists.
1787 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1788 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001789 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001790 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1791 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001792 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001793 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001794 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001795 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001796 } else if(strcmp(srcarg, "vendor") == 0) {
1797 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001798 } else if(strcmp(srcarg, "oem") == 0) {
1799 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001800 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001801 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001802 return 1;
1803 }
1804 }
1805
Elliott Hughesec7a6672015-03-16 21:58:32 +00001806 if(system_srcdir_out != NULL)
1807 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001808 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001809 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001810
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001811 if(vendor_srcdir_out != NULL)
1812 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001813 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001814 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815
Elliott Hughesec7a6672015-03-16 21:58:32 +00001816 if(oem_srcdir_out != NULL)
1817 *oem_srcdir_out = oem_srcdir;
1818 else
1819 free(oem_srcdir);
1820
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001821 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001822 *data_srcdir_out = data_srcdir;
1823 else
1824 free(data_srcdir);
1825
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001826 return 0;
1827}
1828
Dan Albertbac34742015-02-25 17:51:28 -08001829static int pm_command(transport_type transport, const char* serial,
1830 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001831{
1832 char buf[4096];
1833
1834 snprintf(buf, sizeof(buf), "shell:pm");
1835
1836 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001837 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001838 strncat(buf, " ", sizeof(buf) - 1);
1839 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001840 free(quoted);
1841 }
1842
1843 send_shellcommand(transport, serial, buf);
1844 return 0;
1845}
1846
Dan Albertbac34742015-02-25 17:51:28 -08001847int uninstall_app(transport_type transport, const char* serial, int argc,
1848 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001849{
1850 /* if the user choose the -k option, we refuse to do it until devices are
1851 out with the option to uninstall the remaining data somehow (adb/ui) */
1852 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1853 {
1854 printf(
1855 "The -k option uninstalls the application while retaining the data/cache.\n"
1856 "At the moment, there is no way to remove the remaining data.\n"
1857 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1858 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1859 return -1;
1860 }
1861
1862 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1863 return pm_command(transport, serial, argc, argv);
1864}
1865
Dan Albertbac34742015-02-25 17:51:28 -08001866static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001867{
1868 char buf[4096];
1869 char* quoted;
1870
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001871 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001872 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001873 strncat(buf, quoted, sizeof(buf)-1);
1874 free(quoted);
1875
1876 send_shellcommand(transport, serial, buf);
1877 return 0;
1878}
1879
Kenny Root597ea5b2011-08-05 11:19:45 -07001880static const char* get_basename(const char* filename)
1881{
1882 const char* basename = adb_dirstop(filename);
1883 if (basename) {
1884 basename++;
1885 return basename;
1886 } else {
1887 return filename;
1888 }
1889}
1890
Dan Albertbac34742015-02-25 17:51:28 -08001891int install_app(transport_type transport, const char* serial, int argc,
1892 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001893{
1894 static const char *const DATA_DEST = "/data/local/tmp/%s";
1895 static const char *const SD_DEST = "/sdcard/tmp/%s";
1896 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001897 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001898 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001899
1900 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001901 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001902 where = SD_DEST;
1903 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001904 }
1905
Jeff Sharkey960df972014-06-09 17:30:57 -07001906 // Find last APK argument.
1907 // All other arguments passed through verbatim.
1908 int last_apk = -1;
1909 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001910 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001911 char* dot = strrchr(file, '.');
1912 if (dot && !strcasecmp(dot, ".apk")) {
1913 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1914 fprintf(stderr, "Invalid APK file: %s\n", file);
1915 return -1;
1916 }
1917
1918 last_apk = i;
1919 break;
1920 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001921 }
1922
Jeff Sharkey960df972014-06-09 17:30:57 -07001923 if (last_apk == -1) {
1924 fprintf(stderr, "Missing APK file\n");
1925 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001926 }
1927
Dan Albertbac34742015-02-25 17:51:28 -08001928 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001929 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001930 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001931 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001932 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001933 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001934 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001935 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 }
1937
1938 pm_command(transport, serial, argc, argv);
1939
Kenny Root60733e92012-03-26 16:14:02 -07001940cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001941 delete_file(transport, serial, apk_dest);
1942 return err;
1943}
1944
Dan Albertbac34742015-02-25 17:51:28 -08001945int install_multiple_app(transport_type transport, const char* serial, int argc,
1946 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001947{
1948 char buf[1024];
1949 int i;
1950 struct stat sb;
1951 unsigned long long total_size = 0;
1952
1953 // Find all APK arguments starting at end.
1954 // All other arguments passed through verbatim.
1955 int first_apk = -1;
1956 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001957 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001958 char* dot = strrchr(file, '.');
1959 if (dot && !strcasecmp(dot, ".apk")) {
1960 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1961 fprintf(stderr, "Invalid APK file: %s\n", file);
1962 return -1;
1963 }
1964
1965 total_size += sb.st_size;
1966 first_apk = i;
1967 } else {
1968 break;
1969 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001970 }
1971
Jeff Sharkey960df972014-06-09 17:30:57 -07001972 if (first_apk == -1) {
1973 fprintf(stderr, "Missing APK file\n");
1974 return 1;
1975 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001976
Jeff Sharkey960df972014-06-09 17:30:57 -07001977 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1978 for (i = 1; i < first_apk; i++) {
1979 char *quoted = escape_arg(argv[i]);
1980 strncat(buf, " ", sizeof(buf) - 1);
1981 strncat(buf, quoted, sizeof(buf) - 1);
1982 free(quoted);
1983 }
1984
1985 // Create install session
1986 int fd = adb_connect(buf);
1987 if (fd < 0) {
1988 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1989 return -1;
1990 }
1991 read_status_line(fd, buf, sizeof(buf));
1992 adb_close(fd);
1993
1994 int session_id = -1;
1995 if (!strncmp("Success", buf, 7)) {
1996 char* start = strrchr(buf, '[');
1997 char* end = strrchr(buf, ']');
1998 if (start && end) {
1999 *end = '\0';
2000 session_id = strtol(start + 1, NULL, 10);
2001 }
2002 }
2003 if (session_id < 0) {
2004 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002005 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002006 return -1;
2007 }
2008
2009 // Valid session, now stream the APKs
2010 int success = 1;
2011 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08002012 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07002013 if (stat(file, &sb) == -1) {
2014 fprintf(stderr, "Failed to stat %s\n", file);
2015 success = 0;
2016 goto finalize_session;
2017 }
2018
2019 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002020 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002021
2022 int localFd = adb_open(file, O_RDONLY);
2023 if (localFd < 0) {
2024 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2025 success = 0;
2026 goto finalize_session;
2027 }
2028
2029 int remoteFd = adb_connect(buf);
2030 if (remoteFd < 0) {
2031 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2032 adb_close(localFd);
2033 success = 0;
2034 goto finalize_session;
2035 }
2036
2037 copy_to_file(localFd, remoteFd);
2038 read_status_line(remoteFd, buf, sizeof(buf));
2039
2040 adb_close(localFd);
2041 adb_close(remoteFd);
2042
2043 if (strncmp("Success", buf, 7)) {
2044 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002045 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002046 success = 0;
2047 goto finalize_session;
2048 }
2049 }
2050
2051finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002052 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002053 if (success) {
2054 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2055 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002056 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002057 }
2058
2059 fd = adb_connect(buf);
2060 if (fd < 0) {
2061 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2062 return -1;
2063 }
2064 read_status_line(fd, buf, sizeof(buf));
2065 adb_close(fd);
2066
2067 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002068 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002069 return 0;
2070 } else {
2071 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002072 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002073 return -1;
2074 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002075}