blob: eea882d12f8b59b756e28c1b11df5502fbfeb411 [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
32#ifdef HAVE_TERMIO_H
33#include <termios.h>
34#endif
35
36#define TRACE_TAG TRACE_ADB
37#include "adb.h"
38#include "adb_client.h"
39#include "file_sync_service.h"
40
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
42
Alexey Tarasov31664102009-10-22 02:55:00 +110043void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080044int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -070045 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046int install_app(transport_type transport, char* serial, int argc, char** argv);
Jeff Sharkey960df972014-06-09 17:30:57 -070047int install_multiple_app(transport_type transport, char* serial, int argc, char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
49
50static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080051extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080052
53static char *product_file(const char *extra)
54{
55 int n;
56 char *x;
57
58 if (gProductOutPath == NULL) {
59 fprintf(stderr, "adb: Product directory not specified; "
60 "use -p or define ANDROID_PRODUCT_OUT\n");
61 exit(1);
62 }
63
64 n = strlen(gProductOutPath) + strlen(extra) + 2;
65 x = malloc(n);
66 if (x == 0) {
67 fprintf(stderr, "adb: Out of memory (product_file())\n");
68 exit(1);
69 }
70
71 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
72 return x;
73}
74
75void version(FILE * out) {
76 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
77 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
78}
79
80void help()
81{
82 version(stderr);
83
84 fprintf(stderr,
85 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080086 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080087 " -d - directs command to the only connected USB device\n"
88 " returns an error if more than one USB device is present.\n"
89 " -e - directs command to the only running emulator.\n"
90 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070091 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070092 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070093 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080094 " -p <product name or path> - simple product name like 'sooner', or\n"
95 " a relative/absolute path to a product\n"
96 " out directory like 'out/target/product/sooner'.\n"
97 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
98 " environment variable is used, which must\n"
99 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800100 " -H - Name of adb server host (default: localhost)\n"
101 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700102 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700103 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400104 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
105 " Port 5555 is used by default if no port number is specified.\n"
106 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
107 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200108 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400109 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800110 "\n"
111 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700112 " adb push [-p] <local> <remote>\n"
113 " - copy file/dir to device\n"
114 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700115 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700116 " - copy file/dir from device\n"
117 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700118 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600120 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 " (see 'adb help all')\n"
122 " adb shell - run remote shell interactively\n"
123 " adb shell <command> - run remote shell command\n"
124 " adb emu <command> - run emulator console command\n"
125 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100126 " adb forward --list - list all forward socket connections.\n"
127 " the format is a list of lines with the following format:\n"
128 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129 " adb forward <local> <remote> - forward socket connections\n"
130 " forward specs are one of: \n"
131 " tcp:<port>\n"
132 " localabstract:<unix domain socket name>\n"
133 " localreserved:<unix domain socket name>\n"
134 " localfilesystem:<unix domain socket name>\n"
135 " dev:<character device name>\n"
136 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100137 " adb forward --no-rebind <local> <remote>\n"
138 " - same as 'adb forward <local> <remote>' but fails\n"
139 " if <local> is already forwarded\n"
140 " adb forward --remove <local> - remove a specific forward socket connection\n"
141 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100142 " adb reverse --list - list all reverse socket connections from device\n"
143 " adb reverse <remote> <local> - reverse socket connections\n"
144 " reverse specs are one of:\n"
145 " tcp:<port>\n"
146 " localabstract:<unix domain socket name>\n"
147 " localreserved:<unix domain socket name>\n"
148 " localfilesystem:<unix domain socket name>\n"
149 " adb reverse --norebind <remote> <local>\n"
150 " - same as 'adb reverse <remote> <local>' but fails\n"
151 " if <remote> is already reversed.\n"
152 " adb reverse --remove <remote>\n"
153 " - remove a specific reversed socket connection\n"
154 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800155 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700156 " adb install [-lrtsd] <file>\n"
157 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700158 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700159 " (-l: forward lock application)\n"
160 " (-r: replace existing application)\n"
161 " (-t: allow test packages)\n"
162 " (-s: install application on sdcard)\n"
163 " (-d: allow version code downgrade)\n"
164 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165 " adb uninstall [-k] <package> - remove this app package from the device\n"
166 " ('-k' means keep the data and cache directories)\n"
167 " adb bugreport - return all information from the device\n"
168 " that should be included in a bug report.\n"
169 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800170 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700171 " - write an archive of the device's data to <file>.\n"
172 " If no -f option is supplied then the data is written\n"
173 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700174 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700175 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800176 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
177 " (aka .obb) files associated with each application; the default\n"
178 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700179 " (-shared|-noshared enable/disable backup of the device's\n"
180 " shared storage / SD card contents; the default is noshared.)\n"
181 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700182 " (-system|-nosystem toggles whether -all automatically includes\n"
183 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700184 " (<packages...> is the list of applications to be backed up. If\n"
185 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700186 " list is optional. Applications explicitly given on the\n"
187 " command line will be included even if -nosystem would\n"
188 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700189 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700190 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700191 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800192 " adb help - show this help message\n"
193 " adb version - show version num\n"
194 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800195 "scripting:\n"
196 " adb wait-for-device - block until device is online\n"
197 " adb start-server - ensure that there is a server running\n"
198 " adb kill-server - kill the server if it is running\n"
199 " adb get-state - prints: offline | bootloader | device\n"
200 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700201 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800202 " adb status-window - continuously print device status for a specified device\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700203 " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400204 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800205 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700206 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800207 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700208 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 "\n"
210 "networking:\n"
211 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500212 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800213 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
214 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
215 "\n"
216 "adb sync notes: adb sync [ <directory> ]\n"
217 " <localdir> can be interpreted in several ways:\n"
218 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700219 " - 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 -0800220 "\n"
Daniel Rosenberg686bce62014-06-30 20:29:40 -0700221 " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800222 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000223 "\n"
224 "environmental variables:\n"
225 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
226 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
227 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
228 " 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 -0800229 );
230}
231
232int usage()
233{
234 help();
235 return 1;
236}
237
238#ifdef HAVE_TERMIO_H
239static struct termios tio_save;
240
241static void stdin_raw_init(int fd)
242{
243 struct termios tio;
244
245 if(tcgetattr(fd, &tio)) return;
246 if(tcgetattr(fd, &tio_save)) return;
247
248 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
249
250 /* no timeout but request at least one character per read */
251 tio.c_cc[VTIME] = 0;
252 tio.c_cc[VMIN] = 1;
253
254 tcsetattr(fd, TCSANOW, &tio);
255 tcflush(fd, TCIFLUSH);
256}
257
258static void stdin_raw_restore(int fd)
259{
260 tcsetattr(fd, TCSANOW, &tio_save);
261 tcflush(fd, TCIFLUSH);
262}
263#endif
264
265static void read_and_dump(int fd)
266{
267 char buf[4096];
268 int len;
269
270 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700271 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700273 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274 if(len == 0) {
275 break;
276 }
277
278 if(len < 0) {
279 if(errno == EINTR) continue;
280 break;
281 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400282 fwrite(buf, 1, len, stdout);
283 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284 }
285}
286
Jeff Sharkey960df972014-06-09 17:30:57 -0700287static void read_status_line(int fd, char* buf, size_t count)
288{
289 count--;
290 while (count > 0) {
291 int len = adb_read(fd, buf, count);
292 if (len == 0) {
293 break;
294 } else if (len < 0) {
295 if (errno == EINTR) continue;
296 break;
297 }
298
299 buf += len;
300 count -= len;
301 }
302 *buf = '\0';
303}
304
Christopher Tated2f54152011-04-21 12:53:28 -0700305static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700306 const size_t BUFSIZE = 32 * 1024;
307 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700308 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700309 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700310
311 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700312#ifdef HAVE_TERMIO_H
313 if (inFd == STDIN_FILENO) {
314 stdin_raw_init(STDIN_FILENO);
315 }
316#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700317 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700318 if (inFd == STDIN_FILENO) {
319 len = unix_read(inFd, buf, BUFSIZE);
320 } else {
321 len = adb_read(inFd, buf, BUFSIZE);
322 }
Christopher Tated2f54152011-04-21 12:53:28 -0700323 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700324 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700325 break;
326 }
327 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700328 if (errno == EINTR) {
329 D("copy_to_file() : EINTR, retrying\n");
330 continue;
331 }
Christopher Tated2f54152011-04-21 12:53:28 -0700332 D("copy_to_file() : error %d\n", errno);
333 break;
334 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700335 if (outFd == STDOUT_FILENO) {
336 fwrite(buf, 1, len, stdout);
337 fflush(stdout);
338 } else {
339 adb_write(outFd, buf, len);
340 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700341 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700342 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700343#ifdef HAVE_TERMIO_H
344 if (inFd == STDIN_FILENO) {
345 stdin_raw_restore(STDIN_FILENO);
346 }
347#endif
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700348 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700349 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700350}
351
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800352static void *stdin_read_thread(void *x)
353{
354 int fd, fdi;
355 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800356 int r, n;
357 int state = 0;
358
359 int *fds = (int*) x;
360 fd = fds[0];
361 fdi = fds[1];
362 free(fds);
363
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800364 for(;;) {
365 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700366 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700368 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369 if(r == 0) break;
370 if(r < 0) {
371 if(errno == EINTR) continue;
372 break;
373 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400374 for(n = 0; n < r; n++){
375 switch(buf[n]) {
376 case '\n':
377 state = 1;
378 break;
379 case '\r':
380 state = 1;
381 break;
382 case '~':
383 if(state == 1) state++;
384 break;
385 case '.':
386 if(state == 2) {
387 fprintf(stderr,"\n* disconnect *\n");
388#ifdef HAVE_TERMIO_H
389 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800390#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400391 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800392 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400393 default:
394 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800395 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397 r = adb_write(fd, buf, r);
398 if(r <= 0) {
399 break;
400 }
401 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402 return 0;
403}
404
405int interactive_shell(void)
406{
407 adb_thread_t thr;
408 int fdi, fd;
409 int *fds;
410
411 fd = adb_connect("shell:");
412 if(fd < 0) {
413 fprintf(stderr,"error: %s\n", adb_error());
414 return 1;
415 }
416 fdi = 0; //dup(0);
417
418 fds = malloc(sizeof(int) * 2);
419 fds[0] = fd;
420 fds[1] = fdi;
421
422#ifdef HAVE_TERMIO_H
423 stdin_raw_init(fdi);
424#endif
425 adb_thread_create(&thr, stdin_read_thread, fds);
426 read_and_dump(fd);
427#ifdef HAVE_TERMIO_H
428 stdin_raw_restore(fdi);
429#endif
430 return 0;
431}
432
433
434static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
435{
436 if (serial) {
437 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
438 } else {
439 const char* prefix = "host";
440 if (ttype == kTransportUsb)
441 prefix = "host-usb";
442 else if (ttype == kTransportLocal)
443 prefix = "host-local";
444
445 snprintf(buffer, buflen, "%s:%s", prefix, command);
446 }
447}
448
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100449int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800450 unsigned progress)
451{
452 char buf[4096];
453 unsigned total;
454 int fd;
455 const unsigned char *ptr;
456
457 sprintf(buf,"%s:%d", service, sz);
458 fd = adb_connect(buf);
459 if(fd < 0) {
460 fprintf(stderr,"error: %s\n", adb_error());
461 return -1;
462 }
463
464 int opt = CHUNK_SIZE;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700465 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800466
467 total = sz;
468 ptr = data;
469
470 if(progress) {
471 char *x = strrchr(service, ':');
472 if(x) service = x + 1;
473 }
474
475 while(sz > 0) {
476 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
477 if(writex(fd, ptr, xfer)) {
478 adb_status(fd);
479 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
480 return -1;
481 }
482 sz -= xfer;
483 ptr += xfer;
484 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100485 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800486 fflush(stdout);
487 }
488 }
489 if(progress) {
490 printf("\n");
491 }
492
493 if(readx(fd, buf, 4)){
494 fprintf(stderr,"* error reading response *\n");
495 adb_close(fd);
496 return -1;
497 }
498 if(memcmp(buf, "OKAY", 4)) {
499 buf[4] = 0;
500 fprintf(stderr,"* error response '%s' *\n", buf);
501 adb_close(fd);
502 return -1;
503 }
504
505 adb_close(fd);
506 return 0;
507}
508
509
510int adb_download(const char *service, const char *fn, unsigned progress)
511{
512 void *data;
513 unsigned sz;
514
515 data = load_file(fn, &sz);
516 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100517 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800518 return -1;
519 }
520
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100521 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800522 free(data);
523 return status;
524}
525
Doug Zongker71fe5842014-06-26 15:35:36 -0700526#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
527
528/*
529 * The sideload-host protocol serves the data in a file (given on the
530 * command line) to the client, using a simple protocol:
531 *
532 * - The connect message includes the total number of bytes in the
533 * file and a block size chosen by us.
534 *
535 * - The other side sends the desired block number as eight decimal
536 * digits (eg "00000023" for block 23). Blocks are numbered from
537 * zero.
538 *
539 * - We send back the data of the requested block. The last block is
540 * likely to be partial; when the last block is requested we only
541 * send the part of the block that exists, it's not padded up to the
542 * block size.
543 *
544 * - When the other side sends "DONEDONE" instead of a block number,
545 * we hang up.
546 */
547int adb_sideload_host(const char* fn) {
548 uint8_t* data;
549 unsigned sz;
550 size_t xfer = 0;
551 int status;
552
553 printf("loading: '%s'", fn);
554 fflush(stdout);
555 data = load_file(fn, &sz);
556 if (data == 0) {
557 printf("\n");
558 fprintf(stderr, "* cannot read '%s' *\n", fn);
559 return -1;
560 }
561
562 char buf[100];
563 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
564 int fd = adb_connect(buf);
565 if (fd < 0) {
566 // Try falling back to the older sideload method. Maybe this
567 // is an older device that doesn't support sideload-host.
568 printf("\n");
569 status = adb_download_buffer("sideload", fn, data, sz, 1);
570 goto done;
571 }
572
573 int opt = SIDELOAD_HOST_BLOCK_SIZE;
574 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
575
576 int last_percent = -1;
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700577 for (;;) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700578 if (readx(fd, buf, 8)) {
579 fprintf(stderr, "* failed to read command: %s\n", adb_error());
580 status = -1;
581 goto done;
582 }
583
584 if (strncmp("DONEDONE", buf, 8) == 0) {
585 status = 0;
586 break;
587 }
588
589 buf[8] = '\0';
590 int block = strtol(buf, NULL, 10);
591
592 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
593 if (offset >= sz) {
594 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
595 status = -1;
596 goto done;
597 }
598 uint8_t* start = data + offset;
599 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
600 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
601 if (offset_end > sz) {
602 to_write = sz - offset;
603 }
604
605 if(writex(fd, start, to_write)) {
606 adb_status(fd);
607 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
608 status = -1;
609 goto done;
610 }
611 xfer += to_write;
612
613 // For normal OTA packages, we expect to transfer every byte
614 // twice, plus a bit of overhead (one read during
615 // verification, one read of each byte for installation, plus
616 // extra access to things like the zip central directory).
617 // This estimate of the completion becomes 100% when we've
618 // transferred ~2.13 (=100/47) times the package size.
619 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
620 if (percent != last_percent) {
621 printf("\rserving: '%s' (~%d%%) ", fn, percent);
622 fflush(stdout);
623 last_percent = percent;
624 }
625 }
626
Colin Cross6d6a8982014-07-07 14:12:41 -0700627 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700628
629 done:
630 if (fd >= 0) adb_close(fd);
631 free(data);
632 return status;
633}
634
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800635static void status_window(transport_type ttype, const char* serial)
636{
637 char command[4096];
638 char *state = 0;
639 char *laststate = 0;
640
641 /* silence stderr */
642#ifdef _WIN32
643 /* XXX: TODO */
644#else
645 int fd;
646 fd = unix_open("/dev/null", O_WRONLY);
647 dup2(fd, 2);
648 adb_close(fd);
649#endif
650
651 format_host_command(command, sizeof command, "get-state", ttype, serial);
652
653 for(;;) {
654 adb_sleep_ms(250);
655
656 if(state) {
657 free(state);
658 state = 0;
659 }
660
661 state = adb_query(command);
662
663 if(state) {
664 if(laststate && !strcmp(state,laststate)){
665 continue;
666 } else {
667 if(laststate) free(laststate);
668 laststate = strdup(state);
669 }
670 }
671
672 printf("%c[2J%c[2H", 27, 27);
673 printf("Android Debug Bridge\n");
674 printf("State: %s\n", state ? state : "offline");
675 fflush(stdout);
676 }
677}
678
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700679static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700680{
681 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
682}
683
684/* Duplicate and escape given argument. */
Jeff Sharkey7c460352014-06-10 16:22:17 -0700685static char *escape_arg(const char *s)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800686{
687 const char *ts;
688 size_t alloc_len;
689 char *ret;
690 char *dest;
691
Jeff Sharkey7c460352014-06-10 16:22:17 -0700692 alloc_len = 0;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700693 for (ts = s; *ts != '\0'; ts++) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800694 alloc_len++;
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700695 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696 alloc_len++;
697 }
698 }
699
Jeff Sharkey7c460352014-06-10 16:22:17 -0700700 if (alloc_len == 0) {
701 // Preserve empty arguments
702 ret = (char *) malloc(3);
703 ret[0] = '\"';
704 ret[1] = '\"';
705 ret[2] = '\0';
706 return ret;
707 }
708
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700709 ret = (char *) malloc(alloc_len + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800710 dest = ret;
711
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700712 for (ts = s; *ts != '\0'; ts++) {
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700713 if (should_escape(*ts)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800714 *dest++ = '\\';
715 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800716 *dest++ = *ts;
717 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800718 *dest++ = '\0';
719
720 return ret;
721}
722
723/**
724 * Run ppp in "notty" mode against a resource listed as the first parameter
725 * eg:
726 *
727 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
728 *
729 */
730int ppp(int argc, char **argv)
731{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800732#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800733 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
734 return -1;
735#else
736 char *adb_service_name;
737 pid_t pid;
738 int fd;
739
740 if (argc < 2) {
741 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
742 argv[0]);
743
744 return 1;
745 }
746
747 adb_service_name = argv[1];
748
749 fd = adb_connect(adb_service_name);
750
751 if(fd < 0) {
752 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
753 adb_service_name, adb_error());
754 return 1;
755 }
756
757 pid = fork();
758
759 if (pid < 0) {
760 perror("from fork()");
761 return 1;
762 } else if (pid == 0) {
763 int err;
764 int i;
765 const char **ppp_args;
766
767 // copy args
768 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
769 ppp_args[0] = "pppd";
770 for (i = 2 ; i < argc ; i++) {
771 //argv[2] and beyond become ppp_args[1] and beyond
772 ppp_args[i - 1] = argv[i];
773 }
774 ppp_args[i-1] = NULL;
775
776 // child side
777
778 dup2(fd, STDIN_FILENO);
779 dup2(fd, STDOUT_FILENO);
780 adb_close(STDERR_FILENO);
781 adb_close(fd);
782
783 err = execvp("pppd", (char * const *)ppp_args);
784
785 if (err < 0) {
786 perror("execing pppd");
787 }
788 exit(-1);
789 } else {
790 // parent side
791
792 adb_close(fd);
793 return 0;
794 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800795#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800796}
797
798static int send_shellcommand(transport_type transport, char* serial, char* buf)
799{
800 int fd, ret;
801
802 for(;;) {
803 fd = adb_connect(buf);
804 if(fd >= 0)
805 break;
806 fprintf(stderr,"- waiting for device -\n");
807 adb_sleep_ms(1000);
808 do_cmd(transport, serial, "wait-for-device", 0);
809 }
810
811 read_and_dump(fd);
812 ret = adb_close(fd);
813 if (ret)
814 perror("close");
815
816 return ret;
817}
818
819static int logcat(transport_type transport, char* serial, int argc, char **argv)
820{
821 char buf[4096];
822
823 char *log_tags;
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700824 char *quoted;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800825
826 log_tags = getenv("ANDROID_LOG_TAGS");
Jeff Sharkey7c460352014-06-10 16:22:17 -0700827 quoted = escape_arg(log_tags == NULL ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800828 snprintf(buf, sizeof(buf),
Jeff Sharkey7c460352014-06-10 16:22:17 -0700829 "shell:export ANDROID_LOG_TAGS=\"%s\"; exec logcat", quoted);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700830 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800831
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700832 if (!strcmp(argv[0], "longcat")) {
833 strncat(buf, " -v long", sizeof(buf) - 1);
Christopher Tatedb0a8802011-11-30 13:00:33 -0800834 }
835
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836 argc -= 1;
837 argv += 1;
838 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -0700839 quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700840 strncat(buf, " ", sizeof(buf) - 1);
841 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800842 free(quoted);
843 }
844
845 send_shellcommand(transport, serial, buf);
846 return 0;
847}
848
Mark Salyzyn60299df2014-04-30 09:10:31 -0700849static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800850{
851 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700852 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800853
854 for(;;) {
855 x = adb_dirstart(x);
856 if(x == 0) return 0;
857 *x = 0;
858 ret = adb_mkdir(path, 0775);
859 *x = OS_PATH_SEPARATOR;
860 if((ret < 0) && (errno != EEXIST)) {
861 return ret;
862 }
863 x++;
864 }
865 return 0;
866}
867
Christopher Tated2f54152011-04-21 12:53:28 -0700868static int backup(int argc, char** argv) {
869 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800870 char default_name[32];
871 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700872 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700873 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700874
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700875 /* find, extract, and use any -f argument */
876 for (i = 1; i < argc; i++) {
877 if (!strcmp("-f", argv[i])) {
878 if (i == argc-1) {
879 fprintf(stderr, "adb: -f passed with no filename\n");
880 return usage();
881 }
882 filename = argv[i+1];
883 for (j = i+2; j <= argc; ) {
884 argv[i++] = argv[j++];
885 }
886 argc -= 2;
887 argv[argc] = NULL;
888 }
Christopher Tated2f54152011-04-21 12:53:28 -0700889 }
890
Christopher Tatebb86bc52011-08-22 17:12:08 -0700891 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
892 if (argc < 2) return usage();
893
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800894 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700895 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800896 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700897 if (outFd < 0) {
898 fprintf(stderr, "adb: unable to open file %s\n", filename);
899 return -1;
900 }
901
902 snprintf(buf, sizeof(buf), "backup");
903 for (argc--, argv++; argc; argc--, argv++) {
904 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
905 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
906 }
907
908 D("backup. filename=%s buf=%s\n", filename, buf);
909 fd = adb_connect(buf);
910 if (fd < 0) {
911 fprintf(stderr, "adb: unable to connect for backup\n");
912 adb_close(outFd);
913 return -1;
914 }
915
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800916 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700917 copy_to_file(fd, outFd);
918
919 adb_close(fd);
920 adb_close(outFd);
921 return 0;
922}
923
Christopher Tate702967a2011-05-17 15:52:54 -0700924static int restore(int argc, char** argv) {
925 const char* filename;
926 int fd, tarFd;
927
928 if (argc != 2) return usage();
929
930 filename = argv[1];
931 tarFd = adb_open(filename, O_RDONLY);
932 if (tarFd < 0) {
933 fprintf(stderr, "adb: unable to open file %s\n", filename);
934 return -1;
935 }
936
937 fd = adb_connect("restore:");
938 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700939 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700940 adb_close(tarFd);
941 return -1;
942 }
943
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800944 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700945 copy_to_file(tarFd, fd);
946
947 adb_close(fd);
948 adb_close(tarFd);
949 return 0;
950}
951
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800952#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
953static int top_works(const char *top)
954{
955 if (top != NULL && adb_is_absolute_host_path(top)) {
956 char path_buf[PATH_MAX];
957 snprintf(path_buf, sizeof(path_buf),
958 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
959 return access(path_buf, F_OK) == 0;
960 }
961 return 0;
962}
963
964static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
965{
966 strcpy(path_buf, indir);
967 while (1) {
968 if (top_works(path_buf)) {
969 return path_buf;
970 }
971 char *s = adb_dirstop(path_buf);
972 if (s != NULL) {
973 *s = '\0';
974 } else {
975 path_buf[0] = '\0';
976 return NULL;
977 }
978 }
979}
980
981static char *find_top(char path_buf[PATH_MAX])
982{
983 char *top = getenv("ANDROID_BUILD_TOP");
984 if (top != NULL && top[0] != '\0') {
985 if (!top_works(top)) {
986 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
987 return NULL;
988 }
989 } else {
990 top = getenv("TOP");
991 if (top != NULL && top[0] != '\0') {
992 if (!top_works(top)) {
993 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
994 return NULL;
995 }
996 } else {
997 top = NULL;
998 }
999 }
1000
1001 if (top != NULL) {
1002 /* The environment pointed to a top directory that works.
1003 */
1004 strcpy(path_buf, top);
1005 return path_buf;
1006 }
1007
1008 /* The environment didn't help. Walk up the tree from the CWD
1009 * to see if we can find the top.
1010 */
1011 char dir[PATH_MAX];
1012 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
1013 if (top == NULL) {
1014 /* If the CWD isn't under a good-looking top, see if the
1015 * executable is.
1016 */
Alexey Tarasov31664102009-10-22 02:55:00 +11001017 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 top = find_top_from(dir, path_buf);
1019 }
1020 return top;
1021}
1022
1023/* <hint> may be:
1024 * - A simple product name
1025 * e.g., "sooner"
1026TODO: debug? sooner-debug, sooner:debug?
1027 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1028 * e.g., "out/target/product/sooner"
1029 * - An absolute path to the PRODUCT_OUT dir
1030 * e.g., "/src/device/out/target/product/sooner"
1031 *
1032 * Given <hint>, try to construct an absolute path to the
1033 * ANDROID_PRODUCT_OUT dir.
1034 */
1035static const char *find_product_out_path(const char *hint)
1036{
1037 static char path_buf[PATH_MAX];
1038
1039 if (hint == NULL || hint[0] == '\0') {
1040 return NULL;
1041 }
1042
1043 /* If it's already absolute, don't bother doing any work.
1044 */
1045 if (adb_is_absolute_host_path(hint)) {
1046 strcpy(path_buf, hint);
1047 return path_buf;
1048 }
1049
1050 /* If there are any slashes in it, assume it's a relative path;
1051 * make it absolute.
1052 */
1053 if (adb_dirstart(hint) != NULL) {
1054 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1055 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1056 return NULL;
1057 }
1058 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1059 fprintf(stderr, "adb: Couldn't assemble path\n");
1060 return NULL;
1061 }
1062 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1063 strcat(path_buf, hint);
1064 return path_buf;
1065 }
1066
1067 /* It's a string without any slashes. Try to do something with it.
1068 *
1069 * Try to find the root of the build tree, and build a PRODUCT_OUT
1070 * path from there.
1071 */
1072 char top_buf[PATH_MAX];
1073 const char *top = find_top(top_buf);
1074 if (top == NULL) {
1075 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1076 return NULL;
1077 }
1078//TODO: if we have a way to indicate debug, look in out/debug/target/...
1079 snprintf(path_buf, sizeof(path_buf),
1080 "%s" OS_PATH_SEPARATOR_STR
1081 "out" OS_PATH_SEPARATOR_STR
1082 "target" OS_PATH_SEPARATOR_STR
1083 "product" OS_PATH_SEPARATOR_STR
1084 "%s", top_buf, hint);
1085 if (access(path_buf, F_OK) < 0) {
1086 fprintf(stderr, "adb: Couldn't find a product dir "
1087 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1088 return NULL;
1089 }
1090 return path_buf;
1091}
1092
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001093static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2,
1094 int *show_progress, int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001095 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001096 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001097
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001098 while (narg > 0) {
1099 if (!strcmp(*arg, "-p")) {
1100 *show_progress = 1;
1101 } else if (!strcmp(*arg, "-a")) {
1102 *copy_attrs = 1;
1103 } else {
1104 break;
1105 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001106 ++arg;
1107 --narg;
1108 }
1109
1110 if (narg > 0) {
1111 *path1 = *arg;
1112 ++arg;
1113 --narg;
1114 }
1115
1116 if (narg > 0) {
1117 *path2 = *arg;
1118 }
1119}
1120
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001121int adb_commandline(int argc, char **argv)
1122{
1123 char buf[4096];
1124 int no_daemon = 0;
1125 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001126 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001127 int persist = 0;
1128 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001129 transport_type ttype = kTransportAny;
1130 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001131 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001132
1133 /* If defined, this should be an absolute path to
1134 * the directory containing all of the various system images
1135 * for a particular product. If not defined, and the adb
1136 * command requires this information, then the user must
1137 * specify the path using "-p".
1138 */
1139 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1140 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1141 gProductOutPath = NULL;
1142 }
1143 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1144
Nick Pellydb449262009-05-07 12:48:03 -07001145 serial = getenv("ANDROID_SERIAL");
1146
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001147 /* Validate and assign the server port */
1148 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1149 int server_port = DEFAULT_ADB_PORT;
1150 if (server_port_str && strlen(server_port_str) > 0) {
1151 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001152 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001153 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001154 "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 +01001155 server_port_str);
1156 return usage();
1157 }
1158 }
1159
1160 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001161 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001162 if(!strcmp(argv[0],"server")) {
1163 is_server = 1;
1164 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001165 no_daemon = 1;
1166 } else if (!strcmp(argv[0], "fork-server")) {
1167 /* this is a special flag used only when the ADB client launches the ADB Server */
1168 is_daemon = 1;
1169 } else if(!strcmp(argv[0],"persist")) {
1170 persist = 1;
1171 } else if(!strncmp(argv[0], "-p", 2)) {
1172 const char *product = NULL;
1173 if (argv[0][2] == '\0') {
1174 if (argc < 2) return usage();
1175 product = argv[1];
1176 argc--;
1177 argv++;
1178 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001179 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001180 }
1181 gProductOutPath = find_product_out_path(product);
1182 if (gProductOutPath == NULL) {
1183 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1184 product);
1185 return usage();
1186 }
1187 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1188 if (isdigit(argv[0][2])) {
1189 serial = argv[0] + 2;
1190 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001191 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 serial = argv[1];
1193 argc--;
1194 argv++;
1195 }
1196 } else if (!strcmp(argv[0],"-d")) {
1197 ttype = kTransportUsb;
1198 } else if (!strcmp(argv[0],"-e")) {
1199 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001200 } else if (!strcmp(argv[0],"-a")) {
1201 gListenAll = 1;
1202 } else if(!strncmp(argv[0], "-H", 2)) {
1203 const char *hostname = NULL;
1204 if (argv[0][2] == '\0') {
1205 if (argc < 2) return usage();
1206 hostname = argv[1];
1207 argc--;
1208 argv++;
1209 } else {
1210 hostname = argv[0] + 2;
1211 }
1212 adb_set_tcp_name(hostname);
1213
1214 } else if(!strncmp(argv[0], "-P", 2)) {
1215 if (argv[0][2] == '\0') {
1216 if (argc < 2) return usage();
1217 server_port_str = argv[1];
1218 argc--;
1219 argv++;
1220 } else {
1221 server_port_str = argv[0] + 2;
1222 }
1223 if (strlen(server_port_str) > 0) {
1224 server_port = (int) strtol(server_port_str, NULL, 0);
1225 if (server_port <= 0 || server_port > 65535) {
1226 fprintf(stderr,
1227 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1228 server_port_str);
1229 return usage();
1230 }
1231 } else {
1232 fprintf(stderr,
1233 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1234 return usage();
1235 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001236 } else {
1237 /* out of recognized modifiers and flags */
1238 break;
1239 }
1240 argc--;
1241 argv++;
1242 }
1243
1244 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001245 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001246
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001247 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001248 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001249 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001250 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001251 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001252 }
1253 if(r) {
1254 fprintf(stderr,"* could not start server *\n");
1255 }
1256 return r;
1257 }
1258
1259top:
1260 if(argc == 0) {
1261 return usage();
1262 }
1263
1264 /* adb_connect() commands */
1265
1266 if(!strcmp(argv[0], "devices")) {
1267 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001268 char *listopt;
1269 if (argc < 2)
1270 listopt = "";
1271 else if (argc == 2 && !strcmp(argv[1], "-l"))
1272 listopt = argv[1];
1273 else {
1274 fprintf(stderr, "Usage: adb devices [-l]\n");
1275 return 1;
1276 }
1277 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001278 tmp = adb_query(buf);
1279 if(tmp) {
1280 printf("List of devices attached \n");
1281 printf("%s\n", tmp);
1282 return 0;
1283 } else {
1284 return 1;
1285 }
1286 }
1287
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001288 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001289 char *tmp;
1290 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001291 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001292 return 1;
1293 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001294 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1295 tmp = adb_query(buf);
1296 if(tmp) {
1297 printf("%s\n", tmp);
1298 return 0;
1299 } else {
1300 return 1;
1301 }
1302 }
1303
1304 if(!strcmp(argv[0], "disconnect")) {
1305 char *tmp;
1306 if (argc > 2) {
1307 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1308 return 1;
1309 }
1310 if (argc == 2) {
1311 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1312 } else {
1313 snprintf(buf, sizeof buf, "host:disconnect:");
1314 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001315 tmp = adb_query(buf);
1316 if(tmp) {
1317 printf("%s\n", tmp);
1318 return 0;
1319 } else {
1320 return 1;
1321 }
1322 }
1323
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001324 if (!strcmp(argv[0], "emu")) {
1325 return adb_send_emulator_command(argc, argv);
1326 }
1327
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001328 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001329 int r;
1330 int fd;
1331
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001332 char h = (argv[0][0] == 'h');
1333
1334 if (h) {
1335 printf("\x1b[41;33m");
1336 fflush(stdout);
1337 }
1338
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001339 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001340 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001341 r = interactive_shell();
1342 if (h) {
1343 printf("\x1b[0m");
1344 fflush(stdout);
1345 }
1346 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001347 }
1348
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001349 snprintf(buf, sizeof(buf), "shell:%s", argv[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001350 argc -= 2;
1351 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001352 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001353 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001354 strncat(buf, " ", sizeof(buf) - 1);
1355 strncat(buf, quoted, sizeof(buf) - 1);
1356 free(quoted);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001357 }
1358
1359 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001360 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001361 fd = adb_connect(buf);
1362 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001363 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001365 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001366 adb_close(fd);
1367 r = 0;
1368 } else {
1369 fprintf(stderr,"error: %s\n", adb_error());
1370 r = -1;
1371 }
1372
1373 if(persist) {
1374 fprintf(stderr,"\n- waiting for device -\n");
1375 adb_sleep_ms(1000);
1376 do_cmd(ttype, serial, "wait-for-device", 0);
1377 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001378 if (h) {
1379 printf("\x1b[0m");
1380 fflush(stdout);
1381 }
JP Abgrall408fa572011-03-16 15:57:42 -07001382 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001383 return r;
1384 }
1385 }
1386 }
1387
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001388 if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
1389 int exec_in = !strcmp(argv[0], "exec-in");
1390 int fd;
1391
1392 snprintf(buf, sizeof buf, "exec:%s", argv[1]);
1393 argc -= 2;
1394 argv += 2;
1395 while (argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001396 char *quoted = escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001397 strncat(buf, " ", sizeof(buf) - 1);
1398 strncat(buf, quoted, sizeof(buf) - 1);
1399 free(quoted);
1400 }
1401
1402 fd = adb_connect(buf);
1403 if (fd < 0) {
1404 fprintf(stderr, "error: %s\n", adb_error());
1405 return -1;
1406 }
1407
1408 if (exec_in) {
1409 copy_to_file(STDIN_FILENO, fd);
1410 } else {
1411 copy_to_file(fd, STDOUT_FILENO);
1412 }
1413
1414 adb_close(fd);
1415 return 0;
1416 }
1417
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418 if(!strcmp(argv[0], "kill-server")) {
1419 int fd;
1420 fd = _adb_connect("host:kill");
1421 if(fd == -1) {
1422 fprintf(stderr,"* server not running *\n");
1423 return 1;
1424 }
1425 return 0;
1426 }
1427
Doug Zongker447f0612012-01-09 14:54:53 -08001428 if(!strcmp(argv[0], "sideload")) {
1429 if(argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001430 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001431 return 1;
1432 } else {
1433 return 0;
1434 }
1435 }
1436
Mike Lockwoodff196702009-08-24 15:58:40 -07001437 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001438 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001439 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001440 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001441 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001442 if (!strcmp(argv[0], "reboot-bootloader"))
1443 snprintf(command, sizeof(command), "reboot:bootloader");
1444 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001445 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001446 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001447 snprintf(command, sizeof(command), "%s:", argv[0]);
1448 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001449 if(fd >= 0) {
1450 read_and_dump(fd);
1451 adb_close(fd);
1452 return 0;
1453 }
1454 fprintf(stderr,"error: %s\n", adb_error());
1455 return 1;
1456 }
1457
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001458 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001459 if (argc != 1) return usage();
1460 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001461 return 0;
1462 }
1463
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001464 /* adb_command() wrapper commands */
1465
1466 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1467 char* service = argv[0];
1468 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1469 if (ttype == kTransportUsb) {
1470 service = "wait-for-usb";
1471 } else if (ttype == kTransportLocal) {
1472 service = "wait-for-local";
1473 } else {
1474 service = "wait-for-any";
1475 }
1476 }
1477
1478 format_host_command(buf, sizeof buf, service, ttype, serial);
1479
1480 if (adb_command(buf)) {
1481 D("failure: %s *\n",adb_error());
1482 fprintf(stderr,"error: %s\n", adb_error());
1483 return 1;
1484 }
1485
1486 /* Allow a command to be run after wait-for-device,
1487 * e.g. 'adb wait-for-device shell'.
1488 */
1489 if(argc > 1) {
1490 argc--;
1491 argv++;
1492 goto top;
1493 }
1494 return 0;
1495 }
1496
David 'Digit' Turner25258692013-03-21 21:07:42 +01001497 if(!strcmp(argv[0], "forward") ||
1498 !strcmp(argv[0], "reverse"))
1499 {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001500 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001501 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001502 char remove = 0;
1503 char remove_all = 0;
1504 char list = 0;
1505 char no_rebind = 0;
1506
1507 // Parse options here.
1508 while (argc > 1 && argv[1][0] == '-') {
1509 if (!strcmp(argv[1], "--list"))
1510 list = 1;
1511 else if (!strcmp(argv[1], "--remove"))
1512 remove = 1;
1513 else if (!strcmp(argv[1], "--remove-all"))
1514 remove_all = 1;
1515 else if (!strcmp(argv[1], "--no-rebind"))
1516 no_rebind = 1;
1517 else {
1518 return usage();
1519 }
1520 argc--;
1521 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001522 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001523
1524 // Ensure we can only use one option at a time.
1525 if (list + remove + remove_all + no_rebind > 1) {
1526 return usage();
1527 }
1528
1529 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001530 if (reverse) {
1531 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001532 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001533 if (serial) {
1534 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1535 serial);
1536 } else if (ttype == kTransportUsb) {
1537 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1538 } else if (ttype == kTransportLocal) {
1539 snprintf(host_prefix, sizeof host_prefix, "host-local");
1540 } else {
1541 snprintf(host_prefix, sizeof host_prefix, "host");
1542 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001543 }
1544
1545 // Implement forward --list
1546 if (list) {
1547 if (argc != 1)
1548 return usage();
1549 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1550 char* forwards = adb_query(buf);
1551 if (forwards == NULL) {
1552 fprintf(stderr, "error: %s\n", adb_error());
1553 return 1;
1554 }
1555 printf("%s", forwards);
1556 free(forwards);
1557 return 0;
1558 }
1559
1560 // Implement forward --remove-all
1561 else if (remove_all) {
1562 if (argc != 1)
1563 return usage();
1564 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1565 }
1566
1567 // Implement forward --remove <local>
1568 else if (remove) {
1569 if (argc != 2)
1570 return usage();
1571 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1572 }
1573 // Or implement one of:
1574 // forward <local> <remote>
1575 // forward --no-rebind <local> <remote>
1576 else
1577 {
1578 if (argc != 3)
1579 return usage();
1580 const char* command = no_rebind ? "forward:norebind:" : "forward";
1581 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1582 }
1583
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001584 if(adb_command(buf)) {
1585 fprintf(stderr,"error: %s\n", adb_error());
1586 return 1;
1587 }
1588 return 0;
1589 }
1590
1591 /* do_sync_*() commands */
1592
1593 if(!strcmp(argv[0], "ls")) {
1594 if(argc != 2) return usage();
1595 return do_sync_ls(argv[1]);
1596 }
1597
1598 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 }
1611
1612 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001613 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001614 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001615 const char* rpath = NULL, *lpath = ".";
1616
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001617 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001618
1619 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001620 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001621 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001622
1623 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001624 }
1625
Jeff Sharkey960df972014-06-09 17:30:57 -07001626 if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001627 if (argc < 2) return usage();
1628 return install_app(ttype, serial, argc, argv);
1629 }
1630
Jeff Sharkey960df972014-06-09 17:30:57 -07001631 if (!strcmp(argv[0], "install-multiple")) {
1632 if (argc < 2) return usage();
1633 return install_multiple_app(ttype, serial, argc, argv);
1634 }
1635
1636 if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637 if (argc < 2) return usage();
1638 return uninstall_app(ttype, serial, argc, argv);
1639 }
1640
1641 if(!strcmp(argv[0], "sync")) {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001642 char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001643 int listonly = 0;
1644
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001645 int ret;
1646 if(argc < 2) {
1647 /* No local path was specified. */
1648 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001649 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1650 listonly = 1;
1651 if (argc == 3) {
1652 srcarg = argv[2];
1653 } else {
1654 srcarg = NULL;
1655 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001656 } else if(argc == 2) {
1657 /* A local path or "android"/"data" arg was specified. */
1658 srcarg = argv[1];
1659 } else {
1660 return usage();
1661 }
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001662 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001663 if(ret != 0) return usage();
1664
1665 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001666 ret = do_sync_sync(android_srcpath, "/system", listonly);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001667 if(ret == 0 && vendor_srcpath != NULL)
1668 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001669 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001670 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001671
1672 free(android_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001673 free(vendor_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001674 free(data_srcpath);
1675 return ret;
1676 }
1677
1678 /* passthrough commands */
1679
1680 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001681 !strcmp(argv[0],"get-serialno") ||
1682 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001683 {
1684 char *tmp;
1685
1686 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1687 tmp = adb_query(buf);
1688 if(tmp) {
1689 printf("%s\n", tmp);
1690 return 0;
1691 } else {
1692 return 1;
1693 }
1694 }
1695
1696 /* other commands */
1697
1698 if(!strcmp(argv[0],"status-window")) {
1699 status_window(ttype, serial);
1700 return 0;
1701 }
1702
Christopher Tatedb0a8802011-11-30 13:00:33 -08001703 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001704 return logcat(ttype, serial, argc, argv);
1705 }
1706
1707 if(!strcmp(argv[0],"ppp")) {
1708 return ppp(argc, argv);
1709 }
1710
1711 if (!strcmp(argv[0], "start-server")) {
1712 return adb_connect("host:start-server");
1713 }
1714
Christopher Tated2f54152011-04-21 12:53:28 -07001715 if (!strcmp(argv[0], "backup")) {
1716 return backup(argc, argv);
1717 }
1718
Christopher Tate702967a2011-05-17 15:52:54 -07001719 if (!strcmp(argv[0], "restore")) {
1720 return restore(argc, argv);
1721 }
1722
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001723 if (!strcmp(argv[0], "jdwp")) {
1724 int fd = adb_connect("jdwp");
1725 if (fd >= 0) {
1726 read_and_dump(fd);
1727 adb_close(fd);
1728 return 0;
1729 } else {
1730 fprintf(stderr, "error: %s\n", adb_error());
1731 return -1;
1732 }
1733 }
1734
1735 /* "adb /?" is a common idiom under Windows */
1736 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1737 help();
1738 return 0;
1739 }
1740
1741 if(!strcmp(argv[0], "version")) {
1742 version(stdout);
1743 return 0;
1744 }
1745
1746 usage();
1747 return 1;
1748}
1749
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001750#define MAX_ARGV_LENGTH 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001751static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1752{
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001753 char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001754 int argc;
1755 va_list ap;
1756
1757 va_start(ap, cmd);
1758 argc = 0;
1759
1760 if (serial) {
1761 argv[argc++] = "-s";
1762 argv[argc++] = serial;
1763 } else if (ttype == kTransportUsb) {
1764 argv[argc++] = "-d";
1765 } else if (ttype == kTransportLocal) {
1766 argv[argc++] = "-e";
1767 }
1768
1769 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001770 while(argc < MAX_ARGV_LENGTH &&
1771 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1772 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001773 va_end(ap);
1774
1775#if 0
1776 int n;
1777 fprintf(stderr,"argc = %d\n",argc);
1778 for(n = 0; n < argc; n++) {
1779 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1780 }
1781#endif
1782
1783 return adb_commandline(argc, argv);
1784}
1785
1786int find_sync_dirs(const char *srcarg,
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001787 char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001788{
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001789 char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL;
1790 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001791
1792 if(srcarg == NULL) {
1793 android_srcdir = product_file("system");
1794 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001795 vendor_srcdir = product_file("vendor");
1796 /* Check if vendor partition exists */
1797 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1798 vendor_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001799 } else {
1800 /* srcarg may be "data", "system" or NULL.
1801 * if srcarg is NULL, then both data and system are synced
1802 */
1803 if(strcmp(srcarg, "system") == 0) {
1804 android_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001805 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001806 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001807 } else if(strcmp(srcarg, "vendor") == 0) {
1808 vendor_srcdir = product_file("vendor");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001809 } else {
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001810 /* It's not "system", "vendor", or "data".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001811 */
1812 return 1;
1813 }
1814 }
1815
1816 if(android_srcdir_out != NULL)
1817 *android_srcdir_out = android_srcdir;
1818 else
1819 free(android_srcdir);
1820
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001821 if(vendor_srcdir_out != NULL)
1822 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001823 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001824 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001825
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001826 if(data_srcdir_out != NULL)
1827 *data_srcdir_out = data_srcdir;
1828 else
1829 free(data_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001830 return 0;
1831}
1832
1833static int pm_command(transport_type transport, char* serial,
1834 int argc, char** argv)
1835{
1836 char buf[4096];
1837
1838 snprintf(buf, sizeof(buf), "shell:pm");
1839
1840 while(argc-- > 0) {
Jeff Sharkey7c460352014-06-10 16:22:17 -07001841 char *quoted = escape_arg(*argv++);
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001842 strncat(buf, " ", sizeof(buf) - 1);
1843 strncat(buf, quoted, sizeof(buf) - 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001844 free(quoted);
1845 }
1846
1847 send_shellcommand(transport, serial, buf);
1848 return 0;
1849}
1850
1851int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1852{
1853 /* if the user choose the -k option, we refuse to do it until devices are
1854 out with the option to uninstall the remaining data somehow (adb/ui) */
1855 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1856 {
1857 printf(
1858 "The -k option uninstalls the application while retaining the data/cache.\n"
1859 "At the moment, there is no way to remove the remaining data.\n"
1860 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1861 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1862 return -1;
1863 }
1864
1865 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1866 return pm_command(transport, serial, argc, argv);
1867}
1868
1869static int delete_file(transport_type transport, char* serial, char* filename)
1870{
1871 char buf[4096];
1872 char* quoted;
1873
Jeff Sharkey41b3cfa2014-09-09 12:38:30 -07001874 snprintf(buf, sizeof(buf), "shell:rm -f ");
Jeff Sharkey7c460352014-06-10 16:22:17 -07001875 quoted = escape_arg(filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001876 strncat(buf, quoted, sizeof(buf)-1);
1877 free(quoted);
1878
1879 send_shellcommand(transport, serial, buf);
1880 return 0;
1881}
1882
Kenny Root597ea5b2011-08-05 11:19:45 -07001883static const char* get_basename(const char* filename)
1884{
1885 const char* basename = adb_dirstop(filename);
1886 if (basename) {
1887 basename++;
1888 return basename;
1889 } else {
1890 return filename;
1891 }
1892}
1893
Kenny Root597ea5b2011-08-05 11:19:45 -07001894int install_app(transport_type transport, char* serial, int argc, char** argv)
1895{
1896 static const char *const DATA_DEST = "/data/local/tmp/%s";
1897 static const char *const SD_DEST = "/sdcard/tmp/%s";
1898 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001899 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001900 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001901
1902 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001903 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001904 where = SD_DEST;
1905 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001906 }
1907
Jeff Sharkey960df972014-06-09 17:30:57 -07001908 // Find last APK argument.
1909 // All other arguments passed through verbatim.
1910 int last_apk = -1;
1911 for (i = argc - 1; i >= 0; i--) {
1912 char* file = argv[i];
1913 char* dot = strrchr(file, '.');
1914 if (dot && !strcasecmp(dot, ".apk")) {
1915 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1916 fprintf(stderr, "Invalid APK file: %s\n", file);
1917 return -1;
1918 }
1919
1920 last_apk = i;
1921 break;
1922 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001923 }
1924
Jeff Sharkey960df972014-06-09 17:30:57 -07001925 if (last_apk == -1) {
1926 fprintf(stderr, "Missing APK file\n");
1927 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001928 }
1929
Jeff Sharkey960df972014-06-09 17:30:57 -07001930 char* apk_file = argv[last_apk];
1931 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001932 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001933 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001934 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001935 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001936 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001937 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001938 }
1939
1940 pm_command(transport, serial, argc, argv);
1941
Kenny Root60733e92012-03-26 16:14:02 -07001942cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001943 delete_file(transport, serial, apk_dest);
1944 return err;
1945}
1946
1947int install_multiple_app(transport_type transport, char* serial, int argc, char** argv)
1948{
1949 char buf[1024];
1950 int i;
1951 struct stat sb;
1952 unsigned long long total_size = 0;
1953
1954 // Find all APK arguments starting at end.
1955 // All other arguments passed through verbatim.
1956 int first_apk = -1;
1957 for (i = argc - 1; i >= 0; i--) {
1958 char* file = argv[i];
1959 char* dot = strrchr(file, '.');
1960 if (dot && !strcasecmp(dot, ".apk")) {
1961 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1962 fprintf(stderr, "Invalid APK file: %s\n", file);
1963 return -1;
1964 }
1965
1966 total_size += sb.st_size;
1967 first_apk = i;
1968 } else {
1969 break;
1970 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001971 }
1972
Jeff Sharkey960df972014-06-09 17:30:57 -07001973 if (first_apk == -1) {
1974 fprintf(stderr, "Missing APK file\n");
1975 return 1;
1976 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001977
Jeff Sharkey960df972014-06-09 17:30:57 -07001978 snprintf(buf, sizeof(buf), "exec:pm install-create -S %lld", total_size);
1979 for (i = 1; i < first_apk; i++) {
1980 char *quoted = escape_arg(argv[i]);
1981 strncat(buf, " ", sizeof(buf) - 1);
1982 strncat(buf, quoted, sizeof(buf) - 1);
1983 free(quoted);
1984 }
1985
1986 // Create install session
1987 int fd = adb_connect(buf);
1988 if (fd < 0) {
1989 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1990 return -1;
1991 }
1992 read_status_line(fd, buf, sizeof(buf));
1993 adb_close(fd);
1994
1995 int session_id = -1;
1996 if (!strncmp("Success", buf, 7)) {
1997 char* start = strrchr(buf, '[');
1998 char* end = strrchr(buf, ']');
1999 if (start && end) {
2000 *end = '\0';
2001 session_id = strtol(start + 1, NULL, 10);
2002 }
2003 }
2004 if (session_id < 0) {
2005 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002006 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002007 return -1;
2008 }
2009
2010 // Valid session, now stream the APKs
2011 int success = 1;
2012 for (i = first_apk; i < argc; i++) {
2013 char* file = argv[i];
2014 if (stat(file, &sb) == -1) {
2015 fprintf(stderr, "Failed to stat %s\n", file);
2016 success = 0;
2017 goto finalize_session;
2018 }
2019
2020 snprintf(buf, sizeof(buf), "exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07002021 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07002022
2023 int localFd = adb_open(file, O_RDONLY);
2024 if (localFd < 0) {
2025 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
2026 success = 0;
2027 goto finalize_session;
2028 }
2029
2030 int remoteFd = adb_connect(buf);
2031 if (remoteFd < 0) {
2032 fprintf(stderr, "Connect error for write: %s\n", adb_error());
2033 adb_close(localFd);
2034 success = 0;
2035 goto finalize_session;
2036 }
2037
2038 copy_to_file(localFd, remoteFd);
2039 read_status_line(remoteFd, buf, sizeof(buf));
2040
2041 adb_close(localFd);
2042 adb_close(remoteFd);
2043
2044 if (strncmp("Success", buf, 7)) {
2045 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07002046 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002047 success = 0;
2048 goto finalize_session;
2049 }
2050 }
2051
2052finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002053 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002054 if (success) {
2055 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2056 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002057 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002058 }
2059
2060 fd = adb_connect(buf);
2061 if (fd < 0) {
2062 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2063 return -1;
2064 }
2065 read_status_line(fd, buf, sizeof(buf));
2066 adb_close(fd);
2067
2068 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002069 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002070 return 0;
2071 } else {
2072 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002073 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002074 return -1;
2075 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002076}