blob: 830f2900e4fded543374213ff676929b05c5cdf4 [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 Lockwoodcbbe79ad2010-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 Lockwoodcbbe79ad2010-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"
Dan Pasanen98858812014-10-06 12:57:20 -0500213 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800214 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000215 " 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 -0800216 "networking:\n"
217 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500218 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800219 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
220 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
221 "\n"
222 "adb sync notes: adb sync [ <directory> ]\n"
223 " <localdir> can be interpreted in several ways:\n"
224 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700225 " - 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 -0800226 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700227 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000229 "\n"
230 "environmental variables:\n"
231 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
232 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
233 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
234 " 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 -0800235 );
236}
237
238int usage()
239{
240 help();
241 return 1;
242}
243
Yabin Cuid325e862014-11-17 14:48:25 -0800244#if defined(_WIN32)
245
246// Windows does not have <termio.h>.
247static void stdin_raw_init(int fd) {
248
249}
250
251static void stdin_raw_restore(int fd) {
252
253}
254
255#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256static struct termios tio_save;
257
258static void stdin_raw_init(int fd)
259{
260 struct termios tio;
261
262 if(tcgetattr(fd, &tio)) return;
263 if(tcgetattr(fd, &tio_save)) return;
264
265 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
266
267 /* no timeout but request at least one character per read */
268 tio.c_cc[VTIME] = 0;
269 tio.c_cc[VMIN] = 1;
270
271 tcsetattr(fd, TCSANOW, &tio);
272 tcflush(fd, TCIFLUSH);
273}
274
275static void stdin_raw_restore(int fd)
276{
277 tcsetattr(fd, TCSANOW, &tio_save);
278 tcflush(fd, TCIFLUSH);
279}
280#endif
281
282static void read_and_dump(int fd)
283{
284 char buf[4096];
285 int len;
286
287 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700288 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800289 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700290 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 if(len == 0) {
292 break;
293 }
294
295 if(len < 0) {
296 if(errno == EINTR) continue;
297 break;
298 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400299 fwrite(buf, 1, len, stdout);
300 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301 }
302}
303
Jeff Sharkey960df972014-06-09 17:30:57 -0700304static void read_status_line(int fd, char* buf, size_t count)
305{
306 count--;
307 while (count > 0) {
308 int len = adb_read(fd, buf, count);
309 if (len == 0) {
310 break;
311 } else if (len < 0) {
312 if (errno == EINTR) continue;
313 break;
314 }
315
316 buf += len;
317 count -= len;
318 }
319 *buf = '\0';
320}
321
Christopher Tated2f54152011-04-21 12:53:28 -0700322static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700323 const size_t BUFSIZE = 32 * 1024;
324 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700325 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700326 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700327
328 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800329
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700330 if (inFd == STDIN_FILENO) {
331 stdin_raw_init(STDIN_FILENO);
332 }
Yabin Cuid325e862014-11-17 14:48:25 -0800333
Christopher Tated2f54152011-04-21 12:53:28 -0700334 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700335 if (inFd == STDIN_FILENO) {
336 len = unix_read(inFd, buf, BUFSIZE);
337 } else {
338 len = adb_read(inFd, buf, BUFSIZE);
339 }
Christopher Tated2f54152011-04-21 12:53:28 -0700340 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700341 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700342 break;
343 }
344 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700345 if (errno == EINTR) {
346 D("copy_to_file() : EINTR, retrying\n");
347 continue;
348 }
Christopher Tated2f54152011-04-21 12:53:28 -0700349 D("copy_to_file() : error %d\n", errno);
350 break;
351 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700352 if (outFd == STDOUT_FILENO) {
353 fwrite(buf, 1, len, stdout);
354 fflush(stdout);
355 } else {
356 adb_write(outFd, buf, len);
357 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700358 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700359 }
Yabin Cuid325e862014-11-17 14:48:25 -0800360
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700361 if (inFd == STDIN_FILENO) {
362 stdin_raw_restore(STDIN_FILENO);
363 }
Yabin Cuid325e862014-11-17 14:48:25 -0800364
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700365 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700366 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700367}
368
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369static void *stdin_read_thread(void *x)
370{
371 int fd, fdi;
372 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 int r, n;
374 int state = 0;
375
376 int *fds = (int*) x;
377 fd = fds[0];
378 fdi = fds[1];
379 free(fds);
380
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800381 for(;;) {
382 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700383 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800384 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700385 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386 if(r == 0) break;
387 if(r < 0) {
388 if(errno == EINTR) continue;
389 break;
390 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400391 for(n = 0; n < r; n++){
392 switch(buf[n]) {
393 case '\n':
394 state = 1;
395 break;
396 case '\r':
397 state = 1;
398 break;
399 case '~':
400 if(state == 1) state++;
401 break;
402 case '.':
403 if(state == 2) {
404 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400405 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400406 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400408 default:
409 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 r = adb_write(fd, buf, r);
413 if(r <= 0) {
414 break;
415 }
416 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800417 return 0;
418}
419
420int interactive_shell(void)
421{
422 adb_thread_t thr;
423 int fdi, fd;
424 int *fds;
425
426 fd = adb_connect("shell:");
427 if(fd < 0) {
428 fprintf(stderr,"error: %s\n", adb_error());
429 return 1;
430 }
431 fdi = 0; //dup(0);
432
433 fds = malloc(sizeof(int) * 2);
434 fds[0] = fd;
435 fds[1] = fdi;
436
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 adb_thread_create(&thr, stdin_read_thread, fds);
439 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 return 0;
442}
443
444
445static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
446{
447 if (serial) {
448 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
449 } else {
450 const char* prefix = "host";
451 if (ttype == kTransportUsb)
452 prefix = "host-usb";
453 else if (ttype == kTransportLocal)
454 prefix = "host-local";
455
456 snprintf(buffer, buflen, "%s:%s", prefix, command);
457 }
458}
459
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100460int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800461 unsigned progress)
462{
463 char buf[4096];
464 unsigned total;
465 int fd;
466 const unsigned char *ptr;
467
468 sprintf(buf,"%s:%d", service, sz);
469 fd = adb_connect(buf);
470 if(fd < 0) {
471 fprintf(stderr,"error: %s\n", adb_error());
472 return -1;
473 }
474
475 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800476 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800477
478 total = sz;
479 ptr = data;
480
481 if(progress) {
482 char *x = strrchr(service, ':');
483 if(x) service = x + 1;
484 }
485
486 while(sz > 0) {
487 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
488 if(writex(fd, ptr, xfer)) {
489 adb_status(fd);
490 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
491 return -1;
492 }
493 sz -= xfer;
494 ptr += xfer;
495 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100496 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800497 fflush(stdout);
498 }
499 }
500 if(progress) {
501 printf("\n");
502 }
503
504 if(readx(fd, buf, 4)){
505 fprintf(stderr,"* error reading response *\n");
506 adb_close(fd);
507 return -1;
508 }
509 if(memcmp(buf, "OKAY", 4)) {
510 buf[4] = 0;
511 fprintf(stderr,"* error response '%s' *\n", buf);
512 adb_close(fd);
513 return -1;
514 }
515
516 adb_close(fd);
517 return 0;
518}
519
520
521int adb_download(const char *service, const char *fn, unsigned progress)
522{
523 void *data;
524 unsigned sz;
525
526 data = load_file(fn, &sz);
527 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100528 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800529 return -1;
530 }
531
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100532 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800533 free(data);
534 return status;
535}
536
Doug Zongker71fe5842014-06-26 15:35:36 -0700537#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
538
539/*
540 * The sideload-host protocol serves the data in a file (given on the
541 * command line) to the client, using a simple protocol:
542 *
543 * - The connect message includes the total number of bytes in the
544 * file and a block size chosen by us.
545 *
546 * - The other side sends the desired block number as eight decimal
547 * digits (eg "00000023" for block 23). Blocks are numbered from
548 * zero.
549 *
550 * - We send back the data of the requested block. The last block is
551 * likely to be partial; when the last block is requested we only
552 * send the part of the block that exists, it's not padded up to the
553 * block size.
554 *
555 * - When the other side sends "DONEDONE" instead of a block number,
556 * we hang up.
557 */
558int adb_sideload_host(const char* fn) {
559 uint8_t* data;
560 unsigned sz;
561 size_t xfer = 0;
562 int status;
563
564 printf("loading: '%s'", fn);
565 fflush(stdout);
566 data = load_file(fn, &sz);
567 if (data == 0) {
568 printf("\n");
569 fprintf(stderr, "* cannot read '%s' *\n", fn);
570 return -1;
571 }
572
573 char buf[100];
574 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
575 int fd = adb_connect(buf);
576 if (fd < 0) {
577 // Try falling back to the older sideload method. Maybe this
578 // is an older device that doesn't support sideload-host.
579 printf("\n");
580 status = adb_download_buffer("sideload", fn, data, sz, 1);
581 goto done;
582 }
583
584 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800585 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700586
587 int last_percent = -1;
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700588 for (;;) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700589 if (readx(fd, buf, 8)) {
590 fprintf(stderr, "* failed to read command: %s\n", adb_error());
591 status = -1;
592 goto done;
593 }
594
595 if (strncmp("DONEDONE", buf, 8) == 0) {
596 status = 0;
597 break;
598 }
599
600 buf[8] = '\0';
601 int block = strtol(buf, NULL, 10);
602
603 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
604 if (offset >= sz) {
605 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
606 status = -1;
607 goto done;
608 }
609 uint8_t* start = data + offset;
610 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
611 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
612 if (offset_end > sz) {
613 to_write = sz - offset;
614 }
615
616 if(writex(fd, start, to_write)) {
617 adb_status(fd);
618 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
619 status = -1;
620 goto done;
621 }
622 xfer += to_write;
623
624 // For normal OTA packages, we expect to transfer every byte
625 // twice, plus a bit of overhead (one read during
626 // verification, one read of each byte for installation, plus
627 // extra access to things like the zip central directory).
628 // This estimate of the completion becomes 100% when we've
629 // transferred ~2.13 (=100/47) times the package size.
630 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
631 if (percent != last_percent) {
632 printf("\rserving: '%s' (~%d%%) ", fn, percent);
633 fflush(stdout);
634 last_percent = percent;
635 }
636 }
637
Colin Cross6d6a8982014-07-07 14:12:41 -0700638 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700639
640 done:
641 if (fd >= 0) adb_close(fd);
642 free(data);
643 return status;
644}
645
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800646static void status_window(transport_type ttype, const char* serial)
647{
648 char command[4096];
649 char *state = 0;
650 char *laststate = 0;
651
652 /* silence stderr */
653#ifdef _WIN32
654 /* XXX: TODO */
655#else
656 int fd;
657 fd = unix_open("/dev/null", O_WRONLY);
658 dup2(fd, 2);
659 adb_close(fd);
660#endif
661
662 format_host_command(command, sizeof command, "get-state", ttype, serial);
663
664 for(;;) {
665 adb_sleep_ms(250);
666
667 if(state) {
668 free(state);
669 state = 0;
670 }
671
672 state = adb_query(command);
673
674 if(state) {
675 if(laststate && !strcmp(state,laststate)){
676 continue;
677 } else {
678 if(laststate) free(laststate);
679 laststate = strdup(state);
680 }
681 }
682
683 printf("%c[2J%c[2H", 27, 27);
684 printf("Android Debug Bridge\n");
685 printf("State: %s\n", state ? state : "offline");
686 fflush(stdout);
687 }
688}
689
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700690static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700691{
692 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
693}
694
695/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700696static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697{
698 const char *ts;
699 size_t alloc_len;
700 char *ret;
701 char *dest;
702
Jeff Sharkey7c460352014-06-10 16:22:17 -0700703 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700704 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800705 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700706 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800707 alloc_len++;
708 }
709 }
710
Jeff Sharkey7c460352014-06-10 16:22:17 -0700711 if (alloc_len == 0) {
712 // Preserve empty arguments
713 ret = (char *) malloc(3);
714 ret[0] = '\"';
715 ret[1] = '\"';
716 ret[2] = '\0';
717 return ret;
718 }
719
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700720 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 dest = ret;
722
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700723 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700724 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725 *dest++ = '\\';
726 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800727 *dest++ = *ts;
728 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800729 *dest++ = '\0';
730
731 return ret;
732}
733
734/**
735 * Run ppp in "notty" mode against a resource listed as the first parameter
736 * eg:
737 *
738 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
739 *
740 */
741int ppp(int argc, char **argv)
742{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800743#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800744 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
745 return -1;
746#else
747 char *adb_service_name;
748 pid_t pid;
749 int fd;
750
751 if (argc < 2) {
752 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
753 argv[0]);
754
755 return 1;
756 }
757
758 adb_service_name = argv[1];
759
760 fd = adb_connect(adb_service_name);
761
762 if(fd < 0) {
763 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
764 adb_service_name, adb_error());
765 return 1;
766 }
767
768 pid = fork();
769
770 if (pid < 0) {
771 perror("from fork()");
772 return 1;
773 } else if (pid == 0) {
774 int err;
775 int i;
776 const char **ppp_args;
777
778 // copy args
779 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
780 ppp_args[0] = "pppd";
781 for (i = 2 ; i < argc ; i++) {
782 //argv[2] and beyond become ppp_args[1] and beyond
783 ppp_args[i - 1] = argv[i];
784 }
785 ppp_args[i-1] = NULL;
786
787 // child side
788
789 dup2(fd, STDIN_FILENO);
790 dup2(fd, STDOUT_FILENO);
791 adb_close(STDERR_FILENO);
792 adb_close(fd);
793
794 err = execvp("pppd", (char * const *)ppp_args);
795
796 if (err < 0) {
797 perror("execing pppd");
798 }
799 exit(-1);
800 } else {
801 // parent side
802
803 adb_close(fd);
804 return 0;
805 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800806#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800807}
808
809static int send_shellcommand(transport_type transport, char* serial, char* buf)
810{
811 int fd, ret;
812
813 for(;;) {
814 fd = adb_connect(buf);
815 if(fd >= 0)
816 break;
817 fprintf(stderr,"- waiting for device -\n");
818 adb_sleep_ms(1000);
819 do_cmd(transport, serial, "wait-for-device", 0);
820 }
821
822 read_and_dump(fd);
823 ret = adb_close(fd);
824 if (ret)
825 perror("close");
826
827 return ret;
828}
829
830static int logcat(transport_type transport, char* serial, int argc, char **argv)
831{
832 char buf[4096];
833
834 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700835 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836
837 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700838 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800839 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700840 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700841 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800842
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700843 if (!strcmp(argv[0], "longcat")) {
844 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800845 }
846
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800847 argc -= 1;
848 argv += 1;
849 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700850 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700851 strncat(buf, " ", sizeof(buf) - 1);
852 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853 free(quoted);
854 }
855
856 send_shellcommand(transport, serial, buf);
857 return 0;
858}
859
Mark Salyzyn60299df2014-04-30 09:10:31 -0700860static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800861{
862 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700863 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800864
865 for(;;) {
866 x = adb_dirstart(x);
867 if(x == 0) return 0;
868 *x = 0;
869 ret = adb_mkdir(path, 0775);
870 *x = OS_PATH_SEPARATOR;
871 if((ret < 0) && (errno != EEXIST)) {
872 return ret;
873 }
874 x++;
875 }
876 return 0;
877}
878
Christopher Tated2f54152011-04-21 12:53:28 -0700879static int backup(int argc, char** argv) {
880 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800881 char default_name[32];
882 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700883 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700884 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700885
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700886 /* find, extract, and use any -f argument */
887 for (i = 1; i < argc; i++) {
888 if (!strcmp("-f", argv[i])) {
889 if (i == argc-1) {
890 fprintf(stderr, "adb: -f passed with no filename\n");
891 return usage();
892 }
893 filename = argv[i+1];
894 for (j = i+2; j <= argc; ) {
895 argv[i++] = argv[j++];
896 }
897 argc -= 2;
898 argv[argc] = NULL;
899 }
Christopher Tated2f54152011-04-21 12:53:28 -0700900 }
901
Christopher Tatebb86bc52011-08-22 17:12:08 -0700902 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
903 if (argc < 2) return usage();
904
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800905 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700906 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800907 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700908 if (outFd < 0) {
909 fprintf(stderr, "adb: unable to open file %s\n", filename);
910 return -1;
911 }
912
913 snprintf(buf, sizeof(buf), "backup");
914 for (argc--, argv++; argc; argc--, argv++) {
915 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
916 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
917 }
918
919 D("backup. filename=%s buf=%s\n", filename, buf);
920 fd = adb_connect(buf);
921 if (fd < 0) {
922 fprintf(stderr, "adb: unable to connect for backup\n");
923 adb_close(outFd);
924 return -1;
925 }
926
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800927 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700928 copy_to_file(fd, outFd);
929
930 adb_close(fd);
931 adb_close(outFd);
932 return 0;
933}
934
Christopher Tate702967a2011-05-17 15:52:54 -0700935static int restore(int argc, char** argv) {
936 const char* filename;
937 int fd, tarFd;
938
939 if (argc != 2) return usage();
940
941 filename = argv[1];
942 tarFd = adb_open(filename, O_RDONLY);
943 if (tarFd < 0) {
944 fprintf(stderr, "adb: unable to open file %s\n", filename);
945 return -1;
946 }
947
948 fd = adb_connect("restore:");
949 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700950 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700951 adb_close(tarFd);
952 return -1;
953 }
954
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800955 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700956 copy_to_file(tarFd, fd);
957
958 adb_close(fd);
959 adb_close(tarFd);
960 return 0;
961}
962
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800963#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
964static int top_works(const char *top)
965{
966 if (top != NULL && adb_is_absolute_host_path(top)) {
967 char path_buf[PATH_MAX];
968 snprintf(path_buf, sizeof(path_buf),
969 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
970 return access(path_buf, F_OK) == 0;
971 }
972 return 0;
973}
974
975static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
976{
977 strcpy(path_buf, indir);
978 while (1) {
979 if (top_works(path_buf)) {
980 return path_buf;
981 }
982 char *s = adb_dirstop(path_buf);
983 if (s != NULL) {
984 *s = '\0';
985 } else {
986 path_buf[0] = '\0';
987 return NULL;
988 }
989 }
990}
991
992static char *find_top(char path_buf[PATH_MAX])
993{
994 char *top = getenv("ANDROID_BUILD_TOP");
995 if (top != NULL && top[0] != '\0') {
996 if (!top_works(top)) {
997 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
998 return NULL;
999 }
1000 } else {
1001 top = getenv("TOP");
1002 if (top != NULL && top[0] != '\0') {
1003 if (!top_works(top)) {
1004 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
1005 return NULL;
1006 }
1007 } else {
1008 top = NULL;
1009 }
1010 }
1011
1012 if (top != NULL) {
1013 /* The environment pointed to a top directory that works.
1014 */
1015 strcpy(path_buf, top);
1016 return path_buf;
1017 }
1018
1019 /* The environment didn't help. Walk up the tree from the CWD
1020 * to see if we can find the top.
1021 */
1022 char dir[PATH_MAX];
1023 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1024 if (top == NULL) {
1025 /* If the CWD isn't under a good-looking top, see if the
1026 * executable is.
1027 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001028 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001029 top = find_top_from(dir, path_buf);
1030 }
1031 return top;
1032}
1033
1034/* <hint> may be:
1035 * - A simple product name
1036 * e.g., "sooner"
1037TODO: debug? sooner-debug, sooner:debug?
1038 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1039 * e.g., "out/target/product/sooner"
1040 * - An absolute path to the PRODUCT_OUT dir
1041 * e.g., "/src/device/out/target/product/sooner"
1042 *
1043 * Given <hint>, try to construct an absolute path to the
1044 * ANDROID_PRODUCT_OUT dir.
1045 */
1046static const char *find_product_out_path(const char *hint)
1047{
1048 static char path_buf[PATH_MAX];
1049
1050 if (hint == NULL || hint[0] == '\0') {
1051 return NULL;
1052 }
1053
1054 /* If it's already absolute, don't bother doing any work.
1055 */
1056 if (adb_is_absolute_host_path(hint)) {
1057 strcpy(path_buf, hint);
1058 return path_buf;
1059 }
1060
1061 /* If there are any slashes in it, assume it's a relative path;
1062 * make it absolute.
1063 */
1064 if (adb_dirstart(hint) != NULL) {
1065 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1066 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1067 return NULL;
1068 }
1069 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1070 fprintf(stderr, "adb: Couldn't assemble path\n");
1071 return NULL;
1072 }
1073 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1074 strcat(path_buf, hint);
1075 return path_buf;
1076 }
1077
1078 /* It's a string without any slashes. Try to do something with it.
1079 *
1080 * Try to find the root of the build tree, and build a PRODUCT_OUT
1081 * path from there.
1082 */
1083 char top_buf[PATH_MAX];
1084 const char *top = find_top(top_buf);
1085 if (top == NULL) {
1086 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1087 return NULL;
1088 }
1089//TODO: if we have a way to indicate debug, look in out/debug/target/...
1090 snprintf(path_buf, sizeof(path_buf),
1091 "%s" OS_PATH_SEPARATOR_STR
1092 "out" OS_PATH_SEPARATOR_STR
1093 "target" OS_PATH_SEPARATOR_STR
1094 "product" OS_PATH_SEPARATOR_STR
1095 "%s", top_buf, hint);
1096 if (access(path_buf, F_OK) < 0) {
1097 fprintf(stderr, "adb: Couldn't find a product dir "
1098 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1099 return NULL;
1100 }
1101 return path_buf;
1102}
1103
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001104static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1105 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001106 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001107 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001108
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001109 while (narg > 0) {
1110 if (!strcmp(*arg, "-p")) {
1111 *show_progress = 1;
1112 } else if (!strcmp(*arg, "-a")) {
1113 *copy_attrs = 1;
1114 } else {
1115 break;
1116 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001117 ++arg;
1118 --narg;
1119 }
1120
1121 if (narg > 0) {
1122 *path1 = *arg;
1123 ++arg;
1124 --narg;
1125 }
1126
1127 if (narg > 0) {
1128 *path2 = *arg;
1129 }
1130}
1131
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001132int adb_commandline(int argc, char **argv)
1133{
1134 char buf[4096];
1135 int no_daemon = 0;
1136 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001137 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001138 int persist = 0;
1139 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001140 transport_type ttype = kTransportAny;
1141 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001142 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001143
1144 /* If defined, this should be an absolute path to
1145 * the directory containing all of the various system images
1146 * for a particular product. If not defined, and the adb
1147 * command requires this information, then the user must
1148 * specify the path using "-p".
1149 */
1150 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1151 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1152 gProductOutPath = NULL;
1153 }
1154 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1155
Nick Pellydb449262009-05-07 12:48:03 -07001156 serial = getenv("ANDROID_SERIAL");
1157
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001158 /* Validate and assign the server port */
1159 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1160 int server_port = DEFAULT_ADB_PORT;
1161 if (server_port_str && strlen(server_port_str) > 0) {
1162 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001163 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001164 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001165 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001166 server_port_str);
1167 return usage();
1168 }
1169 }
1170
1171 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001172 while (argc > 0) {
1173 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001174 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001175 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001176 no_daemon = 1;
1177 } else if (!strcmp(argv[0], "fork-server")) {
1178 /* this is a special flag used only when the ADB client launches the ADB Server */
1179 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001180 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001181 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001182 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001183 const char *product = NULL;
1184 if (argv[0][2] == '\0') {
1185 if (argc < 2) return usage();
1186 product = argv[1];
1187 argc--;
1188 argv++;
1189 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001190 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191 }
1192 gProductOutPath = find_product_out_path(product);
1193 if (gProductOutPath == NULL) {
1194 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1195 product);
1196 return usage();
1197 }
1198 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1199 if (isdigit(argv[0][2])) {
1200 serial = argv[0] + 2;
1201 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001202 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001203 serial = argv[1];
1204 argc--;
1205 argv++;
1206 }
1207 } else if (!strcmp(argv[0],"-d")) {
1208 ttype = kTransportUsb;
1209 } else if (!strcmp(argv[0],"-e")) {
1210 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001211 } else if (!strcmp(argv[0],"-a")) {
1212 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001213 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001214 const char *hostname = NULL;
1215 if (argv[0][2] == '\0') {
1216 if (argc < 2) return usage();
1217 hostname = argv[1];
1218 argc--;
1219 argv++;
1220 } else {
1221 hostname = argv[0] + 2;
1222 }
1223 adb_set_tcp_name(hostname);
1224
Riley Andrews98f58e82014-12-05 17:37:24 -08001225 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001226 if (argv[0][2] == '\0') {
1227 if (argc < 2) return usage();
1228 server_port_str = argv[1];
1229 argc--;
1230 argv++;
1231 } else {
1232 server_port_str = argv[0] + 2;
1233 }
1234 if (strlen(server_port_str) > 0) {
1235 server_port = (int) strtol(server_port_str, NULL, 0);
1236 if (server_port <= 0 || server_port > 65535) {
1237 fprintf(stderr,
1238 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1239 server_port_str);
1240 return usage();
1241 }
1242 } else {
1243 fprintf(stderr,
1244 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1245 return usage();
1246 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001247 } else {
1248 /* out of recognized modifiers and flags */
1249 break;
1250 }
1251 argc--;
1252 argv++;
1253 }
1254
1255 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001256 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001257
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001258 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001259 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001260 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001261 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001262 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001264 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001265 fprintf(stderr,"* could not start server *\n");
1266 }
1267 return r;
1268 }
1269
Riley Andrews98f58e82014-12-05 17:37:24 -08001270 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001271 return usage();
1272 }
1273
Riley Andrewsc8514c82014-12-05 17:32:46 -08001274 /* handle wait-for-* prefix */
1275 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1276 char* service = argv[0];
1277 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1278 if (ttype == kTransportUsb) {
1279 service = "wait-for-usb";
1280 } else if (ttype == kTransportLocal) {
1281 service = "wait-for-local";
1282 } else {
1283 service = "wait-for-any";
1284 }
1285 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001286
Riley Andrewsc8514c82014-12-05 17:32:46 -08001287 format_host_command(buf, sizeof buf, service, ttype, serial);
1288
1289 if (adb_command(buf)) {
1290 D("failure: %s *\n",adb_error());
1291 fprintf(stderr,"error: %s\n", adb_error());
1292 return 1;
1293 }
1294
1295 /* Allow a command to be run after wait-for-device,
1296 * e.g. 'adb wait-for-device shell'.
1297 */
1298 if (argc == 1) {
1299 return 0;
1300 }
1301
1302 /* Fall through */
1303 argc--;
1304 argv++;
1305 }
1306
1307 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001308 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001309 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001310 char *listopt;
1311 if (argc < 2)
1312 listopt = "";
1313 else if (argc == 2 && !strcmp(argv[1], "-l"))
1314 listopt = argv[1];
1315 else {
1316 fprintf(stderr, "Usage: adb devices [-l]\n");
1317 return 1;
1318 }
1319 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001321 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001322 printf("List of devices attached \n");
1323 printf("%s\n", tmp);
1324 return 0;
1325 } else {
1326 return 1;
1327 }
1328 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001329 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001330 char *tmp;
1331 if (argc != 2) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001332 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001333 return 1;
1334 }
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001335 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1336 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001337 if (tmp) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001338 printf("%s\n", tmp);
1339 return 0;
1340 } else {
1341 return 1;
1342 }
1343 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001344 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001345 char *tmp;
1346 if (argc > 2) {
1347 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1348 return 1;
1349 }
1350 if (argc == 2) {
1351 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1352 } else {
1353 snprintf(buf, sizeof buf, "host:disconnect:");
1354 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001355 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001356 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001357 printf("%s\n", tmp);
1358 return 0;
1359 } else {
1360 return 1;
1361 }
1362 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001363 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 return adb_send_emulator_command(argc, argv);
1365 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001366 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001367 int r;
1368 int fd;
1369
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001370 char h = (argv[0][0] == 'h');
1371
1372 if (h) {
1373 printf("\x1b[41;33m");
1374 fflush(stdout);
1375 }
1376
Riley Andrews98f58e82014-12-05 17:37:24 -08001377 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001378 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001379 r = interactive_shell();
1380 if (h) {
1381 printf("\x1b[0m");
1382 fflush(stdout);
1383 }
1384 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385 }
1386
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001387 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001388 argc -= 2;
1389 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001390 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001391 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001392 strncat(buf, " ", sizeof(buf) - 1);
1393 strncat(buf, quoted, sizeof(buf) - 1);
1394 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001395 }
1396
1397 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001398 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001399 fd = adb_connect(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001400 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001401 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001403 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001404 adb_close(fd);
1405 r = 0;
1406 } else {
1407 fprintf(stderr,"error: %s\n", adb_error());
1408 r = -1;
1409 }
1410
Riley Andrews98f58e82014-12-05 17:37:24 -08001411 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001412 fprintf(stderr,"\n- waiting for device -\n");
1413 adb_sleep_ms(1000);
1414 do_cmd(ttype, serial, "wait-for-device", 0);
1415 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001416 if (h) {
1417 printf("\x1b[0m");
1418 fflush(stdout);
1419 }
JP Abgrall408fa572011-03-16 15:57:42 -07001420 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001421 return r;
1422 }
1423 }
1424 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001425 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001426 int exec_in = !strcmp(argv[0], "exec-in");
1427 int fd;
1428
1429 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1430 argc -= 2;
1431 argv += 2;
1432 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001433 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001434 strncat(buf, " ", sizeof(buf) - 1);
1435 strncat(buf, quoted, sizeof(buf) - 1);
1436 free(quoted);
1437 }
1438
1439 fd = adb_connect(buf);
1440 if (fd < 0) {
1441 fprintf(stderr, "error: %s\n", adb_error());
1442 return -1;
1443 }
1444
1445 if (exec_in) {
1446 copy_to_file(STDIN_FILENO, fd);
1447 } else {
1448 copy_to_file(fd, STDOUT_FILENO);
1449 }
1450
1451 adb_close(fd);
1452 return 0;
1453 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001454 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001455 int fd;
1456 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001457 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001458 fprintf(stderr,"* server not running *\n");
1459 return 1;
1460 }
1461 return 0;
1462 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001463 else if (!strcmp(argv[0], "sideload")) {
1464 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001465 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001466 return 1;
1467 } else {
1468 return 0;
1469 }
1470 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001471 else if (!strcmp(argv[0], "remount") ||
1472 !strcmp(argv[0], "reboot") ||
1473 !strcmp(argv[0], "reboot-bootloader") ||
1474 !strcmp(argv[0], "tcpip") ||
1475 !strcmp(argv[0], "usb") ||
1476 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001477 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001478 !strcmp(argv[0], "disable-verity") ||
1479 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001480 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001481 if (!strcmp(argv[0], "reboot-bootloader"))
1482 snprintf(command, sizeof(command), "reboot:bootloader");
1483 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001484 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001485 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001486 snprintf(command, sizeof(command), "%s:", argv[0]);
1487 int fd = adb_connect(command);
Riley Andrews98f58e82014-12-05 17:37:24 -08001488 if (fd >= 0) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001489 read_and_dump(fd);
1490 adb_close(fd);
1491 return 0;
1492 }
1493 fprintf(stderr,"error: %s\n", adb_error());
1494 return 1;
1495 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001496 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001497 if (argc != 1) return usage();
1498 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001499 return 0;
1500 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001501 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001502 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001503 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001504 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001505 char remove = 0;
1506 char remove_all = 0;
1507 char list = 0;
1508 char no_rebind = 0;
1509
1510 // Parse options here.
1511 while (argc > 1 && argv[1][0] == '-') {
1512 if (!strcmp(argv[1], "--list"))
1513 list = 1;
1514 else if (!strcmp(argv[1], "--remove"))
1515 remove = 1;
1516 else if (!strcmp(argv[1], "--remove-all"))
1517 remove_all = 1;
1518 else if (!strcmp(argv[1], "--no-rebind"))
1519 no_rebind = 1;
1520 else {
1521 return usage();
1522 }
1523 argc--;
1524 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001526
1527 // Ensure we can only use one option at a time.
1528 if (list + remove + remove_all + no_rebind > 1) {
1529 return usage();
1530 }
1531
1532 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001533 if (reverse) {
1534 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001535 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001536 if (serial) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1538 serial);
1539 } else if (ttype == kTransportUsb) {
1540 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1541 } else if (ttype == kTransportLocal) {
1542 snprintf(host_prefix, sizeof host_prefix, "host-local");
1543 } else {
1544 snprintf(host_prefix, sizeof host_prefix, "host");
1545 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001546 }
1547
1548 // Implement forward --list
1549 if (list) {
1550 if (argc != 1)
1551 return usage();
1552 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1553 char* forwards = adb_query(buf);
1554 if (forwards == NULL) {
1555 fprintf(stderr, "error: %s\n", adb_error());
1556 return 1;
1557 }
1558 printf("%s", forwards);
1559 free(forwards);
1560 return 0;
1561 }
1562
1563 // Implement forward --remove-all
1564 else if (remove_all) {
1565 if (argc != 1)
1566 return usage();
1567 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1568 }
1569
1570 // Implement forward --remove <local>
1571 else if (remove) {
1572 if (argc != 2)
1573 return usage();
1574 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1575 }
1576 // Or implement one of:
1577 // forward <local> <remote>
1578 // forward --no-rebind <local> <remote>
1579 else
1580 {
1581 if (argc != 3)
1582 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001583 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001584 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1585 }
1586
Riley Andrews98f58e82014-12-05 17:37:24 -08001587 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001588 fprintf(stderr,"error: %s\n", adb_error());
1589 return 1;
1590 }
1591 return 0;
1592 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001593 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001594 else if (!strcmp(argv[0], "ls")) {
1595 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001596 return do_sync_ls(argv[1]);
1597 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001598 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001599 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001600 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001601 const char* lpath = NULL, *rpath = NULL;
1602
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001603 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001604
1605 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001606 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001607 }
1608
1609 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001610 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001611 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001612 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001613 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001614 const char* rpath = NULL, *lpath = ".";
1615
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001616 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001617
1618 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001619 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001620 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001621
1622 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001624 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 if (argc < 2) return usage();
1626 return install_app(ttype, serial, argc, argv);
1627 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001628 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001629 if (argc < 2) return usage();
1630 return install_multiple_app(ttype, serial, argc, argv);
1631 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001632 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 if (argc < 2) return usage();
1634 return uninstall_app(ttype, serial, argc, argv);
1635 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001636 else if (!strcmp(argv[0], "sync")) {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001637 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001638 int listonly = 0;
1639
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001640 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001641 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001642 /* No local path was specified. */
1643 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001644 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1645 listonly = 1;
1646 if (argc == 3) {
1647 srcarg = argv[2];
1648 } else {
1649 srcarg = NULL;
1650 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001651 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001652 /* A local path or "android"/"data" arg was specified. */
1653 srcarg = argv[1];
1654 } else {
1655 return usage();
1656 }
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001657 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001658 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001659
Riley Andrews98f58e82014-12-05 17:37:24 -08001660 if (android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001661 ret = do_sync_sync(android_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001662 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001663 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001664 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001665 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001666
1667 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001668 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001669 free(data_srcpath);
1670 return ret;
1671 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001672 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001673 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001674 !strcmp(argv[0],"get-serialno") ||
1675 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001676 {
1677 char *tmp;
1678
1679 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1680 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001681 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 printf("%s\n", tmp);
1683 return 0;
1684 } else {
1685 return 1;
1686 }
1687 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001689 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 status_window(ttype, serial);
1691 return 0;
1692 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001693 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001694 return logcat(ttype, serial, argc, argv);
1695 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001696 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001697 return ppp(argc, argv);
1698 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001699 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001700 return adb_connect("host:start-server");
1701 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001703 return backup(argc, argv);
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001706 return restore(argc, argv);
1707 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001708 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001709 if (argc < 2) return usage();
1710 return adb_auth_keygen(argv[1]);
1711 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001712 else if (!strcmp(argv[0], "jdwp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001713 int fd = adb_connect("jdwp");
1714 if (fd >= 0) {
1715 read_and_dump(fd);
1716 adb_close(fd);
1717 return 0;
1718 } else {
1719 fprintf(stderr, "error: %s\n", adb_error());
1720 return -1;
1721 }
1722 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001723 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001724 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001725 help();
1726 return 0;
1727 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001728 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001729 version(stdout);
1730 return 0;
1731 }
1732
1733 usage();
1734 return 1;
1735}
1736
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001737#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001738static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1739{
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001740 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001741 int argc;
1742 va_list ap;
1743
1744 va_start(ap, cmd);
1745 argc = 0;
1746
1747 if (serial) {
1748 argv[argc++] = "-s";
1749 argv[argc++] = serial;
1750 } else if (ttype == kTransportUsb) {
1751 argv[argc++] = "-d";
1752 } else if (ttype == kTransportLocal) {
1753 argv[argc++] = "-e";
1754 }
1755
1756 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001757 while(argc < MAX_ARGV_LENGTH &&
1758 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1759 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001760 va_end(ap);
1761
1762#if 0
1763 int n;
1764 fprintf(stderr,"argc = %d\n",argc);
1765 for(n = 0; n < argc; n++) {
1766 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1767 }
1768#endif
1769
1770 return adb_commandline(argc, argv);
1771}
1772
1773int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001774 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001775{
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001776 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1777 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001778
1779 if(srcarg == NULL) {
1780 android_srcdir = product_file("system");
1781 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001782 vendor_srcdir = product_file("vendor");
1783 /* Check if vendor partition exists */
1784 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1785 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001786 } else {
1787 /* srcarg may be "data", "system" or NULL.
1788 * if srcarg is NULL, then both data and system are synced
1789 */
1790 if(strcmp(srcarg, "system") == 0) {
1791 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001792 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001793 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001794 } else if(strcmp(srcarg, "vendor") == 0) {
1795 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001796 } else {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001797 /* It's not "system", "vendor", or "data".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001798 */
1799 return 1;
1800 }
1801 }
1802
1803 if(android_srcdir_out != NULL)
1804 *android_srcdir_out = android_srcdir;
1805 else
1806 free(android_srcdir);
1807
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001808 if(vendor_srcdir_out != NULL)
1809 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001810 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001811 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001812
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001813 if(data_srcdir_out != NULL)
1814 *data_srcdir_out = data_srcdir;
1815 else
1816 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001817 return 0;
1818}
1819
1820static int pm_command(transport_type transport, char* serial,
1821 int argc, char** argv)
1822{
1823 char buf[4096];
1824
1825 snprintf(buf, sizeof(buf), "shell:pm");
1826
1827 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001828 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001829 strncat(buf, " ", sizeof(buf) - 1);
1830 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001831 free(quoted);
1832 }
1833
1834 send_shellcommand(transport, serial, buf);
1835 return 0;
1836}
1837
1838int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1839{
1840 /* if the user choose the -k option, we refuse to do it until devices are
1841 out with the option to uninstall the remaining data somehow (adb/ui) */
1842 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1843 {
1844 printf(
1845 "The -k option uninstalls the application while retaining the data/cache.\n"
1846 "At the moment, there is no way to remove the remaining data.\n"
1847 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1848 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1849 return -1;
1850 }
1851
1852 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1853 return pm_command(transport, serial, argc, argv);
1854}
1855
1856static int delete_file(transport_type transport, char* serial, char* filename)
1857{
1858 char buf[4096];
1859 char* quoted;
1860
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001861 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001862 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001863 strncat(buf, quoted, sizeof(buf)-1);
1864 free(quoted);
1865
1866 send_shellcommand(transport, serial, buf);
1867 return 0;
1868}
1869
Kenny Root597ea5b2011-08-05 11:19:45 -07001870static const char* get_basename(const char* filename)
1871{
1872 const char* basename = adb_dirstop(filename);
1873 if (basename) {
1874 basename++;
1875 return basename;
1876 } else {
1877 return filename;
1878 }
1879}
1880
Kenny Root597ea5b2011-08-05 11:19:45 -07001881int install_app(transport_type transport, char* serial, int argc, char** argv)
1882{
1883 static const char *const DATA_DEST = "/data/local/tmp/%s";
1884 static const char *const SD_DEST = "/sdcard/tmp/%s";
1885 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001886 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001887 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001888
1889 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001890 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001891 where = SD_DEST;
1892 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001893 }
1894
Jeff Sharkey960df972014-06-09 17:30:57 -07001895 // Find last APK argument.
1896 // All other arguments passed through verbatim.
1897 int last_apk = -1;
1898 for (i = argc - 1; i >= 0; i--) {
1899 char* file = argv[i];
1900 char* dot = strrchr(file, '.');
1901 if (dot && !strcasecmp(dot, ".apk")) {
1902 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1903 fprintf(stderr, "Invalid APK file: %s\n", file);
1904 return -1;
1905 }
1906
1907 last_apk = i;
1908 break;
1909 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001910 }
1911
Jeff Sharkey960df972014-06-09 17:30:57 -07001912 if (last_apk == -1) {
1913 fprintf(stderr, "Missing APK file\n");
1914 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001915 }
1916
Jeff Sharkey960df972014-06-09 17:30:57 -07001917 char* apk_file = argv[last_apk];
1918 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001919 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001920 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001921 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001922 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001923 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001924 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001925 }
1926
1927 pm_command(transport, serial, argc, argv);
1928
Kenny Root60733e92012-03-26 16:14:02 -07001929cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001930 delete_file(transport, serial, apk_dest);
1931 return err;
1932}
1933
1934int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1935{
1936 char buf[1024];
1937 int i;
1938 struct stat sb;
1939 unsigned long long total_size = 0;
1940
1941 // Find all APK arguments starting at end.
1942 // All other arguments passed through verbatim.
1943 int first_apk = -1;
1944 for (i = argc - 1; i >= 0; i--) {
1945 char* file = argv[i];
1946 char* dot = strrchr(file, '.');
1947 if (dot && !strcasecmp(dot, ".apk")) {
1948 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1949 fprintf(stderr, "Invalid APK file: %s\n", file);
1950 return -1;
1951 }
1952
1953 total_size += sb.st_size;
1954 first_apk = i;
1955 } else {
1956 break;
1957 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001958 }
1959
Jeff Sharkey960df972014-06-09 17:30:57 -07001960 if (first_apk == -1) {
1961 fprintf(stderr, "Missing APK file\n");
1962 return 1;
1963 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001964
Jeff Sharkey960df972014-06-09 17:30:57 -07001965 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1966 for (i = 1; i < first_apk; i++) {
1967 char *quoted = escape_arg(argv[i]);
1968 strncat(buf, " ", sizeof(buf) - 1);
1969 strncat(buf, quoted, sizeof(buf) - 1);
1970 free(quoted);
1971 }
1972
1973 // Create install session
1974 int fd = adb_connect(buf);
1975 if (fd < 0) {
1976 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1977 return -1;
1978 }
1979 read_status_line(fd, buf, sizeof(buf));
1980 adb_close(fd);
1981
1982 int session_id = -1;
1983 if (!strncmp("Success", buf, 7)) {
1984 char* start = strrchr(buf, '[');
1985 char* end = strrchr(buf, ']');
1986 if (start && end) {
1987 *end = '\0';
1988 session_id = strtol(start + 1, NULL, 10);
1989 }
1990 }
1991 if (session_id < 0) {
1992 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001993 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001994 return -1;
1995 }
1996
1997 // Valid session, now stream the APKs
1998 int success = 1;
1999 for (i = first_apk; i < argc; i++) {
2000 char* file = argv[i];
2001 if (stat(file, &sb) == -1) {
2002 fprintf(stderr, "Failed to stat %s\n", file);
2003 success = 0;
2004 goto finalize_session;
2005 }
2006
2007 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002008 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002009
2010 int localFd = adb_open(file, O_RDONLY);
2011 if (localFd < 0) {
2012 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2013 success = 0;
2014 goto finalize_session;
2015 }
2016
2017 int remoteFd = adb_connect(buf);
2018 if (remoteFd < 0) {
2019 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2020 adb_close(localFd);
2021 success = 0;
2022 goto finalize_session;
2023 }
2024
2025 copy_to_file(localFd, remoteFd);
2026 read_status_line(remoteFd, buf, sizeof(buf));
2027
2028 adb_close(localFd);
2029 adb_close(remoteFd);
2030
2031 if (strncmp("Success", buf, 7)) {
2032 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002033 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002034 success = 0;
2035 goto finalize_session;
2036 }
2037 }
2038
2039finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002040 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002041 if (success) {
2042 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2043 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002044 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002045 }
2046
2047 fd = adb_connect(buf);
2048 if (fd < 0) {
2049 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2050 return -1;
2051 }
2052 read_status_line(fd, buf, sizeof(buf));
2053 adb_close(fd);
2054
2055 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002056 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002057 return 0;
2058 } else {
2059 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002060 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002061 return -1;
2062 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002063}