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 (%d bytes in %lld.%03llds)\n", 61 ((((long long) 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 closedir(d); 645 fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); 646 return -1; 647 } 648 if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { 649 fprintf(stderr, "skipping special file '%s'\n", ci->src); 650 free(ci); 651 } else { 652 ci->time = st.st_mtime; 653 ci->mode = st.st_mode; 654 ci->size = st.st_size; 655 ci->next = *filelist; 656 *filelist = ci; 657 } 658 } 659 } 660 661 closedir(d); 662 663 for(ci = dirlist; ci != 0; ci = next) { 664 next = ci->next; 665 local_build_list(filelist, ci->src, ci->dst); 666 free(ci); 667 } 668 669 return 0; 670 } 671 672 673 static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps, int listonly) 674 { 675 copyinfo *filelist = 0; 676 copyinfo *ci, *next; 677 int pushed = 0; 678 int skipped = 0; 679 680 if((lpath[0] == 0) || (rpath[0] == 0)) return -1; 681 if(lpath[strlen(lpath) - 1] != '/') { 682 int tmplen = strlen(lpath)+2; 683 char *tmp = malloc(tmplen); 684 if(tmp == 0) return -1; 685 snprintf(tmp, tmplen, "%s/",lpath); 686 lpath = tmp; 687 } 688 if(rpath[strlen(rpath) - 1] != '/') { 689 int tmplen = strlen(rpath)+2; 690 char *tmp = malloc(tmplen); 691 if(tmp == 0) return -1; 692 snprintf(tmp, tmplen, "%s/",rpath); 693 rpath = tmp; 694 } 695 696 if(local_build_list(&filelist, lpath, rpath)) { 697 return -1; 698 } 699 700 if(checktimestamps){ 701 for(ci = filelist; ci != 0; ci = ci->next) { 702 if(sync_start_readtime(fd, ci->dst)) { 703 return 1; 704 } 705 } 706 for(ci = filelist; ci != 0; ci = ci->next) { 707 unsigned int timestamp, mode, size; 708 if(sync_finish_readtime(fd, ×tamp, &mode, &size)) 709 return 1; 710 if(size == ci->size) { 711 /* for links, we cannot update the atime/mtime */ 712 if((S_ISREG(ci->mode & mode) && timestamp == ci->time) || 713 (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) 714 ci->flag = 1; 715 } 716 } 717 } 718 for(ci = filelist; ci != 0; ci = next) { 719 next = ci->next; 720 if(ci->flag == 0) { 721 fprintf(stderr,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst); 722 if(!listonly && 723 sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */)){ 724 return 1; 725 } 726 pushed++; 727 } else { 728 skipped++; 729 } 730 free(ci); 731 } 732 733 fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n", 734 pushed, (pushed == 1) ? "" : "s", 735 skipped, (skipped == 1) ? "" : "s"); 736 737 return 0; 738 } 739 740 741 int do_sync_push(const char *lpath, const char *rpath, int verifyApk) 742 { 743 struct stat st; 744 unsigned mode; 745 int fd; 746 747 fd = adb_connect("sync:"); 748 if(fd < 0) { 749 fprintf(stderr,"error: %s\n", adb_error()); 750 return 1; 751 } 752 753 if(stat(lpath, &st)) { 754 fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno)); 755 sync_quit(fd); 756 return 1; 757 } 758 759 if(S_ISDIR(st.st_mode)) { 760 BEGIN(); 761 if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) { 762 return 1; 763 } else { 764 END(); 765 sync_quit(fd); 766 } 767 } else { 768 if(sync_readmode(fd, rpath, &mode)) { 769 return 1; 770 } 771 if((mode != 0) && S_ISDIR(mode)) { 772 /* if we're copying a local file to a remote directory, 773 ** we *really* want to copy to remotedir + "/" + localfilename 774 */ 775 const char *name = adb_dirstop(lpath); 776 if(name == 0) { 777 name = lpath; 778 } else { 779 name++; 780 } 781 int tmplen = strlen(name) + strlen(rpath) + 2; 782 char *tmp = malloc(strlen(name) + strlen(rpath) + 2); 783 if(tmp == 0) return 1; 784 snprintf(tmp, tmplen, "%s/%s", rpath, name); 785 rpath = tmp; 786 } 787 BEGIN(); 788 if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk)) { 789 return 1; 790 } else { 791 END(); 792 sync_quit(fd); 793 return 0; 794 } 795 } 796 797 return 0; 798 } 799 800 801 typedef struct { 802 copyinfo **filelist; 803 copyinfo **dirlist; 804 const char *rpath; 805 const char *lpath; 806 } sync_ls_build_list_cb_args; 807 808 void 809 sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time, 810 const char *name, void *cookie) 811 { 812 sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie; 813 copyinfo *ci; 814 815 if (S_ISDIR(mode)) { 816 copyinfo **dirlist = args->dirlist; 817 818 /* Don't try recursing down "." or ".." */ 819 if (name[0] == '.') { 820 if (name[1] == '\0') return; 821 if ((name[1] == '.') && (name[2] == '\0')) return; 822 } 823 824 ci = mkcopyinfo(args->rpath, args->lpath, name, 1); 825 ci->next = *dirlist; 826 *dirlist = ci; 827 } else if (S_ISREG(mode) || S_ISLNK(mode)) { 828 copyinfo **filelist = args->filelist; 829 830 ci = mkcopyinfo(args->rpath, args->lpath, name, 0); 831 ci->time = time; 832 ci->mode = mode; 833 ci->size = size; 834 ci->next = *filelist; 835 *filelist = ci; 836 } else { 837 fprintf(stderr, "skipping special file '%s'\n", name); 838 } 839 } 840 841 static int remote_build_list(int syncfd, copyinfo **filelist, 842 const char *rpath, const char *lpath) 843 { 844 copyinfo *dirlist = NULL; 845 sync_ls_build_list_cb_args args; 846 847 args.filelist = filelist; 848 args.dirlist = &dirlist; 849 args.rpath = rpath; 850 args.lpath = lpath; 851 852 /* Put the files/dirs in rpath on the lists. */ 853 if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) { 854 return 1; 855 } 856 857 /* Recurse into each directory we found. */ 858 while (dirlist != NULL) { 859 copyinfo *next = dirlist->next; 860 if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) { 861 return 1; 862 } 863 free(dirlist); 864 dirlist = next; 865 } 866 867 return 0; 868 } 869 870 static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, 871 int checktimestamps) 872 { 873 copyinfo *filelist = 0; 874 copyinfo *ci, *next; 875 int pulled = 0; 876 int skipped = 0; 877 878 /* Make sure that both directory paths end in a slash. */ 879 if (rpath[0] == 0 || lpath[0] == 0) return -1; 880 if (rpath[strlen(rpath) - 1] != '/') { 881 int tmplen = strlen(rpath) + 2; 882 char *tmp = malloc(tmplen); 883 if (tmp == 0) return -1; 884 snprintf(tmp, tmplen, "%s/", rpath); 885 rpath = tmp; 886 } 887 if (lpath[strlen(lpath) - 1] != '/') { 888 int tmplen = strlen(lpath) + 2; 889 char *tmp = malloc(tmplen); 890 if (tmp == 0) return -1; 891 snprintf(tmp, tmplen, "%s/", lpath); 892 lpath = tmp; 893 } 894 895 fprintf(stderr, "pull: building file list...\n"); 896 /* Recursively build the list of files to copy. */ 897 if (remote_build_list(fd, &filelist, rpath, lpath)) { 898 return -1; 899 } 900 901 #if 0 902 if (checktimestamps) { 903 for (ci = filelist; ci != 0; ci = ci->next) { 904 if (sync_start_readtime(fd, ci->dst)) { 905 return 1; 906 } 907 } 908 for (ci = filelist; ci != 0; ci = ci->next) { 909 unsigned int timestamp, mode, size; 910 if (sync_finish_readtime(fd, ×tamp, &mode, &size)) 911 return 1; 912 if (size == ci->size) { 913 /* for links, we cannot update the atime/mtime */ 914 if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) || 915 (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) 916 ci->flag = 1; 917 } 918 } 919 } 920 #endif 921 for (ci = filelist; ci != 0; ci = next) { 922 next = ci->next; 923 if (ci->flag == 0) { 924 fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst); 925 if (sync_recv(fd, ci->src, ci->dst)) { 926 return 1; 927 } 928 pulled++; 929 } else { 930 skipped++; 931 } 932 free(ci); 933 } 934 935 fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n", 936 pulled, (pulled == 1) ? "" : "s", 937 skipped, (skipped == 1) ? "" : "s"); 938 939 return 0; 940 } 941 942 int do_sync_pull(const char *rpath, const char *lpath) 943 { 944 unsigned mode; 945 struct stat st; 946 947 int fd; 948 949 fd = adb_connect("sync:"); 950 if(fd < 0) { 951 fprintf(stderr,"error: %s\n", adb_error()); 952 return 1; 953 } 954 955 if(sync_readmode(fd, rpath, &mode)) { 956 return 1; 957 } 958 if(mode == 0) { 959 fprintf(stderr,"remote object '%s' does not exist\n", rpath); 960 return 1; 961 } 962 963 if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) { 964 if(stat(lpath, &st) == 0) { 965 if(S_ISDIR(st.st_mode)) { 966 /* if we're copying a remote file to a local directory, 967 ** we *really* want to copy to localdir + "/" + remotefilename 968 */ 969 const char *name = adb_dirstop(rpath); 970 if(name == 0) { 971 name = rpath; 972 } else { 973 name++; 974 } 975 int tmplen = strlen(name) + strlen(lpath) + 2; 976 char *tmp = malloc(tmplen); 977 if(tmp == 0) return 1; 978 snprintf(tmp, tmplen, "%s/%s", lpath, name); 979 lpath = tmp; 980 } 981 } 982 BEGIN(); 983 if(sync_recv(fd, rpath, lpath)) { 984 return 1; 985 } else { 986 END(); 987 sync_quit(fd); 988 return 0; 989 } 990 } else if(S_ISDIR(mode)) { 991 BEGIN(); 992 if (copy_remote_dir_local(fd, rpath, lpath, 0)) { 993 return 1; 994 } else { 995 END(); 996 sync_quit(fd); 997 return 0; 998 } 999 } else { 1000 fprintf(stderr,"remote object '%s' not a file or directory\n", rpath); 1001 return 1; 1002 } 1003 } 1004 1005 int do_sync_sync(const char *lpath, const char *rpath, int listonly) 1006 { 1007 fprintf(stderr,"syncing %s...\n",rpath); 1008 1009 int fd = adb_connect("sync:"); 1010 if(fd < 0) { 1011 fprintf(stderr,"error: %s\n", adb_error()); 1012 return 1; 1013 } 1014 1015 BEGIN(); 1016 if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){ 1017 return 1; 1018 } else { 1019 END(); 1020 sync_quit(fd); 1021 return 0; 1022 } 1023 } 1024