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