Home | History | Annotate | Download | only in adb
      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 <sys/stat.h>
     22 #include <sys/time.h>
     23 #include <time.h>
     24 #include <dirent.h>
     25 #include <limits.h>
     26 #include <sys/types.h>
     27 #include <zipfile/zipfile.h>
     28 
     29 #include "sysdeps.h"
     30 #include "adb.h"
     31 #include "adb_client.h"
     32 #include "file_sync_service.h"
     33 
     34 
     35 static unsigned total_bytes;
     36 static long long start_time;
     37 
     38 static long long NOW()
     39 {
     40     struct timeval tv;
     41     gettimeofday(&tv, 0);
     42     return ((long long) tv.tv_usec) +
     43         1000000LL * ((long long) tv.tv_sec);
     44 }
     45 
     46 static void BEGIN()
     47 {
     48     total_bytes = 0;
     49     start_time = NOW();
     50 }
     51 
     52 static void END()
     53 {
     54     long long t = NOW() - start_time;
     55     if(total_bytes == 0) return;
     56 
     57     if (t == 0)  /* prevent division by 0 :-) */
     58         t = 1000000;
     59 
     60     fprintf(stderr,"%lld KB/s (%lld bytes in %lld.%03llds)\n",
     61             ((((long long) total_bytes) * 1000000LL) / t) / 1024LL,
     62             (long long) total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
     63 }
     64 
     65 void sync_quit(int fd)
     66 {
     67     syncmsg msg;
     68 
     69     msg.req.id = ID_QUIT;
     70     msg.req.namelen = 0;
     71 
     72     writex(fd, &msg.req, sizeof(msg.req));
     73 }
     74 
     75 typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
     76 
     77 int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie)
     78 {
     79     syncmsg msg;
     80     char buf[257];
     81     int len;
     82 
     83     len = strlen(path);
     84     if(len > 1024) goto fail;
     85 
     86     msg.req.id = ID_LIST;
     87     msg.req.namelen = htoll(len);
     88 
     89     if(writex(fd, &msg.req, sizeof(msg.req)) ||
     90        writex(fd, path, len)) {
     91         goto fail;
     92     }
     93 
     94     for(;;) {
     95         if(readx(fd, &msg.dent, sizeof(msg.dent))) break;
     96         if(msg.dent.id == ID_DONE) return 0;
     97         if(msg.dent.id != ID_DENT) break;
     98 
     99         len = ltohl(msg.dent.namelen);
    100         if(len > 256) break;
    101 
    102         if(readx(fd, buf, len)) break;
    103         buf[len] = 0;
    104 
    105         func(ltohl(msg.dent.mode),
    106              ltohl(msg.dent.size),
    107              ltohl(msg.dent.time),
    108              buf, cookie);
    109     }
    110 
    111 fail:
    112     adb_close(fd);
    113     return -1;
    114 }
    115 
    116 typedef struct syncsendbuf syncsendbuf;
    117 
    118 struct syncsendbuf {
    119     unsigned id;
    120     unsigned size;
    121     char data[SYNC_DATA_MAX];
    122 };
    123 
    124 static syncsendbuf send_buffer;
    125 
    126 int sync_readtime(int fd, const char *path, unsigned *timestamp)
    127 {
    128     syncmsg msg;
    129     int len = strlen(path);
    130 
    131     msg.req.id = ID_STAT;
    132     msg.req.namelen = htoll(len);
    133 
    134     if(writex(fd, &msg.req, sizeof(msg.req)) ||
    135        writex(fd, path, len)) {
    136         return -1;
    137     }
    138 
    139     if(readx(fd, &msg.stat, sizeof(msg.stat))) {
    140         return -1;
    141     }
    142 
    143     if(msg.stat.id != ID_STAT) {
    144         return -1;
    145     }
    146 
    147     *timestamp = ltohl(msg.stat.time);
    148     return 0;
    149 }
    150 
    151 static int sync_start_readtime(int fd, const char *path)
    152 {
    153     syncmsg msg;
    154     int len = strlen(path);
    155 
    156     msg.req.id = ID_STAT;
    157     msg.req.namelen = htoll(len);
    158 
    159     if(writex(fd, &msg.req, sizeof(msg.req)) ||
    160        writex(fd, path, len)) {
    161         return -1;
    162     }
    163 
    164     return 0;
    165 }
    166 
    167 static int sync_finish_readtime(int fd, unsigned int *timestamp,
    168                                 unsigned int *mode, unsigned int *size)
    169 {
    170     syncmsg msg;
    171 
    172     if(readx(fd, &msg.stat, sizeof(msg.stat)))
    173         return -1;
    174 
    175     if(msg.stat.id != ID_STAT)
    176         return -1;
    177 
    178     *timestamp = ltohl(msg.stat.time);
    179     *mode = ltohl(msg.stat.mode);
    180     *size = ltohl(msg.stat.size);
    181 
    182     return 0;
    183 }
    184 
    185 int sync_readmode(int fd, const char *path, unsigned *mode)
    186 {
    187     syncmsg msg;
    188     int len = strlen(path);
    189 
    190     msg.req.id = ID_STAT;
    191     msg.req.namelen = htoll(len);
    192 
    193     if(writex(fd, &msg.req, sizeof(msg.req)) ||
    194        writex(fd, path, len)) {
    195         return -1;
    196     }
    197 
    198     if(readx(fd, &msg.stat, sizeof(msg.stat))) {
    199         return -1;
    200     }
    201 
    202     if(msg.stat.id != ID_STAT) {
    203         return -1;
    204     }
    205 
    206     *mode = ltohl(msg.stat.mode);
    207     return 0;
    208 }
    209 
    210 static int write_data_file(int fd, const char *path, syncsendbuf *sbuf)
    211 {
    212     int lfd, err = 0;
    213 
    214     lfd = adb_open(path, O_RDONLY);
    215     if(lfd < 0) {
    216         fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno));
    217         return -1;
    218     }
    219 
    220     sbuf->id = ID_DATA;
    221     for(;;) {
    222         int ret;
    223 
    224         ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX);
    225         if(!ret)
    226             break;
    227 
    228         if(ret < 0) {
    229             if(errno == EINTR)
    230                 continue;
    231             fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
    232             break;
    233         }
    234 
    235         sbuf->size = htoll(ret);
    236         if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
    237             err = -1;
    238             break;
    239         }
    240         total_bytes += ret;
    241     }
    242 
    243     adb_close(lfd);
    244     return err;
    245 }
    246 
    247 static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf)
    248 {
    249     int err = 0;
    250     int total = 0;
    251 
    252     sbuf->id = ID_DATA;
    253     while (total < size) {
    254         int count = size - total;
    255         if (count > SYNC_DATA_MAX) {
    256             count = SYNC_DATA_MAX;
    257         }
    258 
    259         memcpy(sbuf->data, &file_buffer[total], count);
    260         sbuf->size = htoll(count);
    261         if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){
    262             err = -1;
    263             break;
    264         }
    265         total += count;
    266         total_bytes += count;
    267     }
    268 
    269     return err;
    270 }
    271 
    272 #ifdef HAVE_SYMLINKS
    273 static int write_data_link(int fd, const char *path, syncsendbuf *sbuf)
    274 {
    275     int len, ret;
    276 
    277     len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
    278     if(len < 0) {
    279         fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
    280         return -1;
    281     }
    282     sbuf->data[len] = '\0';
    283 
    284     sbuf->size = htoll(len + 1);
    285     sbuf->id = ID_DATA;
    286 
    287     ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1);
    288     if(ret)
    289         return -1;
    290 
    291     total_bytes += len + 1;
    292 
    293     return 0;
    294 }
    295 #endif
    296 
    297 static int sync_send(int fd, const char *lpath, const char *rpath,
    298                      unsigned mtime, mode_t mode, int verifyApk)
    299 {
    300     syncmsg msg;
    301     int len, r;
    302     syncsendbuf *sbuf = &send_buffer;
    303     char* file_buffer = NULL;
    304     int size = 0;
    305     char tmp[64];
    306 
    307     len = strlen(rpath);
    308     if(len > 1024) goto fail;
    309 
    310     snprintf(tmp, sizeof(tmp), ",%d", mode);
    311     r = strlen(tmp);
    312 
    313     if (verifyApk) {
    314         int lfd;
    315         zipfile_t zip;
    316         zipentry_t entry;
    317         int amt;
    318 
    319         // if we are transferring an APK file, then sanity check to make sure
    320         // we have a real zip file that contains an AndroidManifest.xml
    321         // this requires that we read the entire file into memory.
    322         lfd = adb_open(lpath, O_RDONLY);
    323         if(lfd < 0) {
    324             fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
    325             return -1;
    326         }
    327 
    328         size = adb_lseek(lfd, 0, SEEK_END);
    329         if (size == -1 || -1 == adb_lseek(lfd, 0, SEEK_SET)) {
    330             fprintf(stderr, "error seeking in file '%s'\n", lpath);
    331             adb_close(lfd);
    332             return 1;
    333         }
    334 
    335         file_buffer = (char *)malloc(size);
    336         if (file_buffer == NULL) {
    337             fprintf(stderr, "could not allocate buffer for '%s'\n",
    338                     lpath);
    339             adb_close(lfd);
    340             return 1;
    341         }
    342         amt = adb_read(lfd, file_buffer, size);
    343         if (amt != size) {
    344             fprintf(stderr, "error reading from file: '%s'\n", lpath);
    345             adb_close(lfd);
    346             free(file_buffer);
    347             return 1;
    348         }
    349 
    350         adb_close(lfd);
    351 
    352         zip = init_zipfile(file_buffer, size);
    353         if (zip == NULL) {
    354             fprintf(stderr, "file '%s' is not a valid zip file\n",
    355                     lpath);
    356             free(file_buffer);
    357             return 1;
    358         }
    359 
    360         entry = lookup_zipentry(zip, "AndroidManifest.xml");
    361         release_zipfile(zip);
    362         if (entry == NULL) {
    363             fprintf(stderr, "file '%s' does not contain AndroidManifest.xml\n",
    364                     lpath);
    365             free(file_buffer);
    366             return 1;
    367         }
    368     }
    369 
    370     msg.req.id = ID_SEND;
    371     msg.req.namelen = htoll(len + r);
    372 
    373     if(writex(fd, &msg.req, sizeof(msg.req)) ||
    374        writex(fd, rpath, len) || writex(fd, tmp, r)) {
    375         free(file_buffer);
    376         goto fail;
    377     }
    378 
    379     if (file_buffer) {
    380         write_data_buffer(fd, file_buffer, size, sbuf);
    381         free(file_buffer);
    382     } else if (S_ISREG(mode))
    383         write_data_file(fd, lpath, sbuf);
    384 #ifdef HAVE_SYMLINKS
    385     else if (S_ISLNK(mode))
    386         write_data_link(fd, lpath, sbuf);
    387 #endif
    388     else
    389         goto fail;
    390 
    391     msg.data.id = ID_DONE;
    392     msg.data.size = htoll(mtime);
    393     if(writex(fd, &msg.data, sizeof(msg.data)))
    394         goto fail;
    395 
    396     if(readx(fd, &msg.status, sizeof(msg.status)))
    397         return -1;
    398 
    399     if(msg.status.id != ID_OKAY) {
    400         if(msg.status.id == ID_FAIL) {
    401             len = ltohl(msg.status.msglen);
    402             if(len > 256) len = 256;
    403             if(readx(fd, sbuf->data, len)) {
    404                 return -1;
    405             }
    406             sbuf->data[len] = 0;
    407         } else
    408             strcpy(sbuf->data, "unknown reason");
    409 
    410         fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data);
    411         return -1;
    412     }
    413 
    414     return 0;
    415 
    416 fail:
    417     fprintf(stderr,"protocol failure\n");
    418     adb_close(fd);
    419     return -1;
    420 }
    421 
    422 static int mkdirs(char *name)
    423 {
    424     int ret;
    425     char *x = name + 1;
    426 
    427     for(;;) {
    428         x = adb_dirstart(x);
    429         if(x == 0) return 0;
    430         *x = 0;
    431         ret = adb_mkdir(name, 0775);
    432         *x = OS_PATH_SEPARATOR;
    433         if((ret < 0) && (errno != EEXIST)) {
    434             return ret;
    435         }
    436         x++;
    437     }
    438     return 0;
    439 }
    440 
    441 int sync_recv(int fd, const char *rpath, const char *lpath)
    442 {
    443     syncmsg msg;
    444     int len;
    445     int lfd = -1;
    446     char *buffer = send_buffer.data;
    447     unsigned id;
    448 
    449     len = strlen(rpath);
    450     if(len > 1024) return -1;
    451 
    452     msg.req.id = ID_RECV;
    453     msg.req.namelen = htoll(len);
    454     if(writex(fd, &msg.req, sizeof(msg.req)) ||
    455        writex(fd, rpath, len)) {
    456         return -1;
    457     }
    458 
    459     if(readx(fd, &msg.data, sizeof(msg.data))) {
    460         return -1;
    461     }
    462     id = msg.data.id;
    463 
    464     if((id == ID_DATA) || (id == ID_DONE)) {
    465         adb_unlink(lpath);
    466         mkdirs((char *)lpath);
    467         lfd = adb_creat(lpath, 0644);
    468         if(lfd < 0) {
    469             fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno));
    470             return -1;
    471         }
    472         goto handle_data;
    473     } else {
    474         goto remote_error;
    475     }
    476 
    477     for(;;) {
    478         if(readx(fd, &msg.data, sizeof(msg.data))) {
    479             return -1;
    480         }
    481         id = msg.data.id;
    482 
    483     handle_data:
    484         len = ltohl(msg.data.size);
    485         if(id == ID_DONE) break;
    486         if(id != ID_DATA) goto remote_error;
    487         if(len > SYNC_DATA_MAX) {
    488             fprintf(stderr,"data overrun\n");
    489             adb_close(lfd);
    490             return -1;
    491         }
    492 
    493         if(readx(fd, buffer, len)) {
    494             adb_close(lfd);
    495             return -1;
    496         }
    497 
    498         if(writex(lfd, buffer, len)) {
    499             fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno));
    500             adb_close(lfd);
    501             return -1;
    502         }
    503 
    504         total_bytes += len;
    505     }
    506 
    507     adb_close(lfd);
    508     return 0;
    509 
    510 remote_error:
    511     adb_close(lfd);
    512     adb_unlink(lpath);
    513 
    514     if(id == ID_FAIL) {
    515         len = ltohl(msg.data.size);
    516         if(len > 256) len = 256;
    517         if(readx(fd, buffer, len)) {
    518             return -1;
    519         }
    520         buffer[len] = 0;
    521     } else {
    522         memcpy(buffer, &id, 4);
    523         buffer[4] = 0;
    524 //        strcpy(buffer,"unknown reason");
    525     }
    526     fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);
    527     return 0;
    528 }
    529 
    530 
    531 
    532 /* --- */
    533 
    534 
    535 static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
    536                           const char *name, void *cookie)
    537 {
    538     printf("%08x %08x %08x %s\n", mode, size, time, name);
    539 }
    540 
    541 int do_sync_ls(const char *path)
    542 {
    543     int fd = adb_connect("sync:");
    544     if(fd < 0) {
    545         fprintf(stderr,"error: %s\n", adb_error());
    546         return 1;
    547     }
    548 
    549     if(sync_ls(fd, path, do_sync_ls_cb, 0)) {
    550         return 1;
    551     } else {
    552         sync_quit(fd);
    553         return 0;
    554     }
    555 }
    556 
    557 typedef struct copyinfo copyinfo;
    558 
    559 struct copyinfo
    560 {
    561     copyinfo *next;
    562     const char *src;
    563     const char *dst;
    564     unsigned int time;
    565     unsigned int mode;
    566     unsigned int size;
    567     int flag;
    568     //char data[0];
    569 };
    570 
    571 copyinfo *mkcopyinfo(const char *spath, const char *dpath,
    572                      const char *name, int isdir)
    573 {
    574     int slen = strlen(spath);
    575     int dlen = strlen(dpath);
    576     int nlen = strlen(name);
    577     int ssize = slen + nlen + 2;
    578     int dsize = dlen + nlen + 2;
    579 
    580     copyinfo *ci = malloc(sizeof(copyinfo) + ssize + dsize);
    581     if(ci == 0) {
    582         fprintf(stderr,"out of memory\n");
    583         abort();
    584     }
    585 
    586     ci->next = 0;
    587     ci->time = 0;
    588     ci->mode = 0;
    589     ci->size = 0;
    590     ci->flag = 0;
    591     ci->src = (const char*)(ci + 1);
    592     ci->dst = ci->src + ssize;
    593     snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name);
    594     snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name);
    595 
    596 //    fprintf(stderr,"mkcopyinfo('%s','%s')\n", ci->src, ci->dst);
    597     return ci;
    598 }
    599 
    600 
    601 static int local_build_list(copyinfo **filelist,
    602                             const char *lpath, const char *rpath)
    603 {
    604     DIR *d;
    605     struct dirent *de;
    606     struct stat st;
    607     copyinfo *dirlist = 0;
    608     copyinfo *ci, *next;
    609 
    610 //    fprintf(stderr,"local_build_list('%s','%s')\n", lpath, rpath);
    611 
    612     d = opendir(lpath);
    613     if(d == 0) {
    614         fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
    615         return -1;
    616     }
    617 
    618     while((de = readdir(d))) {
    619         char stat_path[PATH_MAX];
    620         char *name = de->d_name;
    621 
    622         if(name[0] == '.') {
    623             if(name[1] == 0) continue;
    624             if((name[1] == '.') && (name[2] == 0)) continue;
    625         }
    626 
    627         /*
    628          * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs
    629          * always returns DT_UNKNOWN, so we just use stat() for all cases.
    630          */
    631         if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path))
    632             continue;
    633         strcpy(stat_path, lpath);
    634         strcat(stat_path, de->d_name);
    635         stat(stat_path, &st);
    636 
    637         if (S_ISDIR(st.st_mode)) {
    638             ci = mkcopyinfo(lpath, rpath, name, 1);
    639             ci->next = dirlist;
    640             dirlist = ci;
    641         } else {
    642             ci = mkcopyinfo(lpath, rpath, name, 0);
    643             if(lstat(ci->src, &st)) {
    644                 fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));
    645                 closedir(d);
    646 
    647                 return -1;
    648             }
    649             if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
    650                 fprintf(stderr, "skipping special file '%s'\n", ci->src);
    651                 free(ci);
    652             } else {
    653                 ci->time = st.st_mtime;
    654                 ci->mode = st.st_mode;
    655                 ci->size = st.st_size;
    656                 ci->next = *filelist;
    657                 *filelist = ci;
    658             }
    659         }
    660     }
    661 
    662     closedir(d);
    663 
    664     for(ci = dirlist; ci != 0; ci = next) {
    665         next = ci->next;
    666         local_build_list(filelist, ci->src, ci->dst);
    667         free(ci);
    668     }
    669 
    670     return 0;
    671 }
    672 
    673 
    674 static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps, int listonly)
    675 {
    676     copyinfo *filelist = 0;
    677     copyinfo *ci, *next;
    678     int pushed = 0;
    679     int skipped = 0;
    680 
    681     if((lpath[0] == 0) || (rpath[0] == 0)) return -1;
    682     if(lpath[strlen(lpath) - 1] != '/') {
    683         int  tmplen = strlen(lpath)+2;
    684         char *tmp = malloc(tmplen);
    685         if(tmp == 0) return -1;
    686         snprintf(tmp, tmplen, "%s/",lpath);
    687         lpath = tmp;
    688     }
    689     if(rpath[strlen(rpath) - 1] != '/') {
    690         int tmplen = strlen(rpath)+2;
    691         char *tmp = malloc(tmplen);
    692         if(tmp == 0) return -1;
    693         snprintf(tmp, tmplen, "%s/",rpath);
    694         rpath = tmp;
    695     }
    696 
    697     if(local_build_list(&filelist, lpath, rpath)) {
    698         return -1;
    699     }
    700 
    701     if(checktimestamps){
    702         for(ci = filelist; ci != 0; ci = ci->next) {
    703             if(sync_start_readtime(fd, ci->dst)) {
    704                 return 1;
    705             }
    706         }
    707         for(ci = filelist; ci != 0; ci = ci->next) {
    708             unsigned int timestamp, mode, size;
    709             if(sync_finish_readtime(fd, &timestamp, &mode, &size))
    710                 return 1;
    711             if(size == ci->size) {
    712                 /* for links, we cannot update the atime/mtime */
    713                 if((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
    714                     (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
    715                     ci->flag = 1;
    716             }
    717         }
    718     }
    719     for(ci = filelist; ci != 0; ci = next) {
    720         next = ci->next;
    721         if(ci->flag == 0) {
    722             fprintf(stderr,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst);
    723             if(!listonly &&
    724                sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */)){
    725                 return 1;
    726             }
    727             pushed++;
    728         } else {
    729             skipped++;
    730         }
    731         free(ci);
    732     }
    733 
    734     fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n",
    735             pushed, (pushed == 1) ? "" : "s",
    736             skipped, (skipped == 1) ? "" : "s");
    737 
    738     return 0;
    739 }
    740 
    741 
    742 int do_sync_push(const char *lpath, const char *rpath, int verifyApk)
    743 {
    744     struct stat st;
    745     unsigned mode;
    746     int fd;
    747 
    748     fd = adb_connect("sync:");
    749     if(fd < 0) {
    750         fprintf(stderr,"error: %s\n", adb_error());
    751         return 1;
    752     }
    753 
    754     if(stat(lpath, &st)) {
    755         fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno));
    756         sync_quit(fd);
    757         return 1;
    758     }
    759 
    760     if(S_ISDIR(st.st_mode)) {
    761         BEGIN();
    762         if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
    763             return 1;
    764         } else {
    765             END();
    766             sync_quit(fd);
    767         }
    768     } else {
    769         if(sync_readmode(fd, rpath, &mode)) {
    770             return 1;
    771         }
    772         if((mode != 0) && S_ISDIR(mode)) {
    773                 /* if we're copying a local file to a remote directory,
    774                 ** we *really* want to copy to remotedir + "/" + localfilename
    775                 */
    776             const char *name = adb_dirstop(lpath);
    777             if(name == 0) {
    778                 name = lpath;
    779             } else {
    780                 name++;
    781             }
    782             int  tmplen = strlen(name) + strlen(rpath) + 2;
    783             char *tmp = malloc(strlen(name) + strlen(rpath) + 2);
    784             if(tmp == 0) return 1;
    785             snprintf(tmp, tmplen, "%s/%s", rpath, name);
    786             rpath = tmp;
    787         }
    788         BEGIN();
    789         if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk)) {
    790             return 1;
    791         } else {
    792             END();
    793             sync_quit(fd);
    794             return 0;
    795         }
    796     }
    797 
    798     return 0;
    799 }
    800 
    801 
    802 typedef struct {
    803     copyinfo **filelist;
    804     copyinfo **dirlist;
    805     const char *rpath;
    806     const char *lpath;
    807 } sync_ls_build_list_cb_args;
    808 
    809 void
    810 sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
    811                       const char *name, void *cookie)
    812 {
    813     sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;
    814     copyinfo *ci;
    815 
    816     if (S_ISDIR(mode)) {
    817         copyinfo **dirlist = args->dirlist;
    818 
    819         /* Don't try recursing down "." or ".." */
    820         if (name[0] == '.') {
    821             if (name[1] == '\0') return;
    822             if ((name[1] == '.') && (name[2] == '\0')) return;
    823         }
    824 
    825         ci = mkcopyinfo(args->rpath, args->lpath, name, 1);
    826         ci->next = *dirlist;
    827         *dirlist = ci;
    828     } else if (S_ISREG(mode) || S_ISLNK(mode)) {
    829         copyinfo **filelist = args->filelist;
    830 
    831         ci = mkcopyinfo(args->rpath, args->lpath, name, 0);
    832         ci->time = time;
    833         ci->mode = mode;
    834         ci->size = size;
    835         ci->next = *filelist;
    836         *filelist = ci;
    837     } else {
    838         fprintf(stderr, "skipping special file '%s'\n", name);
    839     }
    840 }
    841 
    842 static int remote_build_list(int syncfd, copyinfo **filelist,
    843                              const char *rpath, const char *lpath)
    844 {
    845     copyinfo *dirlist = NULL;
    846     sync_ls_build_list_cb_args args;
    847 
    848     args.filelist = filelist;
    849     args.dirlist = &dirlist;
    850     args.rpath = rpath;
    851     args.lpath = lpath;
    852 
    853     /* Put the files/dirs in rpath on the lists. */
    854     if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) {
    855         return 1;
    856     }
    857 
    858     /* Recurse into each directory we found. */
    859     while (dirlist != NULL) {
    860         copyinfo *next = dirlist->next;
    861         if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) {
    862             return 1;
    863         }
    864         free(dirlist);
    865         dirlist = next;
    866     }
    867 
    868     return 0;
    869 }
    870 
    871 static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
    872                                  int checktimestamps)
    873 {
    874     copyinfo *filelist = 0;
    875     copyinfo *ci, *next;
    876     int pulled = 0;
    877     int skipped = 0;
    878 
    879     /* Make sure that both directory paths end in a slash. */
    880     if (rpath[0] == 0 || lpath[0] == 0) return -1;
    881     if (rpath[strlen(rpath) - 1] != '/') {
    882         int  tmplen = strlen(rpath) + 2;
    883         char *tmp = malloc(tmplen);
    884         if (tmp == 0) return -1;
    885         snprintf(tmp, tmplen, "%s/", rpath);
    886         rpath = tmp;
    887     }
    888     if (lpath[strlen(lpath) - 1] != '/') {
    889         int  tmplen = strlen(lpath) + 2;
    890         char *tmp = malloc(tmplen);
    891         if (tmp == 0) return -1;
    892         snprintf(tmp, tmplen, "%s/", lpath);
    893         lpath = tmp;
    894     }
    895 
    896     fprintf(stderr, "pull: building file list...\n");
    897     /* Recursively build the list of files to copy. */
    898     if (remote_build_list(fd, &filelist, rpath, lpath)) {
    899         return -1;
    900     }
    901 
    902 #if 0
    903     if (checktimestamps) {
    904         for (ci = filelist; ci != 0; ci = ci->next) {
    905             if (sync_start_readtime(fd, ci->dst)) {
    906                 return 1;
    907             }
    908         }
    909         for (ci = filelist; ci != 0; ci = ci->next) {
    910             unsigned int timestamp, mode, size;
    911             if (sync_finish_readtime(fd, &timestamp, &mode, &size))
    912                 return 1;
    913             if (size == ci->size) {
    914                 /* for links, we cannot update the atime/mtime */
    915                 if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
    916                     (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
    917                     ci->flag = 1;
    918             }
    919         }
    920     }
    921 #endif
    922     for (ci = filelist; ci != 0; ci = next) {
    923         next = ci->next;
    924         if (ci->flag == 0) {
    925             fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
    926             if (sync_recv(fd, ci->src, ci->dst)) {
    927                 return 1;
    928             }
    929             pulled++;
    930         } else {
    931             skipped++;
    932         }
    933         free(ci);
    934     }
    935 
    936     fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
    937             pulled, (pulled == 1) ? "" : "s",
    938             skipped, (skipped == 1) ? "" : "s");
    939 
    940     return 0;
    941 }
    942 
    943 int do_sync_pull(const char *rpath, const char *lpath)
    944 {
    945     unsigned mode;
    946     struct stat st;
    947 
    948     int fd;
    949 
    950     fd = adb_connect("sync:");
    951     if(fd < 0) {
    952         fprintf(stderr,"error: %s\n", adb_error());
    953         return 1;
    954     }
    955 
    956     if(sync_readmode(fd, rpath, &mode)) {
    957         return 1;
    958     }
    959     if(mode == 0) {
    960         fprintf(stderr,"remote object '%s' does not exist\n", rpath);
    961         return 1;
    962     }
    963 
    964     if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
    965         if(stat(lpath, &st) == 0) {
    966             if(S_ISDIR(st.st_mode)) {
    967                     /* if we're copying a remote file to a local directory,
    968                     ** we *really* want to copy to localdir + "/" + remotefilename
    969                     */
    970                 const char *name = adb_dirstop(rpath);
    971                 if(name == 0) {
    972                     name = rpath;
    973                 } else {
    974                     name++;
    975                 }
    976                 int  tmplen = strlen(name) + strlen(lpath) + 2;
    977                 char *tmp = malloc(tmplen);
    978                 if(tmp == 0) return 1;
    979                 snprintf(tmp, tmplen, "%s/%s", lpath, name);
    980                 lpath = tmp;
    981             }
    982         }
    983         BEGIN();
    984         if(sync_recv(fd, rpath, lpath)) {
    985             return 1;
    986         } else {
    987             END();
    988             sync_quit(fd);
    989             return 0;
    990         }
    991     } else if(S_ISDIR(mode)) {
    992         BEGIN();
    993         if (copy_remote_dir_local(fd, rpath, lpath, 0)) {
    994             return 1;
    995         } else {
    996             END();
    997             sync_quit(fd);
    998             return 0;
    999         }
   1000     } else {
   1001         fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
   1002         return 1;
   1003     }
   1004 }
   1005 
   1006 int do_sync_sync(const char *lpath, const char *rpath, int listonly)
   1007 {
   1008     fprintf(stderr,"syncing %s...\n",rpath);
   1009 
   1010     int fd = adb_connect("sync:");
   1011     if(fd < 0) {
   1012         fprintf(stderr,"error: %s\n", adb_error());
   1013         return 1;
   1014     }
   1015 
   1016     BEGIN();
   1017     if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){
   1018         return 1;
   1019     } else {
   1020         END();
   1021         sync_quit(fd);
   1022         return 0;
   1023     }
   1024 }
   1025