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