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