• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NOW()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 
BEGIN()46 static void BEGIN()
47 {
48     total_bytes = 0;
49     start_time = NOW();
50 }
51 
END()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 
sync_quit(int fd)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 
sync_ls(int fd,const char * path,sync_ls_cb func,void * cookie)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 
sync_readtime(int fd,const char * path,unsigned * timestamp)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 
sync_start_readtime(int fd,const char * path)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 
sync_finish_readtime(int fd,unsigned int * timestamp,unsigned int * mode,unsigned int * size)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 
sync_readmode(int fd,const char * path,unsigned * mode)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 
write_data_file(int fd,const char * path,syncsendbuf * sbuf)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 
write_data_buffer(int fd,char * file_buffer,int size,syncsendbuf * sbuf)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
write_data_link(int fd,const char * path,syncsendbuf * sbuf)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 
sync_send(int fd,const char * lpath,const char * rpath,unsigned mtime,mode_t mode,int verifyApk)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 
mkdirs(char * name)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 
sync_recv(int fd,const char * rpath,const char * lpath)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 
do_sync_ls_cb(unsigned mode,unsigned size,unsigned time,const char * name,void * cookie)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 
do_sync_ls(const char * path)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 
mkcopyinfo(const char * spath,const char * dpath,const char * name,int isdir)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 
local_build_list(copyinfo ** filelist,const char * lpath,const char * rpath)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 
copy_local_dir_remote(int fd,const char * lpath,const char * rpath,int checktimestamps,int listonly)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 
do_sync_push(const char * lpath,const char * rpath,int verifyApk)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
sync_ls_build_list_cb(unsigned mode,unsigned size,unsigned time,const char * name,void * cookie)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 
remote_build_list(int syncfd,copyinfo ** filelist,const char * rpath,const char * lpath)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 
copy_remote_dir_local(int fd,const char * rpath,const char * lpath,int checktimestamps)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 
do_sync_pull(const char * rpath,const char * lpath)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 
do_sync_sync(const char * lpath,const char * rpath,int listonly)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