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 long long 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 ((total_bytes * 1000000LL) / t) / 1024LL, 62 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, ×tamp, &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, ×tamp, &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