blob: f3457879741cea47e32d29ab5fd1ca7f2050786a [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
17#include <stdio.h>
Andrew Hsiehb75d6f12014-05-07 20:21:11 +080018#include <stdint.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <unistd.h>
23#include <limits.h>
24#include <stdarg.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <ctype.h>
28#include <assert.h>
29
30#include "sysdeps.h"
31
Yabin Cuid325e862014-11-17 14:48:25 -080032#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033#include <termios.h>
34#endif
35
36#define TRACE_TAG TRACE_ADB
37#include "adb.h"
38#include "adb_client.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080039#include "adb_auth.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040#include "file_sync_service.h"
41
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
43
Alexey Tarasov31664102009-10-22 02:55:00 +110044void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -070046 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey960df972014-06-09 17:30:57 -070048int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
50
51static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080052extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080053
54static char *product_file(const char *extra)
55{
56 int n;
57 char *x;
58
59 if (gProductOutPath == NULL) {
60 fprintf(stderr, "adb: Product directory not specified; "
61 "use -p or define ANDROID_PRODUCT_OUT\n");
62 exit(1);
63 }
64
65 n = strlen(gProductOutPath) + strlen(extra) + 2;
66 x = malloc(n);
67 if (x == 0) {
68 fprintf(stderr, "adb: Out of memory (product_file())\n");
69 exit(1);
70 }
71
72 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
73 return x;
74}
75
76void version(FILE * out) {
77 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
78 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
79}
80
81void help()
82{
83 version(stderr);
84
85 fprintf(stderr,
86 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080087 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080088 " -d - directs command to the only connected USB device\n"
89 " returns an error if more than one USB device is present.\n"
90 " -e - directs command to the only running emulator.\n"
91 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070092 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070093 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070094 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 " -p <product name or path> - simple product name like 'sooner', or\n"
96 " a relative/absolute path to a product\n"
97 " out directory like 'out/target/product/sooner'.\n"
98 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
99 " environment variable is used, which must\n"
100 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800101 " -H - Name of adb server host (default: localhost)\n"
102 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700103 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700104 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400105 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
106 " Port 5555 is used by default if no port number is specified.\n"
107 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
108 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200109 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400110 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 "\n"
112 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700113 " adb push [-p] <local> <remote>\n"
114 " - copy file/dir to device\n"
115 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700116 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700117 " - copy file/dir from device\n"
118 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700119 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800120 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600121 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800122 " (see 'adb help all')\n"
123 " adb shell - run remote shell interactively\n"
124 " adb shell <command> - run remote shell command\n"
125 " adb emu <command> - run emulator console command\n"
126 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100127 " adb forward --list - list all forward socket connections.\n"
128 " the format is a list of lines with the following format:\n"
129 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800130 " adb forward <local> <remote> - forward socket connections\n"
131 " forward specs are one of: \n"
132 " tcp:<port>\n"
133 " localabstract:<unix domain socket name>\n"
134 " localreserved:<unix domain socket name>\n"
135 " localfilesystem:<unix domain socket name>\n"
136 " dev:<character device name>\n"
137 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100138 " adb forward --no-rebind <local> <remote>\n"
139 " - same as 'adb forward <local> <remote>' but fails\n"
140 " if <local> is already forwarded\n"
141 " adb forward --remove <local> - remove a specific forward socket connection\n"
142 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100143 " adb reverse --list - list all reverse socket connections from device\n"
144 " adb reverse <remote> <local> - reverse socket connections\n"
145 " reverse specs are one of:\n"
146 " tcp:<port>\n"
147 " localabstract:<unix domain socket name>\n"
148 " localreserved:<unix domain socket name>\n"
149 " localfilesystem:<unix domain socket name>\n"
150 " adb reverse --norebind <remote> <local>\n"
151 " - same as 'adb reverse <remote> <local>' but fails\n"
152 " if <remote> is already reversed.\n"
153 " adb reverse --remove <remote>\n"
154 " - remove a specific reversed socket connection\n"
155 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700157 " adb install [-lrtsd] <file>\n"
158 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700160 " (-l: forward lock application)\n"
161 " (-r: replace existing application)\n"
162 " (-t: allow test packages)\n"
163 " (-s: install application on sdcard)\n"
164 " (-d: allow version code downgrade)\n"
165 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166 " adb uninstall [-k] <package> - remove this app package from the device\n"
167 " ('-k' means keep the data and cache directories)\n"
168 " adb bugreport - return all information from the device\n"
169 " that should be included in a bug report.\n"
170 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800171 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700172 " - write an archive of the device's data to <file>.\n"
173 " If no -f option is supplied then the data is written\n"
174 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700175 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700176 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800177 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
178 " (aka .obb) files associated with each application; the default\n"
179 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700180 " (-shared|-noshared enable/disable backup of the device's\n"
181 " shared storage / SD card contents; the default is noshared.)\n"
182 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700183 " (-system|-nosystem toggles whether -all automatically includes\n"
184 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700185 " (<packages...> is the list of applications to be backed up. If\n"
186 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700187 " list is optional. Applications explicitly given on the\n"
188 " command line will be included even if -nosystem would\n"
189 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700190 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700191 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700192 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800193 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
194 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800195 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
196 " and the public key is stored in <file>.pub. Any existing files\n"
197 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800198 " adb help - show this help message\n"
199 " adb version - show version num\n"
200 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800201 "scripting:\n"
202 " adb wait-for-device - block until device is online\n"
203 " adb start-server - ensure that there is a server running\n"
204 " adb kill-server - kill the server if it is running\n"
205 " adb get-state - prints: offline | bootloader | device\n"
206 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700207 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700209 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400210 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800211 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700212 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800213 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000214 " 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 -0800215 "networking:\n"
216 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500217 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
219 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
220 "\n"
221 "adb sync notes: adb sync [ <directory> ]\n"
222 " <localdir> can be interpreted in several ways:\n"
223 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700224 " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800225 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700226 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000228 "\n"
229 "environmental variables:\n"
230 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
231 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
232 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
233 " 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 -0800234 );
235}
236
237int usage()
238{
239 help();
240 return 1;
241}
242
Yabin Cuid325e862014-11-17 14:48:25 -0800243#if defined(_WIN32)
244
245// Windows does not have <termio.h>.
246static void stdin_raw_init(int fd) {
247
248}
249
250static void stdin_raw_restore(int fd) {
251
252}
253
254#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255static struct termios tio_save;
256
257static void stdin_raw_init(int fd)
258{
259 struct termios tio;
260
261 if(tcgetattr(fd, &tio)) return;
262 if(tcgetattr(fd, &tio_save)) return;
263
264 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
265
266 /* no timeout but request at least one character per read */
267 tio.c_cc[VTIME] = 0;
268 tio.c_cc[VMIN] = 1;
269
270 tcsetattr(fd, TCSANOW, &tio);
271 tcflush(fd, TCIFLUSH);
272}
273
274static void stdin_raw_restore(int fd)
275{
276 tcsetattr(fd, TCSANOW, &tio_save);
277 tcflush(fd, TCIFLUSH);
278}
279#endif
280
281static void read_and_dump(int fd)
282{
283 char buf[4096];
284 int len;
285
286 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700287 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 if(len == 0) {
291 break;
292 }
293
294 if(len < 0) {
295 if(errno == EINTR) continue;
296 break;
297 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400298 fwrite(buf, 1, len, stdout);
299 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 }
301}
302
Jeff Sharkey960df972014-06-09 17:30:57 -0700303static void read_status_line(int fd, char* buf, size_t count)
304{
305 count--;
306 while (count > 0) {
307 int len = adb_read(fd, buf, count);
308 if (len == 0) {
309 break;
310 } else if (len < 0) {
311 if (errno == EINTR) continue;
312 break;
313 }
314
315 buf += len;
316 count -= len;
317 }
318 *buf = '\0';
319}
320
Christopher Tated2f54152011-04-21 12:53:28 -0700321static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700322 const size_t BUFSIZE = 32 * 1024;
323 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700324 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700325 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700326
327 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800328
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700329 if (inFd == STDIN_FILENO) {
330 stdin_raw_init(STDIN_FILENO);
331 }
Yabin Cuid325e862014-11-17 14:48:25 -0800332
Christopher Tated2f54152011-04-21 12:53:28 -0700333 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700334 if (inFd == STDIN_FILENO) {
335 len = unix_read(inFd, buf, BUFSIZE);
336 } else {
337 len = adb_read(inFd, buf, BUFSIZE);
338 }
Christopher Tated2f54152011-04-21 12:53:28 -0700339 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700340 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700341 break;
342 }
343 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700344 if (errno == EINTR) {
345 D("copy_to_file() : EINTR, retrying\n");
346 continue;
347 }
Christopher Tated2f54152011-04-21 12:53:28 -0700348 D("copy_to_file() : error %d\n", errno);
349 break;
350 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700351 if (outFd == STDOUT_FILENO) {
352 fwrite(buf, 1, len, stdout);
353 fflush(stdout);
354 } else {
355 adb_write(outFd, buf, len);
356 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700357 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700358 }
Yabin Cuid325e862014-11-17 14:48:25 -0800359
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700360 if (inFd == STDIN_FILENO) {
361 stdin_raw_restore(STDIN_FILENO);
362 }
Yabin Cuid325e862014-11-17 14:48:25 -0800363
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700364 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700365 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700366}
367
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800368static void *stdin_read_thread(void *x)
369{
370 int fd, fdi;
371 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 int r, n;
373 int state = 0;
374
375 int *fds = (int*) x;
376 fd = fds[0];
377 fdi = fds[1];
378 free(fds);
379
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380 for(;;) {
381 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700382 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700384 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 if(r == 0) break;
386 if(r < 0) {
387 if(errno == EINTR) continue;
388 break;
389 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400390 for(n = 0; n < r; n++){
391 switch(buf[n]) {
392 case '\n':
393 state = 1;
394 break;
395 case '\r':
396 state = 1;
397 break;
398 case '~':
399 if(state == 1) state++;
400 break;
401 case '.':
402 if(state == 2) {
403 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400404 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400405 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800406 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 default:
408 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 r = adb_write(fd, buf, r);
412 if(r <= 0) {
413 break;
414 }
415 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800416 return 0;
417}
418
419int interactive_shell(void)
420{
421 adb_thread_t thr;
422 int fdi, fd;
423 int *fds;
424
425 fd = adb_connect("shell:");
426 if(fd < 0) {
427 fprintf(stderr,"error: %s\n", adb_error());
428 return 1;
429 }
430 fdi = 0; //dup(0);
431
432 fds = malloc(sizeof(int) * 2);
433 fds[0] = fd;
434 fds[1] = fdi;
435
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 adb_thread_create(&thr, stdin_read_thread, fds);
438 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800439 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 return 0;
441}
442
443
444static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
445{
446 if (serial) {
447 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
448 } else {
449 const char* prefix = "host";
450 if (ttype == kTransportUsb)
451 prefix = "host-usb";
452 else if (ttype == kTransportLocal)
453 prefix = "host-local";
454
455 snprintf(buffer, buflen, "%s:%s", prefix, command);
456 }
457}
458
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100459int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800460 unsigned progress)
461{
462 char buf[4096];
463 unsigned total;
464 int fd;
465 const unsigned char *ptr;
466
467 sprintf(buf,"%s:%d", service, sz);
468 fd = adb_connect(buf);
469 if(fd < 0) {
470 fprintf(stderr,"error: %s\n", adb_error());
471 return -1;
472 }
473
474 int opt = CHUNK_SIZE;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700475 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800476
477 total = sz;
478 ptr = data;
479
480 if(progress) {
481 char *x = strrchr(service, ':');
482 if(x) service = x + 1;
483 }
484
485 while(sz > 0) {
486 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
487 if(writex(fd, ptr, xfer)) {
488 adb_status(fd);
489 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
490 return -1;
491 }
492 sz -= xfer;
493 ptr += xfer;
494 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100495 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800496 fflush(stdout);
497 }
498 }
499 if(progress) {
500 printf("\n");
501 }
502
503 if(readx(fd, buf, 4)){
504 fprintf(stderr,"* error reading response *\n");
505 adb_close(fd);
506 return -1;
507 }
508 if(memcmp(buf, "OKAY", 4)) {
509 buf[4] = 0;
510 fprintf(stderr,"* error response '%s' *\n", buf);
511 adb_close(fd);
512 return -1;
513 }
514
515 adb_close(fd);
516 return 0;
517}
518
519
520int adb_download(const char *service, const char *fn, unsigned progress)
521{
522 void *data;
523 unsigned sz;
524
525 data = load_file(fn, &sz);
526 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100527 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800528 return -1;
529 }
530
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100531 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800532 free(data);
533 return status;
534}
535
Doug Zongker71fe5842014-06-26 15:35:36 -0700536#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
537
538/*
539 * The sideload-host protocol serves the data in a file (given on the
540 * command line) to the client, using a simple protocol:
541 *
542 * - The connect message includes the total number of bytes in the
543 * file and a block size chosen by us.
544 *
545 * - The other side sends the desired block number as eight decimal
546 * digits (eg "00000023" for block 23). Blocks are numbered from
547 * zero.
548 *
549 * - We send back the data of the requested block. The last block is
550 * likely to be partial; when the last block is requested we only
551 * send the part of the block that exists, it's not padded up to the
552 * block size.
553 *
554 * - When the other side sends "DONEDONE" instead of a block number,
555 * we hang up.
556 */
557int adb_sideload_host(const char* fn) {
558 uint8_t* data;
559 unsigned sz;
560 size_t xfer = 0;
561 int status;
562
563 printf("loading: '%s'", fn);
564 fflush(stdout);
565 data = load_file(fn, &sz);
566 if (data == 0) {
567 printf("\n");
568 fprintf(stderr, "* cannot read '%s' *\n", fn);
569 return -1;
570 }
571
572 char buf[100];
573 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
574 int fd = adb_connect(buf);
575 if (fd < 0) {
576 // Try falling back to the older sideload method. Maybe this
577 // is an older device that doesn't support sideload-host.
578 printf("\n");
579 status = adb_download_buffer("sideload", fn, data, sz, 1);
580 goto done;
581 }
582
583 int opt = SIDELOAD_HOST_BLOCK_SIZE;
584 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
585
586 int last_percent = -1;
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700587 for (;;) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700588 if (readx(fd, buf, 8)) {
589 fprintf(stderr, "* failed to read command: %s\n", adb_error());
590 status = -1;
591 goto done;
592 }
593
594 if (strncmp("DONEDONE", buf, 8) == 0) {
595 status = 0;
596 break;
597 }
598
599 buf[8] = '\0';
600 int block = strtol(buf, NULL, 10);
601
602 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
603 if (offset >= sz) {
604 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
605 status = -1;
606 goto done;
607 }
608 uint8_t* start = data + offset;
609 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
610 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
611 if (offset_end > sz) {
612 to_write = sz - offset;
613 }
614
615 if(writex(fd, start, to_write)) {
616 adb_status(fd);
617 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
618 status = -1;
619 goto done;
620 }
621 xfer += to_write;
622
623 // For normal OTA packages, we expect to transfer every byte
624 // twice, plus a bit of overhead (one read during
625 // verification, one read of each byte for installation, plus
626 // extra access to things like the zip central directory).
627 // This estimate of the completion becomes 100% when we've
628 // transferred ~2.13 (=100/47) times the package size.
629 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
630 if (percent != last_percent) {
631 printf("\rserving: '%s' (~%d%%) ", fn, percent);
632 fflush(stdout);
633 last_percent = percent;
634 }
635 }
636
Colin Cross6d6a8982014-07-07 14:12:41 -0700637 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700638
639 done:
640 if (fd >= 0) adb_close(fd);
641 free(data);
642 return status;
643}
644
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800645static void status_window(transport_type ttype, const char* serial)
646{
647 char command[4096];
648 char *state = 0;
649 char *laststate = 0;
650
651 /* silence stderr */
652#ifdef _WIN32
653 /* XXX: TODO */
654#else
655 int fd;
656 fd = unix_open("/dev/null", O_WRONLY);
657 dup2(fd, 2);
658 adb_close(fd);
659#endif
660
661 format_host_command(command, sizeof command, "get-state", ttype, serial);
662
663 for(;;) {
664 adb_sleep_ms(250);
665
666 if(state) {
667 free(state);
668 state = 0;
669 }
670
671 state = adb_query(command);
672
673 if(state) {
674 if(laststate && !strcmp(state,laststate)){
675 continue;
676 } else {
677 if(laststate) free(laststate);
678 laststate = strdup(state);
679 }
680 }
681
682 printf("%c[2J%c[2H", 27, 27);
683 printf("Android Debug Bridge\n");
684 printf("State: %s\n", state ? state : "offline");
685 fflush(stdout);
686 }
687}
688
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700689static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700690{
691 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
692}
693
694/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700695static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696{
697 const char *ts;
698 size_t alloc_len;
699 char *ret;
700 char *dest;
701
Jeff Sharkey7c460352014-06-10 16:22:17 -0700702 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700703 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800704 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700705 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706 alloc_len++;
707 }
708 }
709
Jeff Sharkey7c460352014-06-10 16:22:17 -0700710 if (alloc_len == 0) {
711 // Preserve empty arguments
712 ret = (char *) malloc(3);
713 ret[0] = '\"';
714 ret[1] = '\"';
715 ret[2] = '\0';
716 return ret;
717 }
718
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700719 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800720 dest = ret;
721
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700722 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700723 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800724 *dest++ = '\\';
725 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800726 *dest++ = *ts;
727 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800728 *dest++ = '\0';
729
730 return ret;
731}
732
733/**
734 * Run ppp in "notty" mode against a resource listed as the first parameter
735 * eg:
736 *
737 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
738 *
739 */
740int ppp(int argc, char **argv)
741{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800742#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800743 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
744 return -1;
745#else
746 char *adb_service_name;
747 pid_t pid;
748 int fd;
749
750 if (argc < 2) {
751 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
752 argv[0]);
753
754 return 1;
755 }
756
757 adb_service_name = argv[1];
758
759 fd = adb_connect(adb_service_name);
760
761 if(fd < 0) {
762 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
763 adb_service_name, adb_error());
764 return 1;
765 }
766
767 pid = fork();
768
769 if (pid < 0) {
770 perror("from fork()");
771 return 1;
772 } else if (pid == 0) {
773 int err;
774 int i;
775 const char **ppp_args;
776
777 // copy args
778 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
779 ppp_args[0] = "pppd";
780 for (i = 2 ; i < argc ; i++) {
781 //argv[2] and beyond become ppp_args[1] and beyond
782 ppp_args[i - 1] = argv[i];
783 }
784 ppp_args[i-1] = NULL;
785
786 // child side
787
788 dup2(fd, STDIN_FILENO);
789 dup2(fd, STDOUT_FILENO);
790 adb_close(STDERR_FILENO);
791 adb_close(fd);
792
793 err = execvp("pppd", (char * const *)ppp_args);
794
795 if (err < 0) {
796 perror("execing pppd");
797 }
798 exit(-1);
799 } else {
800 // parent side
801
802 adb_close(fd);
803 return 0;
804 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800805#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800806}
807
808static int send_shellcommand(transport_type transport, char* serial, char* buf)
809{
810 int fd, ret;
811
812 for(;;) {
813 fd = adb_connect(buf);
814 if(fd >= 0)
815 break;
816 fprintf(stderr,"- waiting for device -\n");
817 adb_sleep_ms(1000);
818 do_cmd(transport, serial, "wait-for-device", 0);
819 }
820
821 read_and_dump(fd);
822 ret = adb_close(fd);
823 if (ret)
824 perror("close");
825
826 return ret;
827}
828
829static int logcat(transport_type transport, char* serial, int argc, char **argv)
830{
831 char buf[4096];
832
833 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700834 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800835
836 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700837 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800838 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700839 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700840 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700842 if (!strcmp(argv[0], "longcat")) {
843 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800844 }
845
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 argc -= 1;
847 argv += 1;
848 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700849 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700850 strncat(buf, " ", sizeof(buf) - 1);
851 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800852 free(quoted);
853 }
854
855 send_shellcommand(transport, serial, buf);
856 return 0;
857}
858
Mark Salyzyn60299df2014-04-30 09:10:31 -0700859static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800860{
861 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700862 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800863
864 for(;;) {
865 x = adb_dirstart(x);
866 if(x == 0) return 0;
867 *x = 0;
868 ret = adb_mkdir(path, 0775);
869 *x = OS_PATH_SEPARATOR;
870 if((ret < 0) && (errno != EEXIST)) {
871 return ret;
872 }
873 x++;
874 }
875 return 0;
876}
877
Christopher Tated2f54152011-04-21 12:53:28 -0700878static int backup(int argc, char** argv) {
879 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800880 char default_name[32];
881 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700882 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700883 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700884
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700885 /* find, extract, and use any -f argument */
886 for (i = 1; i < argc; i++) {
887 if (!strcmp("-f", argv[i])) {
888 if (i == argc-1) {
889 fprintf(stderr, "adb: -f passed with no filename\n");
890 return usage();
891 }
892 filename = argv[i+1];
893 for (j = i+2; j <= argc; ) {
894 argv[i++] = argv[j++];
895 }
896 argc -= 2;
897 argv[argc] = NULL;
898 }
Christopher Tated2f54152011-04-21 12:53:28 -0700899 }
900
Christopher Tatebb86bc52011-08-22 17:12:08 -0700901 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
902 if (argc < 2) return usage();
903
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800904 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700905 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800906 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700907 if (outFd < 0) {
908 fprintf(stderr, "adb: unable to open file %s\n", filename);
909 return -1;
910 }
911
912 snprintf(buf, sizeof(buf), "backup");
913 for (argc--, argv++; argc; argc--, argv++) {
914 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
915 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
916 }
917
918 D("backup. filename=%s buf=%s\n", filename, buf);
919 fd = adb_connect(buf);
920 if (fd < 0) {
921 fprintf(stderr, "adb: unable to connect for backup\n");
922 adb_close(outFd);
923 return -1;
924 }
925
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800926 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700927 copy_to_file(fd, outFd);
928
929 adb_close(fd);
930 adb_close(outFd);
931 return 0;
932}
933
Christopher Tate702967a2011-05-17 15:52:54 -0700934static int restore(int argc, char** argv) {
935 const char* filename;
936 int fd, tarFd;
937
938 if (argc != 2) return usage();
939
940 filename = argv[1];
941 tarFd = adb_open(filename, O_RDONLY);
942 if (tarFd < 0) {
943 fprintf(stderr, "adb: unable to open file %s\n", filename);
944 return -1;
945 }
946
947 fd = adb_connect("restore:");
948 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700949 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700950 adb_close(tarFd);
951 return -1;
952 }
953
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800954 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700955 copy_to_file(tarFd, fd);
956
957 adb_close(fd);
958 adb_close(tarFd);
959 return 0;
960}
961
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800962#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
963static int top_works(const char *top)
964{
965 if (top != NULL && adb_is_absolute_host_path(top)) {
966 char path_buf[PATH_MAX];
967 snprintf(path_buf, sizeof(path_buf),
968 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
969 return access(path_buf, F_OK) == 0;
970 }
971 return 0;
972}
973
974static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
975{
976 strcpy(path_buf, indir);
977 while (1) {
978 if (top_works(path_buf)) {
979 return path_buf;
980 }
981 char *s = adb_dirstop(path_buf);
982 if (s != NULL) {
983 *s = '\0';
984 } else {
985 path_buf[0] = '\0';
986 return NULL;
987 }
988 }
989}
990
991static char *find_top(char path_buf[PATH_MAX])
992{
993 char *top = getenv("ANDROID_BUILD_TOP");
994 if (top != NULL && top[0] != '\0') {
995 if (!top_works(top)) {
996 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
997 return NULL;
998 }
999 } else {
1000 top = getenv("TOP");
1001 if (top != NULL && top[0] != '\0') {
1002 if (!top_works(top)) {
1003 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1004 return NULL;
1005 }
1006 } else {
1007 top = NULL;
1008 }
1009 }
1010
1011 if (top != NULL) {
1012 /* The environment pointed to a top directory that works.
1013 */
1014 strcpy(path_buf, top);
1015 return path_buf;
1016 }
1017
1018 /* The environment didn't help. Walk up the tree from the CWD
1019 * to see if we can find the top.
1020 */
1021 char dir[PATH_MAX];
1022 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1023 if (top == NULL) {
1024 /* If the CWD isn't under a good-looking top, see if the
1025 * executable is.
1026 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001027 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 top = find_top_from(dir, path_buf);
1029 }
1030 return top;
1031}
1032
1033/* <hint> may be:
1034 * - A simple product name
1035 * e.g., "sooner"
1036TODO: debug? sooner-debug, sooner:debug?
1037 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1038 * e.g., "out/target/product/sooner"
1039 * - An absolute path to the PRODUCT_OUT dir
1040 * e.g., "/src/device/out/target/product/sooner"
1041 *
1042 * Given <hint>, try to construct an absolute path to the
1043 * ANDROID_PRODUCT_OUT dir.
1044 */
1045static const char *find_product_out_path(const char *hint)
1046{
1047 static char path_buf[PATH_MAX];
1048
1049 if (hint == NULL || hint[0] == '\0') {
1050 return NULL;
1051 }
1052
1053 /* If it's already absolute, don't bother doing any work.
1054 */
1055 if (adb_is_absolute_host_path(hint)) {
1056 strcpy(path_buf, hint);
1057 return path_buf;
1058 }
1059
1060 /* If there are any slashes in it, assume it's a relative path;
1061 * make it absolute.
1062 */
1063 if (adb_dirstart(hint) != NULL) {
1064 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1065 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1066 return NULL;
1067 }
1068 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1069 fprintf(stderr, "adb: Couldn't assemble path\n");
1070 return NULL;
1071 }
1072 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1073 strcat(path_buf, hint);
1074 return path_buf;
1075 }
1076
1077 /* It's a string without any slashes. Try to do something with it.
1078 *
1079 * Try to find the root of the build tree, and build a PRODUCT_OUT
1080 * path from there.
1081 */
1082 char top_buf[PATH_MAX];
1083 const char *top = find_top(top_buf);
1084 if (top == NULL) {
1085 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1086 return NULL;
1087 }
1088//TODO: if we have a way to indicate debug, look in out/debug/target/...
1089 snprintf(path_buf, sizeof(path_buf),
1090 "%s" OS_PATH_SEPARATOR_STR
1091 "out" OS_PATH_SEPARATOR_STR
1092 "target" OS_PATH_SEPARATOR_STR
1093 "product" OS_PATH_SEPARATOR_STR
1094 "%s", top_buf, hint);
1095 if (access(path_buf, F_OK) < 0) {
1096 fprintf(stderr, "adb: Couldn't find a product dir "
1097 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1098 return NULL;
1099 }
1100 return path_buf;
1101}
1102
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001103static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1104 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001105 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001106 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001107
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001108 while (narg > 0) {
1109 if (!strcmp(*arg, "-p")) {
1110 *show_progress = 1;
1111 } else if (!strcmp(*arg, "-a")) {
1112 *copy_attrs = 1;
1113 } else {
1114 break;
1115 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001116 ++arg;
1117 --narg;
1118 }
1119
1120 if (narg > 0) {
1121 *path1 = *arg;
1122 ++arg;
1123 --narg;
1124 }
1125
1126 if (narg > 0) {
1127 *path2 = *arg;
1128 }
1129}
1130
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001131int adb_commandline(int argc, char **argv)
1132{
1133 char buf[4096];
1134 int no_daemon = 0;
1135 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001136 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137 int persist = 0;
1138 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139 transport_type ttype = kTransportAny;
1140 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001141 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001142
1143 /* If defined, this should be an absolute path to
1144 * the directory containing all of the various system images
1145 * for a particular product. If not defined, and the adb
1146 * command requires this information, then the user must
1147 * specify the path using "-p".
1148 */
1149 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1150 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1151 gProductOutPath = NULL;
1152 }
1153 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1154
Nick Pellydb449262009-05-07 12:48:03 -07001155 serial = getenv("ANDROID_SERIAL");
1156
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001157 /* Validate and assign the server port */
1158 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1159 int server_port = DEFAULT_ADB_PORT;
1160 if (server_port_str && strlen(server_port_str) > 0) {
1161 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001162 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001163 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001164 "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 +01001165 server_port_str);
1166 return usage();
1167 }
1168 }
1169
1170 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001171 while (argc > 0) {
1172 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001173 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001174 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 no_daemon = 1;
1176 } else if (!strcmp(argv[0], "fork-server")) {
1177 /* this is a special flag used only when the ADB client launches the ADB Server */
1178 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001179 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001180 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001181 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001182 const char *product = NULL;
1183 if (argv[0][2] == '\0') {
1184 if (argc < 2) return usage();
1185 product = argv[1];
1186 argc--;
1187 argv++;
1188 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001189 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001190 }
1191 gProductOutPath = find_product_out_path(product);
1192 if (gProductOutPath == NULL) {
1193 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1194 product);
1195 return usage();
1196 }
1197 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1198 if (isdigit(argv[0][2])) {
1199 serial = argv[0] + 2;
1200 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001201 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001202 serial = argv[1];
1203 argc--;
1204 argv++;
1205 }
1206 } else if (!strcmp(argv[0],"-d")) {
1207 ttype = kTransportUsb;
1208 } else if (!strcmp(argv[0],"-e")) {
1209 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001210 } else if (!strcmp(argv[0],"-a")) {
1211 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001212 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001213 const char *hostname = NULL;
1214 if (argv[0][2] == '\0') {
1215 if (argc < 2) return usage();
1216 hostname = argv[1];
1217 argc--;
1218 argv++;
1219 } else {
1220 hostname = argv[0] + 2;
1221 }
1222 adb_set_tcp_name(hostname);
1223
Riley Andrews98f58e82014-12-05 17:37:24 -08001224 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001225 if (argv[0][2] == '\0') {
1226 if (argc < 2) return usage();
1227 server_port_str = argv[1];
1228 argc--;
1229 argv++;
1230 } else {
1231 server_port_str = argv[0] + 2;
1232 }
1233 if (strlen(server_port_str) > 0) {
1234 server_port = (int) strtol(server_port_str, NULL, 0);
1235 if (server_port <= 0 || server_port > 65535) {
1236 fprintf(stderr,
1237 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1238 server_port_str);
1239 return usage();
1240 }
1241 } else {
1242 fprintf(stderr,
1243 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1244 return usage();
1245 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001246 } else {
1247 /* out of recognized modifiers and flags */
1248 break;
1249 }
1250 argc--;
1251 argv++;
1252 }
1253
1254 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001255 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001256
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001257 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001259 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001260 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001261 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001262 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001263 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001264 fprintf(stderr,"* could not start server *\n");
1265 }
1266 return r;
1267 }
1268
Riley Andrews98f58e82014-12-05 17:37:24 -08001269 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001270 return usage();
1271 }
1272
Riley Andrewsc8514c82014-12-05 17:32:46 -08001273 /* handle wait-for-* prefix */
1274 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1275 char* service = argv[0];
1276 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1277 if (ttype == kTransportUsb) {
1278 service = "wait-for-usb";
1279 } else if (ttype == kTransportLocal) {
1280 service = "wait-for-local";
1281 } else {
1282 service = "wait-for-any";
1283 }
1284 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001285
Riley Andrewsc8514c82014-12-05 17:32:46 -08001286 format_host_command(buf, sizeof buf, service, ttype, serial);
1287
1288 if (adb_command(buf)) {
1289 D("failure: %s *\n",adb_error());
1290 fprintf(stderr,"error: %s\n", adb_error());
1291 return 1;
1292 }
1293
1294 /* Allow a command to be run after wait-for-device,
1295 * e.g. 'adb wait-for-device shell'.
1296 */
1297 if (argc == 1) {
1298 return 0;
1299 }
1300
1301 /* Fall through */
1302 argc--;
1303 argv++;
1304 }
1305
1306 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001307 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001308 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001309 char *listopt;
1310 if (argc < 2)
1311 listopt = "";
1312 else if (argc == 2 && !strcmp(argv[1], "-l"))
1313 listopt = argv[1];
1314 else {
1315 fprintf(stderr, "Usage: adb devices [-l]\n");
1316 return 1;
1317 }
1318 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001319 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001320 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001321 printf("List of devices attached \n");
1322 printf("%s\n", tmp);
1323 return 0;
1324 } else {
1325 return 1;
1326 }
1327 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001328 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001329 char *tmp;
1330 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001331 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001332 return 1;
1333 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001334 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1335 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001336 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001337 printf("%s\n", tmp);
1338 return 0;
1339 } else {
1340 return 1;
1341 }
1342 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001343 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001344 char *tmp;
1345 if (argc > 2) {
1346 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1347 return 1;
1348 }
1349 if (argc == 2) {
1350 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1351 } else {
1352 snprintf(buf, sizeof buf, "host:disconnect:");
1353 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001354 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001355 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001356 printf("%s\n", tmp);
1357 return 0;
1358 } else {
1359 return 1;
1360 }
1361 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001362 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001363 return adb_send_emulator_command(argc, argv);
1364 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001365 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001366 int r;
1367 int fd;
1368
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001369 char h = (argv[0][0] == 'h');
1370
1371 if (h) {
1372 printf("\x1b[41;33m");
1373 fflush(stdout);
1374 }
1375
Riley Andrews98f58e82014-12-05 17:37:24 -08001376 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001377 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001378 r = interactive_shell();
1379 if (h) {
1380 printf("\x1b[0m");
1381 fflush(stdout);
1382 }
1383 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001384 }
1385
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001386 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001387 argc -= 2;
1388 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001389 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001390 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001391 strncat(buf, " ", sizeof(buf) - 1);
1392 strncat(buf, quoted, sizeof(buf) - 1);
1393 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001394 }
1395
1396 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001397 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001398 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001399 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001400 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001401 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001402 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 adb_close(fd);
1404 r = 0;
1405 } else {
1406 fprintf(stderr,"error: %s\n", adb_error());
1407 r = -1;
1408 }
1409
Riley Andrews98f58e82014-12-05 17:37:24 -08001410 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411 fprintf(stderr,"\n- waiting for device -\n");
1412 adb_sleep_ms(1000);
1413 do_cmd(ttype, serial, "wait-for-device", 0);
1414 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001415 if (h) {
1416 printf("\x1b[0m");
1417 fflush(stdout);
1418 }
JP Abgrall408fa572011-03-16 15:57:42 -07001419 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001420 return r;
1421 }
1422 }
1423 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001424 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001425 int exec_in = !strcmp(argv[0], "exec-in");
1426 int fd;
1427
1428 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1429 argc -= 2;
1430 argv += 2;
1431 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001432 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001433 strncat(buf, " ", sizeof(buf) - 1);
1434 strncat(buf, quoted, sizeof(buf) - 1);
1435 free(quoted);
1436 }
1437
1438 fd = adb_connect(buf);
1439 if (fd < 0) {
1440 fprintf(stderr, "error: %s\n", adb_error());
1441 return -1;
1442 }
1443
1444 if (exec_in) {
1445 copy_to_file(STDIN_FILENO, fd);
1446 } else {
1447 copy_to_file(fd, STDOUT_FILENO);
1448 }
1449
1450 adb_close(fd);
1451 return 0;
1452 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001453 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001454 int fd;
1455 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001456 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001457 fprintf(stderr,"* server not running *\n");
1458 return 1;
1459 }
1460 return 0;
1461 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001462 else if (!strcmp(argv[0], "sideload")) {
1463 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001464 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001465 return 1;
1466 } else {
1467 return 0;
1468 }
1469 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001470 else if (!strcmp(argv[0], "remount") ||
1471 !strcmp(argv[0], "reboot") ||
1472 !strcmp(argv[0], "reboot-bootloader") ||
1473 !strcmp(argv[0], "tcpip") ||
1474 !strcmp(argv[0], "usb") ||
1475 !strcmp(argv[0], "root") ||
1476 !strcmp(argv[0], "disable-verity") ||
1477 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001478 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001479 if (!strcmp(argv[0], "reboot-bootloader"))
1480 snprintf(command, sizeof(command), "reboot:bootloader");
1481 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001482 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001483 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001484 snprintf(command, sizeof(command), "%s:", argv[0]);
1485 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001486 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001487 read_and_dump(fd);
1488 adb_close(fd);
1489 return 0;
1490 }
1491 fprintf(stderr,"error: %s\n", adb_error());
1492 return 1;
1493 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001494 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001495 if (argc != 1) return usage();
1496 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001497 return 0;
1498 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001499 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001500 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001501 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001502 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001503 char remove = 0;
1504 char remove_all = 0;
1505 char list = 0;
1506 char no_rebind = 0;
1507
1508 // Parse options here.
1509 while (argc > 1 && argv[1][0] == '-') {
1510 if (!strcmp(argv[1], "--list"))
1511 list = 1;
1512 else if (!strcmp(argv[1], "--remove"))
1513 remove = 1;
1514 else if (!strcmp(argv[1], "--remove-all"))
1515 remove_all = 1;
1516 else if (!strcmp(argv[1], "--no-rebind"))
1517 no_rebind = 1;
1518 else {
1519 return usage();
1520 }
1521 argc--;
1522 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001523 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001524
1525 // Ensure we can only use one option at a time.
1526 if (list + remove + remove_all + no_rebind > 1) {
1527 return usage();
1528 }
1529
1530 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001531 if (reverse) {
1532 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001533 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001534 if (serial) {
1535 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1536 serial);
1537 } else if (ttype == kTransportUsb) {
1538 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1539 } else if (ttype == kTransportLocal) {
1540 snprintf(host_prefix, sizeof host_prefix, "host-local");
1541 } else {
1542 snprintf(host_prefix, sizeof host_prefix, "host");
1543 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001544 }
1545
1546 // Implement forward --list
1547 if (list) {
1548 if (argc != 1)
1549 return usage();
1550 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1551 char* forwards = adb_query(buf);
1552 if (forwards == NULL) {
1553 fprintf(stderr, "error: %s\n", adb_error());
1554 return 1;
1555 }
1556 printf("%s", forwards);
1557 free(forwards);
1558 return 0;
1559 }
1560
1561 // Implement forward --remove-all
1562 else if (remove_all) {
1563 if (argc != 1)
1564 return usage();
1565 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1566 }
1567
1568 // Implement forward --remove <local>
1569 else if (remove) {
1570 if (argc != 2)
1571 return usage();
1572 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1573 }
1574 // Or implement one of:
1575 // forward <local> <remote>
1576 // forward --no-rebind <local> <remote>
1577 else
1578 {
1579 if (argc != 3)
1580 return usage();
1581 const char* command = no_rebind ? "forward:norebind:" : "forward";
1582 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1583 }
1584
Riley Andrews98f58e82014-12-05 17:37:24 -08001585 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001586 fprintf(stderr,"error: %s\n", adb_error());
1587 return 1;
1588 }
1589 return 0;
1590 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001591 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001592 else if (!strcmp(argv[0], "ls")) {
1593 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001594 return do_sync_ls(argv[1]);
1595 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001596 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001597 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001598 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001599 const char* lpath = NULL, *rpath = NULL;
1600
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001601 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001602
1603 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001604 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001605 }
1606
1607 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001608 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001609 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001610 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001611 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001612 const char* rpath = NULL, *lpath = ".";
1613
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001614 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001615
1616 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001617 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001618 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001619
1620 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001621 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001622 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 if (argc < 2) return usage();
1624 return install_app(ttype, serial, argc, argv);
1625 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001626 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001627 if (argc < 2) return usage();
1628 return install_multiple_app(ttype, serial, argc, argv);
1629 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001630 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001631 if (argc < 2) return usage();
1632 return uninstall_app(ttype, serial, argc, argv);
1633 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001634 else if (!strcmp(argv[0], "sync")) {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001635 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001636 int listonly = 0;
1637
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001638 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001639 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001640 /* No local path was specified. */
1641 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001642 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1643 listonly = 1;
1644 if (argc == 3) {
1645 srcarg = argv[2];
1646 } else {
1647 srcarg = NULL;
1648 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001649 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001650 /* A local path or "android"/"data" arg was specified. */
1651 srcarg = argv[1];
1652 } else {
1653 return usage();
1654 }
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001655 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001656 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001657
Riley Andrews98f58e82014-12-05 17:37:24 -08001658 if (android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001659 ret = do_sync_sync(android_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001660 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001661 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001662 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001663 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001664
1665 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001666 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001667 free(data_srcpath);
1668 return ret;
1669 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001670 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001671 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001672 !strcmp(argv[0],"get-serialno") ||
1673 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001674 {
1675 char *tmp;
1676
1677 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1678 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001679 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680 printf("%s\n", tmp);
1681 return 0;
1682 } else {
1683 return 1;
1684 }
1685 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001686 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001687 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 status_window(ttype, serial);
1689 return 0;
1690 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001691 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001692 return logcat(ttype, serial, argc, argv);
1693 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001694 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001695 return ppp(argc, argv);
1696 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001697 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001698 return adb_connect("host:start-server");
1699 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001700 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001701 return backup(argc, argv);
1702 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001703 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001704 return restore(argc, argv);
1705 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001706 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001707 if (argc < 2) return usage();
1708 return adb_auth_keygen(argv[1]);
1709 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001710 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001711 int fd = adb_connect("jdwp");
1712 if (fd >= 0) {
1713 read_and_dump(fd);
1714 adb_close(fd);
1715 return 0;
1716 } else {
1717 fprintf(stderr, "error: %s\n", adb_error());
1718 return -1;
1719 }
1720 }
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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001736static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1737{
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001738 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,
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001772 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001773{
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001774 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1775 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001776
1777 if(srcarg == NULL) {
1778 android_srcdir = product_file("system");
1779 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001780 vendor_srcdir = product_file("vendor");
1781 /* Check if vendor partition exists */
1782 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1783 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001784 } else {
1785 /* srcarg may be "data", "system" or NULL.
1786 * if srcarg is NULL, then both data and system are synced
1787 */
1788 if(strcmp(srcarg, "system") == 0) {
1789 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001790 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001791 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001792 } else if(strcmp(srcarg, "vendor") == 0) {
1793 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001794 } else {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001795 /* It's not "system", "vendor", or "data".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001796 */
1797 return 1;
1798 }
1799 }
1800
1801 if(android_srcdir_out != NULL)
1802 *android_srcdir_out = android_srcdir;
1803 else
1804 free(android_srcdir);
1805
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001806 if(vendor_srcdir_out != NULL)
1807 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001808 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001809 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001810
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001811 if(data_srcdir_out != NULL)
1812 *data_srcdir_out = data_srcdir;
1813 else
1814 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001815 return 0;
1816}
1817
1818static int pm_command(transport_type transport, char* serial,
1819 int argc, char** argv)
1820{
1821 char buf[4096];
1822
1823 snprintf(buf, sizeof(buf), "shell:pm");
1824
1825 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001826 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001827 strncat(buf, " ", sizeof(buf) - 1);
1828 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001829 free(quoted);
1830 }
1831
1832 send_shellcommand(transport, serial, buf);
1833 return 0;
1834}
1835
1836int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1837{
1838 /* if the user choose the -k option, we refuse to do it until devices are
1839 out with the option to uninstall the remaining data somehow (adb/ui) */
1840 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1841 {
1842 printf(
1843 "The -k option uninstalls the application while retaining the data/cache.\n"
1844 "At the moment, there is no way to remove the remaining data.\n"
1845 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1846 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1847 return -1;
1848 }
1849
1850 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1851 return pm_command(transport, serial, argc, argv);
1852}
1853
1854static int delete_file(transport_type transport, char* serial, char* filename)
1855{
1856 char buf[4096];
1857 char* quoted;
1858
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001859 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001860 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001861 strncat(buf, quoted, sizeof(buf)-1);
1862 free(quoted);
1863
1864 send_shellcommand(transport, serial, buf);
1865 return 0;
1866}
1867
Kenny Root597ea5b2011-08-05 11:19:45 -07001868static const char* get_basename(const char* filename)
1869{
1870 const char* basename = adb_dirstop(filename);
1871 if (basename) {
1872 basename++;
1873 return basename;
1874 } else {
1875 return filename;
1876 }
1877}
1878
Kenny Root597ea5b2011-08-05 11:19:45 -07001879int install_app(transport_type transport, char* serial, int argc, char** argv)
1880{
1881 static const char *const DATA_DEST = "/data/local/tmp/%s";
1882 static const char *const SD_DEST = "/sdcard/tmp/%s";
1883 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001884 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001885 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001886
1887 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001888 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001889 where = SD_DEST;
1890 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001891 }
1892
Jeff Sharkey960df972014-06-09 17:30:57 -07001893 // Find last APK argument.
1894 // All other arguments passed through verbatim.
1895 int last_apk = -1;
1896 for (i = argc - 1; i >= 0; i--) {
1897 char* file = argv[i];
1898 char* dot = strrchr(file, '.');
1899 if (dot && !strcasecmp(dot, ".apk")) {
1900 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1901 fprintf(stderr, "Invalid APK file: %s\n", file);
1902 return -1;
1903 }
1904
1905 last_apk = i;
1906 break;
1907 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001908 }
1909
Jeff Sharkey960df972014-06-09 17:30:57 -07001910 if (last_apk == -1) {
1911 fprintf(stderr, "Missing APK file\n");
1912 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001913 }
1914
Jeff Sharkey960df972014-06-09 17:30:57 -07001915 char* apk_file = argv[last_apk];
1916 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001917 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001918 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001919 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001920 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001921 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001922 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001923 }
1924
1925 pm_command(transport, serial, argc, argv);
1926
Kenny Root60733e92012-03-26 16:14:02 -07001927cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001928 delete_file(transport, serial, apk_dest);
1929 return err;
1930}
1931
1932int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1933{
1934 char buf[1024];
1935 int i;
1936 struct stat sb;
1937 unsigned long long total_size = 0;
1938
1939 // Find all APK arguments starting at end.
1940 // All other arguments passed through verbatim.
1941 int first_apk = -1;
1942 for (i = argc - 1; i >= 0; i--) {
1943 char* file = argv[i];
1944 char* dot = strrchr(file, '.');
1945 if (dot && !strcasecmp(dot, ".apk")) {
1946 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1947 fprintf(stderr, "Invalid APK file: %s\n", file);
1948 return -1;
1949 }
1950
1951 total_size += sb.st_size;
1952 first_apk = i;
1953 } else {
1954 break;
1955 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001956 }
1957
Jeff Sharkey960df972014-06-09 17:30:57 -07001958 if (first_apk == -1) {
1959 fprintf(stderr, "Missing APK file\n");
1960 return 1;
1961 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001962
Jeff Sharkey960df972014-06-09 17:30:57 -07001963 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1964 for (i = 1; i < first_apk; i++) {
1965 char *quoted = escape_arg(argv[i]);
1966 strncat(buf, " ", sizeof(buf) - 1);
1967 strncat(buf, quoted, sizeof(buf) - 1);
1968 free(quoted);
1969 }
1970
1971 // Create install session
1972 int fd = adb_connect(buf);
1973 if (fd < 0) {
1974 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1975 return -1;
1976 }
1977 read_status_line(fd, buf, sizeof(buf));
1978 adb_close(fd);
1979
1980 int session_id = -1;
1981 if (!strncmp("Success", buf, 7)) {
1982 char* start = strrchr(buf, '[');
1983 char* end = strrchr(buf, ']');
1984 if (start && end) {
1985 *end = '\0';
1986 session_id = strtol(start + 1, NULL, 10);
1987 }
1988 }
1989 if (session_id < 0) {
1990 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001991 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001992 return -1;
1993 }
1994
1995 // Valid session, now stream the APKs
1996 int success = 1;
1997 for (i = first_apk; i < argc; i++) {
1998 char* file = argv[i];
1999 if (stat(file, &sb) == -1) {
2000 fprintf(stderr, "Failed to stat %s\n", file);
2001 success = 0;
2002 goto finalize_session;
2003 }
2004
2005 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002006 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002007
2008 int localFd = adb_open(file, O_RDONLY);
2009 if (localFd < 0) {
2010 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2011 success = 0;
2012 goto finalize_session;
2013 }
2014
2015 int remoteFd = adb_connect(buf);
2016 if (remoteFd < 0) {
2017 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2018 adb_close(localFd);
2019 success = 0;
2020 goto finalize_session;
2021 }
2022
2023 copy_to_file(localFd, remoteFd);
2024 read_status_line(remoteFd, buf, sizeof(buf));
2025
2026 adb_close(localFd);
2027 adb_close(remoteFd);
2028
2029 if (strncmp("Success", buf, 7)) {
2030 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002031 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002032 success = 0;
2033 goto finalize_session;
2034 }
2035 }
2036
2037finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002038 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002039 if (success) {
2040 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2041 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002042 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002043 }
2044
2045 fd = adb_connect(buf);
2046 if (fd < 0) {
2047 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2048 return -1;
2049 }
2050 read_status_line(fd, buf, sizeof(buf));
2051 adb_close(fd);
2052
2053 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002054 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002055 return 0;
2056 } else {
2057 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002058 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002059 return -1;
2060 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002061}