• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <limits.h>
23 #include <stdarg.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <ctype.h>
27 #include <assert.h>
28 
29 #include "sysdeps.h"
30 
31 #ifdef HAVE_TERMIO_H
32 #include <termios.h>
33 #endif
34 
35 #define  TRACE_TAG  TRACE_ADB
36 #include "adb.h"
37 #include "adb_client.h"
38 #include "file_sync_service.h"
39 
40 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41 
42 void get_my_path(char *s, size_t maxLen);
43 int find_sync_dirs(const char *srcarg,
44         char **android_srcdir_out, char **data_srcdir_out);
45 int install_app(transport_type transport, char* serial, int argc, char** argv);
46 int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47 
48 static const char *gProductOutPath = NULL;
49 
product_file(const char * extra)50 static char *product_file(const char *extra)
51 {
52     int n;
53     char *x;
54 
55     if (gProductOutPath == NULL) {
56         fprintf(stderr, "adb: Product directory not specified; "
57                 "use -p or define ANDROID_PRODUCT_OUT\n");
58         exit(1);
59     }
60 
61     n = strlen(gProductOutPath) + strlen(extra) + 2;
62     x = malloc(n);
63     if (x == 0) {
64         fprintf(stderr, "adb: Out of memory (product_file())\n");
65         exit(1);
66     }
67 
68     snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
69     return x;
70 }
71 
version(FILE * out)72 void version(FILE * out) {
73     fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
74          ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
75 }
76 
help()77 void help()
78 {
79     version(stderr);
80 
81     fprintf(stderr,
82         "\n"
83         " -d                            - directs command to the only connected USB device\n"
84         "                                 returns an error if more than one USB device is present.\n"
85         " -e                            - directs command to the only running emulator.\n"
86         "                                 returns an error if more than one emulator is running.\n"
87         " -s <specific device>          - directs command to the device or emulator with the given\n"
88         "                                 serial number or qualifier. Overrides ANDROID_SERIAL\n"
89         "                                 environment variable.\n"
90         " -p <product name or path>     - simple product name like 'sooner', or\n"
91         "                                 a relative/absolute path to a product\n"
92         "                                 out directory like 'out/target/product/sooner'.\n"
93         "                                 If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94         "                                 environment variable is used, which must\n"
95         "                                 be an absolute path.\n"
96         " devices [-l]                  - list all connected devices\n"
97         "                                 ('-l' will also list device qualifiers)\n"
98         " connect <host>[:<port>]       - connect to a device via TCP/IP\n"
99         "                                 Port 5555 is used by default if no port number is specified.\n"
100         " disconnect [<host>[:<port>]]  - disconnect from a TCP/IP device.\n"
101         "                                 Port 5555 is used by default if no port number is specified.\n"
102         "                                 Using this command with no additional arguments\n"
103         "                                 will disconnect from all connected TCP/IP devices.\n"
104         "\n"
105         "device commands:\n"
106         "  adb push <local> <remote>    - copy file/dir to device\n"
107         "  adb pull <remote> [<local>]  - copy file/dir from device\n"
108         "  adb sync [ <directory> ]     - copy host->device only if changed\n"
109         "                                 (-l means list but don't copy)\n"
110         "                                 (see 'adb help all')\n"
111         "  adb shell                    - run remote shell interactively\n"
112         "  adb shell <command>          - run remote shell command\n"
113         "  adb emu <command>            - run emulator console command\n"
114         "  adb logcat [ <filter-spec> ] - View device log\n"
115         "  adb forward <local> <remote> - forward socket connections\n"
116         "                                 forward specs are one of: \n"
117         "                                   tcp:<port>\n"
118         "                                   localabstract:<unix domain socket name>\n"
119         "                                   localreserved:<unix domain socket name>\n"
120         "                                   localfilesystem:<unix domain socket name>\n"
121         "                                   dev:<character device name>\n"
122         "                                   jdwp:<process pid> (remote only)\n"
123         "  adb jdwp                     - list PIDs of processes hosting a JDWP transport\n"
124         "  adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
125         "                               - push this package file to the device and install it\n"
126         "                                 ('-l' means forward-lock the app)\n"
127         "                                 ('-r' means reinstall the app, keeping its data)\n"
128         "                                 ('-s' means install on SD card instead of internal storage)\n"
129         "                                 ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
130         "  adb uninstall [-k] <package> - remove this app package from the device\n"
131         "                                 ('-k' means keep the data and cache directories)\n"
132         "  adb bugreport                - return all information from the device\n"
133         "                                 that should be included in a bug report.\n"
134         "\n"
135         "  adb backup [-f <file>] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
136         "                               - write an archive of the device's data to <file>.\n"
137         "                                 If no -f option is supplied then the data is written\n"
138         "                                 to \"backup.ab\" in the current directory.\n"
139         "                                 (-apk|-noapk enable/disable backup of the .apks themselves\n"
140         "                                    in the archive; the default is noapk.)\n"
141         "                                 (-shared|-noshared enable/disable backup of the device's\n"
142         "                                    shared storage / SD card contents; the default is noshared.)\n"
143         "                                 (-all means to back up all installed applications)\n"
144         "                                 (-system|-nosystem toggles whether -all automatically includes\n"
145         "                                    system applications; the default is to include system apps)\n"
146         "                                 (<packages...> is the list of applications to be backed up.  If\n"
147         "                                    the -all or -shared flags are passed, then the package\n"
148         "                                    list is optional.  Applications explicitly given on the\n"
149         "                                    command line will be included even if -nosystem would\n"
150         "                                    ordinarily cause them to be omitted.)\n"
151         "\n"
152         "  adb restore <file>           - restore device contents from the <file> backup archive\n"
153         "\n"
154         "  adb help                     - show this help message\n"
155         "  adb version                  - show version num\n"
156         "\n"
157         "scripting:\n"
158         "  adb wait-for-device          - block until device is online\n"
159         "  adb start-server             - ensure that there is a server running\n"
160         "  adb kill-server              - kill the server if it is running\n"
161         "  adb get-state                - prints: offline | bootloader | device\n"
162         "  adb get-serialno             - prints: <serial-number>\n"
163         "  adb get-devpath              - prints: <device-path>\n"
164         "  adb status-window            - continuously print device status for a specified device\n"
165         "  adb remount                  - remounts the /system partition on the device read-write\n"
166         "  adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
167         "  adb reboot-bootloader        - reboots the device into the bootloader\n"
168         "  adb root                     - restarts the adbd daemon with root permissions\n"
169         "  adb usb                      - restarts the adbd daemon listening on USB\n"
170         "  adb tcpip <port>             - restarts the adbd daemon listening on TCP on the specified port"
171         "\n"
172         "networking:\n"
173         "  adb ppp <tty> [parameters]   - Run PPP over USB.\n"
174         " Note: you should not automatically start a PPP connection.\n"
175         " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
176         " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
177         "\n"
178         "adb sync notes: adb sync [ <directory> ]\n"
179         "  <localdir> can be interpreted in several ways:\n"
180         "\n"
181         "  - If <directory> is not specified, both /system and /data partitions will be updated.\n"
182         "\n"
183         "  - If it is \"system\" or \"data\", only the corresponding partition\n"
184         "    is updated.\n"
185         "\n"
186         "environmental variables:\n"
187         "  ADB_TRACE                    - Print debug information. A comma separated list of the following values\n"
188         "                                 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
189         "  ANDROID_SERIAL               - The serial number to connect to. -s takes priority over this if given.\n"
190         "  ANDROID_LOG_TAGS             - When used with the logcat option, only these debug tags are printed.\n"
191         );
192 }
193 
usage()194 int usage()
195 {
196     help();
197     return 1;
198 }
199 
200 #ifdef HAVE_TERMIO_H
201 static struct termios tio_save;
202 
stdin_raw_init(int fd)203 static void stdin_raw_init(int fd)
204 {
205     struct termios tio;
206 
207     if(tcgetattr(fd, &tio)) return;
208     if(tcgetattr(fd, &tio_save)) return;
209 
210     tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
211 
212         /* no timeout but request at least one character per read */
213     tio.c_cc[VTIME] = 0;
214     tio.c_cc[VMIN] = 1;
215 
216     tcsetattr(fd, TCSANOW, &tio);
217     tcflush(fd, TCIFLUSH);
218 }
219 
stdin_raw_restore(int fd)220 static void stdin_raw_restore(int fd)
221 {
222     tcsetattr(fd, TCSANOW, &tio_save);
223     tcflush(fd, TCIFLUSH);
224 }
225 #endif
226 
read_and_dump(int fd)227 static void read_and_dump(int fd)
228 {
229     char buf[4096];
230     int len;
231 
232     while(fd >= 0) {
233         D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
234         len = adb_read(fd, buf, 4096);
235         D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
236         if(len == 0) {
237             break;
238         }
239 
240         if(len < 0) {
241             if(errno == EINTR) continue;
242             break;
243         }
244         fwrite(buf, 1, len, stdout);
245         fflush(stdout);
246     }
247 }
248 
copy_to_file(int inFd,int outFd)249 static void copy_to_file(int inFd, int outFd) {
250     const size_t BUFSIZE = 32 * 1024;
251     char* buf = (char*) malloc(BUFSIZE);
252     int len;
253     long total = 0;
254 
255     D("copy_to_file(%d -> %d)\n", inFd, outFd);
256     for (;;) {
257         len = adb_read(inFd, buf, BUFSIZE);
258         if (len == 0) {
259             D("copy_to_file() : read 0 bytes; exiting\n");
260             break;
261         }
262         if (len < 0) {
263             if (errno == EINTR) {
264                 D("copy_to_file() : EINTR, retrying\n");
265                 continue;
266             }
267             D("copy_to_file() : error %d\n", errno);
268             break;
269         }
270         adb_write(outFd, buf, len);
271         total += len;
272     }
273     D("copy_to_file() finished after %lu bytes\n", total);
274     free(buf);
275 }
276 
stdin_read_thread(void * x)277 static void *stdin_read_thread(void *x)
278 {
279     int fd, fdi;
280     unsigned char buf[1024];
281     int r, n;
282     int state = 0;
283 
284     int *fds = (int*) x;
285     fd = fds[0];
286     fdi = fds[1];
287     free(fds);
288 
289     for(;;) {
290         /* fdi is really the client's stdin, so use read, not adb_read here */
291         D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
292         r = unix_read(fdi, buf, 1024);
293         D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
294         if(r == 0) break;
295         if(r < 0) {
296             if(errno == EINTR) continue;
297             break;
298         }
299         for(n = 0; n < r; n++){
300             switch(buf[n]) {
301             case '\n':
302                 state = 1;
303                 break;
304             case '\r':
305                 state = 1;
306                 break;
307             case '~':
308                 if(state == 1) state++;
309                 break;
310             case '.':
311                 if(state == 2) {
312                     fprintf(stderr,"\n* disconnect *\n");
313 #ifdef HAVE_TERMIO_H
314                     stdin_raw_restore(fdi);
315 #endif
316                     exit(0);
317                 }
318             default:
319                 state = 0;
320             }
321         }
322         r = adb_write(fd, buf, r);
323         if(r <= 0) {
324             break;
325         }
326     }
327     return 0;
328 }
329 
interactive_shell(void)330 int interactive_shell(void)
331 {
332     adb_thread_t thr;
333     int fdi, fd;
334     int *fds;
335 
336     fd = adb_connect("shell:");
337     if(fd < 0) {
338         fprintf(stderr,"error: %s\n", adb_error());
339         return 1;
340     }
341     fdi = 0; //dup(0);
342 
343     fds = malloc(sizeof(int) * 2);
344     fds[0] = fd;
345     fds[1] = fdi;
346 
347 #ifdef HAVE_TERMIO_H
348     stdin_raw_init(fdi);
349 #endif
350     adb_thread_create(&thr, stdin_read_thread, fds);
351     read_and_dump(fd);
352 #ifdef HAVE_TERMIO_H
353     stdin_raw_restore(fdi);
354 #endif
355     return 0;
356 }
357 
358 
format_host_command(char * buffer,size_t buflen,const char * command,transport_type ttype,const char * serial)359 static void format_host_command(char* buffer, size_t  buflen, const char* command, transport_type ttype, const char* serial)
360 {
361     if (serial) {
362         snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
363     } else {
364         const char* prefix = "host";
365         if (ttype == kTransportUsb)
366             prefix = "host-usb";
367         else if (ttype == kTransportLocal)
368             prefix = "host-local";
369 
370         snprintf(buffer, buflen, "%s:%s", prefix, command);
371     }
372 }
373 
adb_download_buffer(const char * service,const void * data,int sz,unsigned progress)374 int adb_download_buffer(const char *service, const void* data, int sz,
375                         unsigned progress)
376 {
377     char buf[4096];
378     unsigned total;
379     int fd;
380     const unsigned char *ptr;
381 
382     sprintf(buf,"%s:%d", service, sz);
383     fd = adb_connect(buf);
384     if(fd < 0) {
385         fprintf(stderr,"error: %s\n", adb_error());
386         return -1;
387     }
388 
389     int opt = CHUNK_SIZE;
390     opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
391 
392     total = sz;
393     ptr = data;
394 
395     if(progress) {
396         char *x = strrchr(service, ':');
397         if(x) service = x + 1;
398     }
399 
400     while(sz > 0) {
401         unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
402         if(writex(fd, ptr, xfer)) {
403             adb_status(fd);
404             fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
405             return -1;
406         }
407         sz -= xfer;
408         ptr += xfer;
409         if(progress) {
410             printf("sending: '%s' %4d%%    \r", service, (int)(100LL - ((100LL * sz) / (total))));
411             fflush(stdout);
412         }
413     }
414     if(progress) {
415         printf("\n");
416     }
417 
418     if(readx(fd, buf, 4)){
419         fprintf(stderr,"* error reading response *\n");
420         adb_close(fd);
421         return -1;
422     }
423     if(memcmp(buf, "OKAY", 4)) {
424         buf[4] = 0;
425         fprintf(stderr,"* error response '%s' *\n", buf);
426         adb_close(fd);
427         return -1;
428     }
429 
430     adb_close(fd);
431     return 0;
432 }
433 
434 
adb_download(const char * service,const char * fn,unsigned progress)435 int adb_download(const char *service, const char *fn, unsigned progress)
436 {
437     void *data;
438     unsigned sz;
439 
440     data = load_file(fn, &sz);
441     if(data == 0) {
442         fprintf(stderr,"* cannot read '%s' *\n", service);
443         return -1;
444     }
445 
446     int status = adb_download_buffer(service, data, sz, progress);
447     free(data);
448     return status;
449 }
450 
status_window(transport_type ttype,const char * serial)451 static void status_window(transport_type ttype, const char* serial)
452 {
453     char command[4096];
454     char *state = 0;
455     char *laststate = 0;
456 
457         /* silence stderr */
458 #ifdef _WIN32
459     /* XXX: TODO */
460 #else
461     int  fd;
462     fd = unix_open("/dev/null", O_WRONLY);
463     dup2(fd, 2);
464     adb_close(fd);
465 #endif
466 
467     format_host_command(command, sizeof command, "get-state", ttype, serial);
468 
469     for(;;) {
470         adb_sleep_ms(250);
471 
472         if(state) {
473             free(state);
474             state = 0;
475         }
476 
477         state = adb_query(command);
478 
479         if(state) {
480             if(laststate && !strcmp(state,laststate)){
481                 continue;
482             } else {
483                 if(laststate) free(laststate);
484                 laststate = strdup(state);
485             }
486         }
487 
488         printf("%c[2J%c[2H", 27, 27);
489         printf("Android Debug Bridge\n");
490         printf("State: %s\n", state ? state : "offline");
491         fflush(stdout);
492     }
493 }
494 
495 /** duplicate string and quote all \ " ( ) chars + space character. */
496 static char *
dupAndQuote(const char * s)497 dupAndQuote(const char *s)
498 {
499     const char *ts;
500     size_t alloc_len;
501     char *ret;
502     char *dest;
503 
504     ts = s;
505 
506     alloc_len = 0;
507 
508     for( ;*ts != '\0'; ts++) {
509         alloc_len++;
510         if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
511             alloc_len++;
512         }
513     }
514 
515     ret = (char *)malloc(alloc_len + 1);
516 
517     ts = s;
518     dest = ret;
519 
520     for ( ;*ts != '\0'; ts++) {
521         if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
522             *dest++ = '\\';
523         }
524 
525         *dest++ = *ts;
526     }
527 
528     *dest++ = '\0';
529 
530     return ret;
531 }
532 
533 /**
534  * Run ppp in "notty" mode against a resource listed as the first parameter
535  * eg:
536  *
537  * ppp dev:/dev/omap_csmi_tty0 <ppp options>
538  *
539  */
ppp(int argc,char ** argv)540 int ppp(int argc, char **argv)
541 {
542 #ifdef HAVE_WIN32_PROC
543     fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
544     return -1;
545 #else
546     char *adb_service_name;
547     pid_t pid;
548     int fd;
549 
550     if (argc < 2) {
551         fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
552                 argv[0]);
553 
554         return 1;
555     }
556 
557     adb_service_name = argv[1];
558 
559     fd = adb_connect(adb_service_name);
560 
561     if(fd < 0) {
562         fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
563                 adb_service_name, adb_error());
564         return 1;
565     }
566 
567     pid = fork();
568 
569     if (pid < 0) {
570         perror("from fork()");
571         return 1;
572     } else if (pid == 0) {
573         int err;
574         int i;
575         const char **ppp_args;
576 
577         // copy args
578         ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
579         ppp_args[0] = "pppd";
580         for (i = 2 ; i < argc ; i++) {
581             //argv[2] and beyond become ppp_args[1] and beyond
582             ppp_args[i - 1] = argv[i];
583         }
584         ppp_args[i-1] = NULL;
585 
586         // child side
587 
588         dup2(fd, STDIN_FILENO);
589         dup2(fd, STDOUT_FILENO);
590         adb_close(STDERR_FILENO);
591         adb_close(fd);
592 
593         err = execvp("pppd", (char * const *)ppp_args);
594 
595         if (err < 0) {
596             perror("execing pppd");
597         }
598         exit(-1);
599     } else {
600         // parent side
601 
602         adb_close(fd);
603         return 0;
604     }
605 #endif /* !HAVE_WIN32_PROC */
606 }
607 
send_shellcommand(transport_type transport,char * serial,char * buf)608 static int send_shellcommand(transport_type transport, char* serial, char* buf)
609 {
610     int fd, ret;
611 
612     for(;;) {
613         fd = adb_connect(buf);
614         if(fd >= 0)
615             break;
616         fprintf(stderr,"- waiting for device -\n");
617         adb_sleep_ms(1000);
618         do_cmd(transport, serial, "wait-for-device", 0);
619     }
620 
621     read_and_dump(fd);
622     ret = adb_close(fd);
623     if (ret)
624         perror("close");
625 
626     return ret;
627 }
628 
logcat(transport_type transport,char * serial,int argc,char ** argv)629 static int logcat(transport_type transport, char* serial, int argc, char **argv)
630 {
631     char buf[4096];
632 
633     char *log_tags;
634     char *quoted_log_tags;
635 
636     log_tags = getenv("ANDROID_LOG_TAGS");
637     quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
638 
639     snprintf(buf, sizeof(buf),
640         "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
641         quoted_log_tags);
642 
643     free(quoted_log_tags);
644 
645     if (!strcmp(argv[0],"longcat")) {
646         strncat(buf, " -v long", sizeof(buf)-1);
647     }
648 
649     argc -= 1;
650     argv += 1;
651     while(argc-- > 0) {
652         char *quoted;
653 
654         quoted = dupAndQuote (*argv++);
655 
656         strncat(buf, " ", sizeof(buf)-1);
657         strncat(buf, quoted, sizeof(buf)-1);
658         free(quoted);
659     }
660 
661     send_shellcommand(transport, serial, buf);
662     return 0;
663 }
664 
mkdirs(char * path)665 static int mkdirs(char *path)
666 {
667     int ret;
668     char *x = path + 1;
669 
670     for(;;) {
671         x = adb_dirstart(x);
672         if(x == 0) return 0;
673         *x = 0;
674         ret = adb_mkdir(path, 0775);
675         *x = OS_PATH_SEPARATOR;
676         if((ret < 0) && (errno != EEXIST)) {
677             return ret;
678         }
679         x++;
680     }
681     return 0;
682 }
683 
backup(int argc,char ** argv)684 static int backup(int argc, char** argv) {
685     char buf[4096];
686     char default_name[32];
687     const char* filename = strcpy(default_name, "./backup.ab");
688     int fd, outFd;
689     int i, j;
690 
691     /* find, extract, and use any -f argument */
692     for (i = 1; i < argc; i++) {
693         if (!strcmp("-f", argv[i])) {
694             if (i == argc-1) {
695                 fprintf(stderr, "adb: -f passed with no filename\n");
696                 return usage();
697             }
698             filename = argv[i+1];
699             for (j = i+2; j <= argc; ) {
700                 argv[i++] = argv[j++];
701             }
702             argc -= 2;
703             argv[argc] = NULL;
704         }
705     }
706 
707     /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
708     if (argc < 2) return usage();
709 
710     adb_unlink(filename);
711     mkdirs((char *)filename);
712     outFd = adb_creat(filename, 0640);
713     if (outFd < 0) {
714         fprintf(stderr, "adb: unable to open file %s\n", filename);
715         return -1;
716     }
717 
718     snprintf(buf, sizeof(buf), "backup");
719     for (argc--, argv++; argc; argc--, argv++) {
720         strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
721         strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
722     }
723 
724     D("backup. filename=%s buf=%s\n", filename, buf);
725     fd = adb_connect(buf);
726     if (fd < 0) {
727         fprintf(stderr, "adb: unable to connect for backup\n");
728         adb_close(outFd);
729         return -1;
730     }
731 
732     printf("Now unlock your device and confirm the backup operation.\n");
733     copy_to_file(fd, outFd);
734 
735     adb_close(fd);
736     adb_close(outFd);
737     return 0;
738 }
739 
restore(int argc,char ** argv)740 static int restore(int argc, char** argv) {
741     const char* filename;
742     int fd, tarFd;
743 
744     if (argc != 2) return usage();
745 
746     filename = argv[1];
747     tarFd = adb_open(filename, O_RDONLY);
748     if (tarFd < 0) {
749         fprintf(stderr, "adb: unable to open file %s\n", filename);
750         return -1;
751     }
752 
753     fd = adb_connect("restore:");
754     if (fd < 0) {
755         fprintf(stderr, "adb: unable to connect for backup\n");
756         adb_close(tarFd);
757         return -1;
758     }
759 
760     printf("Now unlock your device and confirm the restore operation.\n");
761     copy_to_file(tarFd, fd);
762 
763     adb_close(fd);
764     adb_close(tarFd);
765     return 0;
766 }
767 
768 #define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
top_works(const char * top)769 static int top_works(const char *top)
770 {
771     if (top != NULL && adb_is_absolute_host_path(top)) {
772         char path_buf[PATH_MAX];
773         snprintf(path_buf, sizeof(path_buf),
774                 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
775         return access(path_buf, F_OK) == 0;
776     }
777     return 0;
778 }
779 
find_top_from(const char * indir,char path_buf[PATH_MAX])780 static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
781 {
782     strcpy(path_buf, indir);
783     while (1) {
784         if (top_works(path_buf)) {
785             return path_buf;
786         }
787         char *s = adb_dirstop(path_buf);
788         if (s != NULL) {
789             *s = '\0';
790         } else {
791             path_buf[0] = '\0';
792             return NULL;
793         }
794     }
795 }
796 
find_top(char path_buf[PATH_MAX])797 static char *find_top(char path_buf[PATH_MAX])
798 {
799     char *top = getenv("ANDROID_BUILD_TOP");
800     if (top != NULL && top[0] != '\0') {
801         if (!top_works(top)) {
802             fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
803             return NULL;
804         }
805     } else {
806         top = getenv("TOP");
807         if (top != NULL && top[0] != '\0') {
808             if (!top_works(top)) {
809                 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
810                 return NULL;
811             }
812         } else {
813             top = NULL;
814         }
815     }
816 
817     if (top != NULL) {
818         /* The environment pointed to a top directory that works.
819          */
820         strcpy(path_buf, top);
821         return path_buf;
822     }
823 
824     /* The environment didn't help.  Walk up the tree from the CWD
825      * to see if we can find the top.
826      */
827     char dir[PATH_MAX];
828     top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
829     if (top == NULL) {
830         /* If the CWD isn't under a good-looking top, see if the
831          * executable is.
832          */
833         get_my_path(dir, PATH_MAX);
834         top = find_top_from(dir, path_buf);
835     }
836     return top;
837 }
838 
839 /* <hint> may be:
840  * - A simple product name
841  *   e.g., "sooner"
842 TODO: debug?  sooner-debug, sooner:debug?
843  * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
844  *   e.g., "out/target/product/sooner"
845  * - An absolute path to the PRODUCT_OUT dir
846  *   e.g., "/src/device/out/target/product/sooner"
847  *
848  * Given <hint>, try to construct an absolute path to the
849  * ANDROID_PRODUCT_OUT dir.
850  */
find_product_out_path(const char * hint)851 static const char *find_product_out_path(const char *hint)
852 {
853     static char path_buf[PATH_MAX];
854 
855     if (hint == NULL || hint[0] == '\0') {
856         return NULL;
857     }
858 
859     /* If it's already absolute, don't bother doing any work.
860      */
861     if (adb_is_absolute_host_path(hint)) {
862         strcpy(path_buf, hint);
863         return path_buf;
864     }
865 
866     /* If there are any slashes in it, assume it's a relative path;
867      * make it absolute.
868      */
869     if (adb_dirstart(hint) != NULL) {
870         if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
871             fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
872             return NULL;
873         }
874         if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
875             fprintf(stderr, "adb: Couldn't assemble path\n");
876             return NULL;
877         }
878         strcat(path_buf, OS_PATH_SEPARATOR_STR);
879         strcat(path_buf, hint);
880         return path_buf;
881     }
882 
883     /* It's a string without any slashes.  Try to do something with it.
884      *
885      * Try to find the root of the build tree, and build a PRODUCT_OUT
886      * path from there.
887      */
888     char top_buf[PATH_MAX];
889     const char *top = find_top(top_buf);
890     if (top == NULL) {
891         fprintf(stderr, "adb: Couldn't find top of build tree\n");
892         return NULL;
893     }
894 //TODO: if we have a way to indicate debug, look in out/debug/target/...
895     snprintf(path_buf, sizeof(path_buf),
896             "%s" OS_PATH_SEPARATOR_STR
897             "out" OS_PATH_SEPARATOR_STR
898             "target" OS_PATH_SEPARATOR_STR
899             "product" OS_PATH_SEPARATOR_STR
900             "%s", top_buf, hint);
901     if (access(path_buf, F_OK) < 0) {
902         fprintf(stderr, "adb: Couldn't find a product dir "
903                 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
904         return NULL;
905     }
906     return path_buf;
907 }
908 
adb_commandline(int argc,char ** argv)909 int adb_commandline(int argc, char **argv)
910 {
911     char buf[4096];
912     int no_daemon = 0;
913     int is_daemon = 0;
914     int is_server = 0;
915     int persist = 0;
916     int r;
917     int quote;
918     transport_type ttype = kTransportAny;
919     char* serial = NULL;
920     char* server_port_str = NULL;
921 
922         /* If defined, this should be an absolute path to
923          * the directory containing all of the various system images
924          * for a particular product.  If not defined, and the adb
925          * command requires this information, then the user must
926          * specify the path using "-p".
927          */
928     gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
929     if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
930         gProductOutPath = NULL;
931     }
932     // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
933 
934     serial = getenv("ANDROID_SERIAL");
935 
936     /* Validate and assign the server port */
937     server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
938     int server_port = DEFAULT_ADB_PORT;
939     if (server_port_str && strlen(server_port_str) > 0) {
940         server_port = (int) strtol(server_port_str, NULL, 0);
941         if (server_port <= 0) {
942             fprintf(stderr,
943                     "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
944                     server_port_str);
945             return usage();
946         }
947     }
948 
949     /* modifiers and flags */
950     while(argc > 0) {
951         if(!strcmp(argv[0],"server")) {
952             is_server = 1;
953         } else if(!strcmp(argv[0],"nodaemon")) {
954             no_daemon = 1;
955         } else if (!strcmp(argv[0], "fork-server")) {
956             /* this is a special flag used only when the ADB client launches the ADB Server */
957             is_daemon = 1;
958         } else if(!strcmp(argv[0],"persist")) {
959             persist = 1;
960         } else if(!strncmp(argv[0], "-p", 2)) {
961             const char *product = NULL;
962             if (argv[0][2] == '\0') {
963                 if (argc < 2) return usage();
964                 product = argv[1];
965                 argc--;
966                 argv++;
967             } else {
968                 product = argv[0] + 2;
969             }
970             gProductOutPath = find_product_out_path(product);
971             if (gProductOutPath == NULL) {
972                 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
973                         product);
974                 return usage();
975             }
976         } else if (argv[0][0]=='-' && argv[0][1]=='s') {
977             if (isdigit(argv[0][2])) {
978                 serial = argv[0] + 2;
979             } else {
980                 if(argc < 2 || argv[0][2] != '\0') return usage();
981                 serial = argv[1];
982                 argc--;
983                 argv++;
984             }
985         } else if (!strcmp(argv[0],"-d")) {
986             ttype = kTransportUsb;
987         } else if (!strcmp(argv[0],"-e")) {
988             ttype = kTransportLocal;
989         } else {
990                 /* out of recognized modifiers and flags */
991             break;
992         }
993         argc--;
994         argv++;
995     }
996 
997     adb_set_transport(ttype, serial);
998     adb_set_tcp_specifics(server_port);
999 
1000     if (is_server) {
1001         if (no_daemon || is_daemon) {
1002             r = adb_main(is_daemon, server_port);
1003         } else {
1004             r = launch_server(server_port);
1005         }
1006         if(r) {
1007             fprintf(stderr,"* could not start server *\n");
1008         }
1009         return r;
1010     }
1011 
1012 top:
1013     if(argc == 0) {
1014         return usage();
1015     }
1016 
1017     /* adb_connect() commands */
1018 
1019     if(!strcmp(argv[0], "devices")) {
1020         char *tmp;
1021         char *listopt;
1022         if (argc < 2)
1023             listopt = "";
1024         else if (argc == 2 && !strcmp(argv[1], "-l"))
1025             listopt = argv[1];
1026         else {
1027             fprintf(stderr, "Usage: adb devices [-l]\n");
1028             return 1;
1029         }
1030         snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
1031         tmp = adb_query(buf);
1032         if(tmp) {
1033             printf("List of devices attached \n");
1034             printf("%s\n", tmp);
1035             return 0;
1036         } else {
1037             return 1;
1038         }
1039     }
1040 
1041     if(!strcmp(argv[0], "connect")) {
1042         char *tmp;
1043         if (argc != 2) {
1044             fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
1045             return 1;
1046         }
1047         snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1048         tmp = adb_query(buf);
1049         if(tmp) {
1050             printf("%s\n", tmp);
1051             return 0;
1052         } else {
1053             return 1;
1054         }
1055     }
1056 
1057     if(!strcmp(argv[0], "disconnect")) {
1058         char *tmp;
1059         if (argc > 2) {
1060             fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1061             return 1;
1062         }
1063         if (argc == 2) {
1064             snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1065         } else {
1066             snprintf(buf, sizeof buf, "host:disconnect:");
1067         }
1068         tmp = adb_query(buf);
1069         if(tmp) {
1070             printf("%s\n", tmp);
1071             return 0;
1072         } else {
1073             return 1;
1074         }
1075     }
1076 
1077     if (!strcmp(argv[0], "emu")) {
1078         return adb_send_emulator_command(argc, argv);
1079     }
1080 
1081     if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
1082         int r;
1083         int fd;
1084 
1085         char h = (argv[0][0] == 'h');
1086 
1087         if (h) {
1088             printf("\x1b[41;33m");
1089             fflush(stdout);
1090         }
1091 
1092         if(argc < 2) {
1093             D("starting interactive shell\n");
1094             r = interactive_shell();
1095             if (h) {
1096                 printf("\x1b[0m");
1097                 fflush(stdout);
1098             }
1099             return r;
1100         }
1101 
1102         snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1103         argc -= 2;
1104         argv += 2;
1105         while(argc-- > 0) {
1106             strcat(buf, " ");
1107 
1108             /* quote empty strings and strings with spaces */
1109             quote = (**argv == 0 || strchr(*argv, ' '));
1110             if (quote)
1111                 strcat(buf, "\"");
1112             strcat(buf, *argv++);
1113             if (quote)
1114                 strcat(buf, "\"");
1115         }
1116 
1117         for(;;) {
1118             D("interactive shell loop. buff=%s\n", buf);
1119             fd = adb_connect(buf);
1120             if(fd >= 0) {
1121                 D("about to read_and_dump(fd=%d)\n", fd);
1122                 read_and_dump(fd);
1123                 D("read_and_dump() done.\n");
1124                 adb_close(fd);
1125                 r = 0;
1126             } else {
1127                 fprintf(stderr,"error: %s\n", adb_error());
1128                 r = -1;
1129             }
1130 
1131             if(persist) {
1132                 fprintf(stderr,"\n- waiting for device -\n");
1133                 adb_sleep_ms(1000);
1134                 do_cmd(ttype, serial, "wait-for-device", 0);
1135             } else {
1136                 if (h) {
1137                     printf("\x1b[0m");
1138                     fflush(stdout);
1139                 }
1140                 D("interactive shell loop. return r=%d\n", r);
1141                 return r;
1142             }
1143         }
1144     }
1145 
1146     if(!strcmp(argv[0], "kill-server")) {
1147         int fd;
1148         fd = _adb_connect("host:kill");
1149         if(fd == -1) {
1150             fprintf(stderr,"* server not running *\n");
1151             return 1;
1152         }
1153         return 0;
1154     }
1155 
1156     if(!strcmp(argv[0], "sideload")) {
1157         if(argc != 2) return usage();
1158         if(adb_download("sideload", argv[1], 1)) {
1159             return 1;
1160         } else {
1161             return 0;
1162         }
1163     }
1164 
1165     if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
1166             || !strcmp(argv[0], "reboot-bootloader")
1167             || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
1168             || !strcmp(argv[0], "root")) {
1169         char command[100];
1170         if (!strcmp(argv[0], "reboot-bootloader"))
1171             snprintf(command, sizeof(command), "reboot:bootloader");
1172         else if (argc > 1)
1173             snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
1174         else
1175             snprintf(command, sizeof(command), "%s:", argv[0]);
1176         int fd = adb_connect(command);
1177         if(fd >= 0) {
1178             read_and_dump(fd);
1179             adb_close(fd);
1180             return 0;
1181         }
1182         fprintf(stderr,"error: %s\n", adb_error());
1183         return 1;
1184     }
1185 
1186     if(!strcmp(argv[0], "bugreport")) {
1187         if (argc != 1) return usage();
1188         do_cmd(ttype, serial, "shell", "bugreport", 0);
1189         return 0;
1190     }
1191 
1192     /* adb_command() wrapper commands */
1193 
1194     if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1195         char* service = argv[0];
1196         if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1197             if (ttype == kTransportUsb) {
1198                 service = "wait-for-usb";
1199             } else if (ttype == kTransportLocal) {
1200                 service = "wait-for-local";
1201             } else {
1202                 service = "wait-for-any";
1203             }
1204         }
1205 
1206         format_host_command(buf, sizeof buf, service, ttype, serial);
1207 
1208         if (adb_command(buf)) {
1209             D("failure: %s *\n",adb_error());
1210             fprintf(stderr,"error: %s\n", adb_error());
1211             return 1;
1212         }
1213 
1214         /* Allow a command to be run after wait-for-device,
1215             * e.g. 'adb wait-for-device shell'.
1216             */
1217         if(argc > 1) {
1218             argc--;
1219             argv++;
1220             goto top;
1221         }
1222         return 0;
1223     }
1224 
1225     if(!strcmp(argv[0], "forward")) {
1226         if(argc != 3) return usage();
1227         if (serial) {
1228             snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1229         } else if (ttype == kTransportUsb) {
1230             snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1231         } else if (ttype == kTransportLocal) {
1232             snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
1233         } else {
1234             snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
1235         }
1236         if(adb_command(buf)) {
1237             fprintf(stderr,"error: %s\n", adb_error());
1238             return 1;
1239         }
1240         return 0;
1241     }
1242 
1243     /* do_sync_*() commands */
1244 
1245     if(!strcmp(argv[0], "ls")) {
1246         if(argc != 2) return usage();
1247         return do_sync_ls(argv[1]);
1248     }
1249 
1250     if(!strcmp(argv[0], "push")) {
1251         if(argc != 3) return usage();
1252         return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1253     }
1254 
1255     if(!strcmp(argv[0], "pull")) {
1256         if (argc == 2) {
1257             return do_sync_pull(argv[1], ".");
1258         } else if (argc == 3) {
1259             return do_sync_pull(argv[1], argv[2]);
1260         } else {
1261             return usage();
1262         }
1263     }
1264 
1265     if(!strcmp(argv[0], "install")) {
1266         if (argc < 2) return usage();
1267         return install_app(ttype, serial, argc, argv);
1268     }
1269 
1270     if(!strcmp(argv[0], "uninstall")) {
1271         if (argc < 2) return usage();
1272         return uninstall_app(ttype, serial, argc, argv);
1273     }
1274 
1275     if(!strcmp(argv[0], "sync")) {
1276         char *srcarg, *android_srcpath, *data_srcpath;
1277         int listonly = 0;
1278 
1279         int ret;
1280         if(argc < 2) {
1281             /* No local path was specified. */
1282             srcarg = NULL;
1283         } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1284             listonly = 1;
1285             if (argc == 3) {
1286                 srcarg = argv[2];
1287             } else {
1288                 srcarg = NULL;
1289             }
1290         } else if(argc == 2) {
1291             /* A local path or "android"/"data" arg was specified. */
1292             srcarg = argv[1];
1293         } else {
1294             return usage();
1295         }
1296         ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1297         if(ret != 0) return usage();
1298 
1299         if(android_srcpath != NULL)
1300             ret = do_sync_sync(android_srcpath, "/system", listonly);
1301         if(ret == 0 && data_srcpath != NULL)
1302             ret = do_sync_sync(data_srcpath, "/data", listonly);
1303 
1304         free(android_srcpath);
1305         free(data_srcpath);
1306         return ret;
1307     }
1308 
1309     /* passthrough commands */
1310 
1311     if(!strcmp(argv[0],"get-state") ||
1312         !strcmp(argv[0],"get-serialno") ||
1313         !strcmp(argv[0],"get-devpath"))
1314     {
1315         char *tmp;
1316 
1317         format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1318         tmp = adb_query(buf);
1319         if(tmp) {
1320             printf("%s\n", tmp);
1321             return 0;
1322         } else {
1323             return 1;
1324         }
1325     }
1326 
1327     /* other commands */
1328 
1329     if(!strcmp(argv[0],"status-window")) {
1330         status_window(ttype, serial);
1331         return 0;
1332     }
1333 
1334     if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
1335         return logcat(ttype, serial, argc, argv);
1336     }
1337 
1338     if(!strcmp(argv[0],"ppp")) {
1339         return ppp(argc, argv);
1340     }
1341 
1342     if (!strcmp(argv[0], "start-server")) {
1343         return adb_connect("host:start-server");
1344     }
1345 
1346     if (!strcmp(argv[0], "backup")) {
1347         return backup(argc, argv);
1348     }
1349 
1350     if (!strcmp(argv[0], "restore")) {
1351         return restore(argc, argv);
1352     }
1353 
1354     if (!strcmp(argv[0], "jdwp")) {
1355         int  fd = adb_connect("jdwp");
1356         if (fd >= 0) {
1357             read_and_dump(fd);
1358             adb_close(fd);
1359             return 0;
1360         } else {
1361             fprintf(stderr, "error: %s\n", adb_error());
1362             return -1;
1363         }
1364     }
1365 
1366     /* "adb /?" is a common idiom under Windows */
1367     if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1368         help();
1369         return 0;
1370     }
1371 
1372     if(!strcmp(argv[0], "version")) {
1373         version(stdout);
1374         return 0;
1375     }
1376 
1377     usage();
1378     return 1;
1379 }
1380 
do_cmd(transport_type ttype,char * serial,char * cmd,...)1381 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1382 {
1383     char *argv[16];
1384     int argc;
1385     va_list ap;
1386 
1387     va_start(ap, cmd);
1388     argc = 0;
1389 
1390     if (serial) {
1391         argv[argc++] = "-s";
1392         argv[argc++] = serial;
1393     } else if (ttype == kTransportUsb) {
1394         argv[argc++] = "-d";
1395     } else if (ttype == kTransportLocal) {
1396         argv[argc++] = "-e";
1397     }
1398 
1399     argv[argc++] = cmd;
1400     while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1401     va_end(ap);
1402 
1403 #if 0
1404     int n;
1405     fprintf(stderr,"argc = %d\n",argc);
1406     for(n = 0; n < argc; n++) {
1407         fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1408     }
1409 #endif
1410 
1411     return adb_commandline(argc, argv);
1412 }
1413 
find_sync_dirs(const char * srcarg,char ** android_srcdir_out,char ** data_srcdir_out)1414 int find_sync_dirs(const char *srcarg,
1415         char **android_srcdir_out, char **data_srcdir_out)
1416 {
1417     char *android_srcdir, *data_srcdir;
1418 
1419     if(srcarg == NULL) {
1420         android_srcdir = product_file("system");
1421         data_srcdir = product_file("data");
1422     } else {
1423         /* srcarg may be "data", "system" or NULL.
1424          * if srcarg is NULL, then both data and system are synced
1425          */
1426         if(strcmp(srcarg, "system") == 0) {
1427             android_srcdir = product_file("system");
1428             data_srcdir = NULL;
1429         } else if(strcmp(srcarg, "data") == 0) {
1430             android_srcdir = NULL;
1431             data_srcdir = product_file("data");
1432         } else {
1433             /* It's not "system" or "data".
1434              */
1435             return 1;
1436         }
1437     }
1438 
1439     if(android_srcdir_out != NULL)
1440         *android_srcdir_out = android_srcdir;
1441     else
1442         free(android_srcdir);
1443 
1444     if(data_srcdir_out != NULL)
1445         *data_srcdir_out = data_srcdir;
1446     else
1447         free(data_srcdir);
1448 
1449     return 0;
1450 }
1451 
pm_command(transport_type transport,char * serial,int argc,char ** argv)1452 static int pm_command(transport_type transport, char* serial,
1453                       int argc, char** argv)
1454 {
1455     char buf[4096];
1456 
1457     snprintf(buf, sizeof(buf), "shell:pm");
1458 
1459     while(argc-- > 0) {
1460         char *quoted;
1461 
1462         quoted = dupAndQuote(*argv++);
1463 
1464         strncat(buf, " ", sizeof(buf)-1);
1465         strncat(buf, quoted, sizeof(buf)-1);
1466         free(quoted);
1467     }
1468 
1469     send_shellcommand(transport, serial, buf);
1470     return 0;
1471 }
1472 
uninstall_app(transport_type transport,char * serial,int argc,char ** argv)1473 int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1474 {
1475     /* if the user choose the -k option, we refuse to do it until devices are
1476        out with the option to uninstall the remaining data somehow (adb/ui) */
1477     if (argc == 3 && strcmp(argv[1], "-k") == 0)
1478     {
1479         printf(
1480             "The -k option uninstalls the application while retaining the data/cache.\n"
1481             "At the moment, there is no way to remove the remaining data.\n"
1482             "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1483             "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1484         return -1;
1485     }
1486 
1487     /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1488     return pm_command(transport, serial, argc, argv);
1489 }
1490 
delete_file(transport_type transport,char * serial,char * filename)1491 static int delete_file(transport_type transport, char* serial, char* filename)
1492 {
1493     char buf[4096];
1494     char* quoted;
1495 
1496     snprintf(buf, sizeof(buf), "shell:rm ");
1497     quoted = dupAndQuote(filename);
1498     strncat(buf, quoted, sizeof(buf)-1);
1499     free(quoted);
1500 
1501     send_shellcommand(transport, serial, buf);
1502     return 0;
1503 }
1504 
get_basename(const char * filename)1505 static const char* get_basename(const char* filename)
1506 {
1507     const char* basename = adb_dirstop(filename);
1508     if (basename) {
1509         basename++;
1510         return basename;
1511     } else {
1512         return filename;
1513     }
1514 }
1515 
check_file(const char * filename)1516 static int check_file(const char* filename)
1517 {
1518     struct stat st;
1519 
1520     if (filename == NULL) {
1521         return 0;
1522     }
1523 
1524     if (stat(filename, &st) != 0) {
1525         fprintf(stderr, "can't find '%s' to install\n", filename);
1526         return 1;
1527     }
1528 
1529     if (!S_ISREG(st.st_mode)) {
1530         fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
1531         return 1;
1532     }
1533 
1534     return 0;
1535 }
1536 
install_app(transport_type transport,char * serial,int argc,char ** argv)1537 int install_app(transport_type transport, char* serial, int argc, char** argv)
1538 {
1539     static const char *const DATA_DEST = "/data/local/tmp/%s";
1540     static const char *const SD_DEST = "/sdcard/tmp/%s";
1541     const char* where = DATA_DEST;
1542     char apk_dest[PATH_MAX];
1543     char verification_dest[PATH_MAX];
1544     char* apk_file;
1545     char* verification_file = NULL;
1546     int file_arg = -1;
1547     int err;
1548     int i;
1549     int verify_apk = 1;
1550 
1551     for (i = 1; i < argc; i++) {
1552         if (*argv[i] != '-') {
1553             file_arg = i;
1554             break;
1555         } else if (!strcmp(argv[i], "-i")) {
1556             // Skip the installer package name.
1557             i++;
1558         } else if (!strcmp(argv[i], "-s")) {
1559             where = SD_DEST;
1560         } else if (!strcmp(argv[i], "--algo")) {
1561             verify_apk = 0;
1562             i++;
1563         } else if (!strcmp(argv[i], "--iv")) {
1564             verify_apk = 0;
1565             i++;
1566         } else if (!strcmp(argv[i], "--key")) {
1567             verify_apk = 0;
1568             i++;
1569         }
1570     }
1571 
1572     if (file_arg < 0) {
1573         fprintf(stderr, "can't find filename in arguments\n");
1574         return 1;
1575     } else if (file_arg + 2 < argc) {
1576         fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
1577         return 1;
1578     }
1579 
1580     apk_file = argv[file_arg];
1581 
1582     if (file_arg != argc - 1) {
1583         verification_file = argv[file_arg + 1];
1584     }
1585 
1586     if (check_file(apk_file) || check_file(verification_file)) {
1587         return 1;
1588     }
1589 
1590     snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1591     if (verification_file != NULL) {
1592         snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1593 
1594         if (!strcmp(apk_dest, verification_dest)) {
1595             fprintf(stderr, "APK and verification file can't have the same name\n");
1596             return 1;
1597         }
1598     }
1599 
1600     err = do_sync_push(apk_file, apk_dest, verify_apk);
1601     if (err) {
1602         goto cleanup_apk;
1603     } else {
1604         argv[file_arg] = apk_dest; /* destination name, not source location */
1605     }
1606 
1607     if (verification_file != NULL) {
1608         err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
1609         if (err) {
1610             goto cleanup_apk;
1611         } else {
1612             argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1613         }
1614     }
1615 
1616     pm_command(transport, serial, argc, argv);
1617 
1618 cleanup_apk:
1619     if (verification_file != NULL) {
1620         delete_file(transport, serial, verification_dest);
1621     }
1622 
1623     delete_file(transport, serial, apk_dest);
1624 
1625     return err;
1626 }
1627