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