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