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