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 <dirent.h> 18#include <errno.h> 19#include <limits.h> 20#include <stdio.h> 21#include <stdlib.h> 22#include <string.h> 23#include <sys/stat.h> 24#include <sys/time.h> 25#include <sys/types.h> 26#include <time.h> 27#include <utime.h> 28 29#include "sysdeps.h" 30 31#include "adb.h" 32#include "adb_client.h" 33#include "adb_io.h" 34#include "file_sync_service.h" 35 36static unsigned long long total_bytes; 37static long long start_time; 38 39static 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 47static void BEGIN() 48{ 49 total_bytes = 0; 50 start_time = NOW(); 51} 52 53static 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 66static const char* transfer_progress_format = "\rTransferring: %llu/%llu (%d%%)"; 67 68static 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 82void sync_quit(int fd) 83{ 84 syncmsg msg; 85 86 msg.req.id = ID_QUIT; 87 msg.req.namelen = 0; 88 89 WriteFdExactly(fd, &msg.req, sizeof(msg.req)); 90} 91 92typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie); 93 94int 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(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || 107 !WriteFdExactly(fd, path, len)) { 108 goto fail; 109 } 110 111 for(;;) { 112 if(!ReadFdExactly(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(!ReadFdExactly(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 128fail: 129 adb_close(fd); 130 return -1; 131} 132 133struct syncsendbuf { 134 unsigned id; 135 unsigned size; 136 char data[SYNC_DATA_MAX]; 137}; 138 139static syncsendbuf send_buffer; 140 141int sync_readtime(int fd, const char *path, unsigned int *timestamp, 142 unsigned int *mode) 143{ 144 syncmsg msg; 145 int len = strlen(path); 146 147 msg.req.id = ID_STAT; 148 msg.req.namelen = htoll(len); 149 150 if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || 151 !WriteFdExactly(fd, path, len)) { 152 return -1; 153 } 154 155 if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) { 156 return -1; 157 } 158 159 if(msg.stat.id != ID_STAT) { 160 return -1; 161 } 162 163 *timestamp = ltohl(msg.stat.time); 164 *mode = ltohl(msg.stat.mode); 165 return 0; 166} 167 168static int sync_start_readtime(int fd, const char *path) 169{ 170 syncmsg msg; 171 int len = strlen(path); 172 173 msg.req.id = ID_STAT; 174 msg.req.namelen = htoll(len); 175 176 if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || 177 !WriteFdExactly(fd, path, len)) { 178 return -1; 179 } 180 181 return 0; 182} 183 184static int sync_finish_readtime(int fd, unsigned int *timestamp, 185 unsigned int *mode, unsigned int *size) 186{ 187 syncmsg msg; 188 189 if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) 190 return -1; 191 192 if(msg.stat.id != ID_STAT) 193 return -1; 194 195 *timestamp = ltohl(msg.stat.time); 196 *mode = ltohl(msg.stat.mode); 197 *size = ltohl(msg.stat.size); 198 199 return 0; 200} 201 202int sync_readmode(int fd, const char *path, unsigned *mode) 203{ 204 syncmsg msg; 205 int len = strlen(path); 206 207 msg.req.id = ID_STAT; 208 msg.req.namelen = htoll(len); 209 210 if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || 211 !WriteFdExactly(fd, path, len)) { 212 return -1; 213 } 214 215 if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) { 216 return -1; 217 } 218 219 if(msg.stat.id != ID_STAT) { 220 return -1; 221 } 222 223 *mode = ltohl(msg.stat.mode); 224 return 0; 225} 226 227static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show_progress) 228{ 229 int lfd, err = 0; 230 unsigned long long size = 0; 231 232 lfd = adb_open(path, O_RDONLY); 233 if(lfd < 0) { 234 fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno)); 235 return -1; 236 } 237 238 if (show_progress) { 239 // Determine local file size. 240 struct stat st; 241 if (stat(path, &st)) { 242 fprintf(stderr,"cannot stat '%s': %s\n", path, strerror(errno)); 243 return -1; 244 } 245 246 size = st.st_size; 247 } 248 249 sbuf->id = ID_DATA; 250 for(;;) { 251 int ret; 252 253 ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX); 254 if(!ret) 255 break; 256 257 if(ret < 0) { 258 if(errno == EINTR) 259 continue; 260 fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno)); 261 break; 262 } 263 264 sbuf->size = htoll(ret); 265 if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + ret)){ 266 err = -1; 267 break; 268 } 269 total_bytes += ret; 270 271 if (show_progress) { 272 print_transfer_progress(total_bytes, size); 273 } 274 } 275 276 adb_close(lfd); 277 return err; 278} 279 280static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf, 281 int show_progress) 282{ 283 int err = 0; 284 int total = 0; 285 286 sbuf->id = ID_DATA; 287 while (total < size) { 288 int count = size - total; 289 if (count > SYNC_DATA_MAX) { 290 count = SYNC_DATA_MAX; 291 } 292 293 memcpy(sbuf->data, &file_buffer[total], count); 294 sbuf->size = htoll(count); 295 if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + count)){ 296 err = -1; 297 break; 298 } 299 total += count; 300 total_bytes += count; 301 302 if (show_progress) { 303 print_transfer_progress(total, size); 304 } 305 } 306 307 return err; 308} 309 310#if defined(_WIN32) 311extern int write_data_link(int fd, const char *path, syncsendbuf *sbuf) __attribute__((error("no symlinks on Windows"))); 312#else 313static 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 = !WriteFdExactly(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 337static 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(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || 357 !WriteFdExactly(fd, rpath, len) || !WriteFdExactly(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 else if (S_ISLNK(mode)) 368 write_data_link(fd, lpath, sbuf); 369 else 370 goto fail; 371 372 msg.data.id = ID_DONE; 373 msg.data.size = htoll(mtime); 374 if(!WriteFdExactly(fd, &msg.data, sizeof(msg.data))) 375 goto fail; 376 377 if(!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) 378 return -1; 379 380 if(msg.status.id != ID_OKAY) { 381 if(msg.status.id == ID_FAIL) { 382 len = ltohl(msg.status.msglen); 383 if(len > 256) len = 256; 384 if(!ReadFdExactly(fd, sbuf->data, len)) { 385 return -1; 386 } 387 sbuf->data[len] = 0; 388 } else 389 strcpy(sbuf->data, "unknown reason"); 390 391 fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data); 392 return -1; 393 } 394 395 return 0; 396 397fail: 398 fprintf(stderr,"protocol failure\n"); 399 adb_close(fd); 400 return -1; 401} 402 403static int mkdirs(const char *name) 404{ 405 int ret; 406 char *x = (char *)name + 1; 407 408 for(;;) { 409 x = adb_dirstart(x); 410 if(x == 0) return 0; 411 *x = 0; 412 ret = adb_mkdir(name, 0775); 413 *x = OS_PATH_SEPARATOR; 414 if((ret < 0) && (errno != EEXIST)) { 415 return ret; 416 } 417 x++; 418 } 419 return 0; 420} 421 422int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress) 423{ 424 syncmsg msg; 425 int len; 426 int lfd = -1; 427 char *buffer = send_buffer.data; 428 unsigned id; 429 unsigned long long size = 0; 430 431 len = strlen(rpath); 432 if(len > 1024) return -1; 433 434 if (show_progress) { 435 // Determine remote file size. 436 syncmsg stat_msg; 437 stat_msg.req.id = ID_STAT; 438 stat_msg.req.namelen = htoll(len); 439 440 if (!WriteFdExactly(fd, &stat_msg.req, sizeof(stat_msg.req)) || 441 !WriteFdExactly(fd, rpath, len)) { 442 return -1; 443 } 444 445 if (!ReadFdExactly(fd, &stat_msg.stat, sizeof(stat_msg.stat))) { 446 return -1; 447 } 448 449 if (stat_msg.stat.id != ID_STAT) return -1; 450 451 size = ltohl(stat_msg.stat.size); 452 } 453 454 msg.req.id = ID_RECV; 455 msg.req.namelen = htoll(len); 456 if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || 457 !WriteFdExactly(fd, rpath, len)) { 458 return -1; 459 } 460 461 if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { 462 return -1; 463 } 464 id = msg.data.id; 465 466 if((id == ID_DATA) || (id == ID_DONE)) { 467 adb_unlink(lpath); 468 mkdirs(lpath); 469 lfd = adb_creat(lpath, 0644); 470 if(lfd < 0) { 471 fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno)); 472 return -1; 473 } 474 goto handle_data; 475 } else { 476 goto remote_error; 477 } 478 479 for(;;) { 480 if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { 481 return -1; 482 } 483 id = msg.data.id; 484 485 handle_data: 486 len = ltohl(msg.data.size); 487 if(id == ID_DONE) break; 488 if(id != ID_DATA) goto remote_error; 489 if(len > SYNC_DATA_MAX) { 490 fprintf(stderr,"data overrun\n"); 491 adb_close(lfd); 492 return -1; 493 } 494 495 if(!ReadFdExactly(fd, buffer, len)) { 496 adb_close(lfd); 497 return -1; 498 } 499 500 if(!WriteFdExactly(lfd, buffer, len)) { 501 fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); 502 adb_close(lfd); 503 return -1; 504 } 505 506 total_bytes += len; 507 508 if (show_progress) { 509 print_transfer_progress(total_bytes, size); 510 } 511 } 512 513 adb_close(lfd); 514 return 0; 515 516remote_error: 517 adb_close(lfd); 518 adb_unlink(lpath); 519 520 if(id == ID_FAIL) { 521 len = ltohl(msg.data.size); 522 if(len > 256) len = 256; 523 if(!ReadFdExactly(fd, buffer, len)) { 524 return -1; 525 } 526 buffer[len] = 0; 527 } else { 528 memcpy(buffer, &id, 4); 529 buffer[4] = 0; 530 } 531 fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer); 532 return 0; 533} 534 535/* --- */ 536static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time, 537 const char *name, void *cookie) 538{ 539 printf("%08x %08x %08x %s\n", mode, size, time, name); 540} 541 542int do_sync_ls(const char* path) { 543 std::string error; 544 int fd = adb_connect("sync:", &error); 545 if (fd < 0) { 546 fprintf(stderr,"error: %s\n", error.c_str()); 547 return 1; 548 } 549 550 if(sync_ls(fd, path, do_sync_ls_cb, 0)) { 551 return 1; 552 } else { 553 sync_quit(fd); 554 return 0; 555 } 556} 557 558struct copyinfo 559{ 560 copyinfo *next; 561 const char *src; 562 const char *dst; 563 unsigned int time; 564 unsigned int mode; 565 unsigned int size; 566 int flag; 567}; 568 569copyinfo *mkcopyinfo(const char *spath, const char *dpath, 570 const char *name, int isdir) 571{ 572 int slen = strlen(spath); 573 int dlen = strlen(dpath); 574 int nlen = strlen(name); 575 int ssize = slen + nlen + 2; 576 int dsize = dlen + nlen + 2; 577 578 copyinfo *ci = reinterpret_cast<copyinfo*>( 579 malloc(sizeof(copyinfo) + ssize + dsize)); 580 if(ci == 0) { 581 fprintf(stderr,"out of memory\n"); 582 abort(); 583 } 584 585 ci->next = 0; 586 ci->time = 0; 587 ci->mode = 0; 588 ci->size = 0; 589 ci->flag = 0; 590 ci->src = (const char*)(ci + 1); 591 ci->dst = ci->src + ssize; 592 snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name); 593 snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name); 594 595 return ci; 596} 597 598 599static int local_build_list(copyinfo **filelist, 600 const char *lpath, const char *rpath) 601{ 602 DIR *d; 603 struct dirent *de; 604 struct stat st; 605 copyinfo *dirlist = 0; 606 copyinfo *ci, *next; 607 608 d = opendir(lpath); 609 if(d == 0) { 610 fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno)); 611 return -1; 612 } 613 614 while((de = readdir(d))) { 615 char stat_path[PATH_MAX]; 616 char *name = de->d_name; 617 618 if(name[0] == '.') { 619 if(name[1] == 0) continue; 620 if((name[1] == '.') && (name[2] == 0)) continue; 621 } 622 623 /* 624 * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs 625 * always returns DT_UNKNOWN, so we just use stat() for all cases. 626 */ 627 if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) 628 continue; 629 strcpy(stat_path, lpath); 630 strcat(stat_path, de->d_name); 631 632 if(!lstat(stat_path, &st)) { 633 if (S_ISDIR(st.st_mode)) { 634 ci = mkcopyinfo(lpath, rpath, name, 1); 635 ci->next = dirlist; 636 dirlist = ci; 637 } else { 638 ci = mkcopyinfo(lpath, rpath, name, 0); 639 if(lstat(ci->src, &st)) { 640 fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); 641 free(ci); 642 closedir(d); 643 return -1; 644 } 645 if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { 646 fprintf(stderr, "skipping special file '%s'\n", ci->src); 647 free(ci); 648 } else { 649 ci->time = st.st_mtime; 650 ci->mode = st.st_mode; 651 ci->size = st.st_size; 652 ci->next = *filelist; 653 *filelist = ci; 654 } 655 } 656 } else { 657 fprintf(stderr, "cannot lstat '%s': %s\n",stat_path , strerror(errno)); 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 673static 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 = reinterpret_cast<char*>(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 = reinterpret_cast<char*>(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, 724 0 /* no show progress */)) { 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 742int do_sync_push(const char *lpath, const char *rpath, int show_progress) 743{ 744 struct stat st; 745 unsigned mode; 746 747 std::string error; 748 int fd = adb_connect("sync:", &error); 749 if (fd < 0) { 750 fprintf(stderr,"error: %s\n", error.c_str()); 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 = reinterpret_cast<char*>( 784 malloc(strlen(name) + strlen(rpath) + 2)); 785 if(tmp == 0) return 1; 786 snprintf(tmp, tmplen, "%s/%s", rpath, name); 787 rpath = tmp; 788 } 789 BEGIN(); 790 if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, show_progress)) { 791 return 1; 792 } else { 793 END(); 794 sync_quit(fd); 795 return 0; 796 } 797 } 798 799 return 0; 800} 801 802 803struct sync_ls_build_list_cb_args { 804 copyinfo **filelist; 805 copyinfo **dirlist; 806 const char *rpath; 807 const char *lpath; 808}; 809 810void 811sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time, 812 const char *name, void *cookie) 813{ 814 sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie; 815 copyinfo *ci; 816 817 if (S_ISDIR(mode)) { 818 copyinfo **dirlist = args->dirlist; 819 820 /* Don't try recursing down "." or ".." */ 821 if (name[0] == '.') { 822 if (name[1] == '\0') return; 823 if ((name[1] == '.') && (name[2] == '\0')) return; 824 } 825 826 ci = mkcopyinfo(args->rpath, args->lpath, name, 1); 827 ci->next = *dirlist; 828 *dirlist = ci; 829 } else if (S_ISREG(mode) || S_ISLNK(mode)) { 830 copyinfo **filelist = args->filelist; 831 832 ci = mkcopyinfo(args->rpath, args->lpath, name, 0); 833 ci->time = time; 834 ci->mode = mode; 835 ci->size = size; 836 ci->next = *filelist; 837 *filelist = ci; 838 } else { 839 fprintf(stderr, "skipping special file '%s'\n", name); 840 } 841} 842 843static int remote_build_list(int syncfd, copyinfo **filelist, 844 const char *rpath, const char *lpath) 845{ 846 copyinfo *dirlist = NULL; 847 sync_ls_build_list_cb_args args; 848 849 args.filelist = filelist; 850 args.dirlist = &dirlist; 851 args.rpath = rpath; 852 args.lpath = lpath; 853 854 /* Put the files/dirs in rpath on the lists. */ 855 if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) { 856 return 1; 857 } 858 859 /* Recurse into each directory we found. */ 860 while (dirlist != NULL) { 861 copyinfo *next = dirlist->next; 862 if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) { 863 return 1; 864 } 865 free(dirlist); 866 dirlist = next; 867 } 868 869 return 0; 870} 871 872static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode) 873{ 874 struct utimbuf times = { time, time }; 875 int r1 = utime(lpath, ×); 876 877 /* use umask for permissions */ 878 mode_t mask=umask(0000); 879 umask(mask); 880 int r2 = chmod(lpath, mode & ~mask); 881 882 return r1 ? : r2; 883} 884 885/* Return a copy of the path string with / appended if needed */ 886static char *add_slash_to_path(const char *path) 887{ 888 if (path[strlen(path) - 1] != '/') { 889 size_t len = strlen(path) + 2; 890 char *path_with_slash = reinterpret_cast<char*>(malloc(len)); 891 if (path_with_slash == NULL) 892 return NULL; 893 snprintf(path_with_slash, len, "%s/", path); 894 return path_with_slash; 895 } else { 896 return strdup(path); 897 } 898} 899 900static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, 901 int copy_attrs) 902{ 903 copyinfo *filelist = 0; 904 copyinfo *ci, *next; 905 int pulled = 0; 906 int skipped = 0; 907 char *rpath_clean = NULL; 908 char *lpath_clean = NULL; 909 int ret = 0; 910 911 if (rpath[0] == '\0' || lpath[0] == '\0') { 912 ret = -1; 913 goto finish; 914 } 915 916 /* Make sure that both directory paths end in a slash. */ 917 rpath_clean = add_slash_to_path(rpath); 918 if (!rpath_clean) { 919 ret = -1; 920 goto finish; 921 } 922 lpath_clean = add_slash_to_path(lpath); 923 if (!lpath_clean) { 924 ret = -1; 925 goto finish; 926 } 927 928 /* Recursively build the list of files to copy. */ 929 fprintf(stderr, "pull: building file list...\n"); 930 if (remote_build_list(fd, &filelist, rpath_clean, lpath_clean)) { 931 ret = -1; 932 goto finish; 933 } 934 935 for (ci = filelist; ci != 0; ci = next) { 936 next = ci->next; 937 if (ci->flag == 0) { 938 fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst); 939 if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) { 940 ret = -1; 941 goto finish; 942 } 943 944 if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) { 945 ret = -1; 946 goto finish; 947 } 948 pulled++; 949 } else { 950 skipped++; 951 } 952 free(ci); 953 } 954 955 fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n", 956 pulled, (pulled == 1) ? "" : "s", 957 skipped, (skipped == 1) ? "" : "s"); 958 959finish: 960 free(lpath_clean); 961 free(rpath_clean); 962 return ret; 963} 964 965int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int copy_attrs) 966{ 967 unsigned mode, time; 968 struct stat st; 969 970 std::string error; 971 int fd = adb_connect("sync:", &error); 972 if (fd < 0) { 973 fprintf(stderr,"error: %s\n", error.c_str()); 974 return 1; 975 } 976 977 if(sync_readtime(fd, rpath, &time, &mode)) { 978 return 1; 979 } 980 if(mode == 0) { 981 fprintf(stderr,"remote object '%s' does not exist\n", rpath); 982 return 1; 983 } 984 985 if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) { 986 if(stat(lpath, &st) == 0) { 987 if(S_ISDIR(st.st_mode)) { 988 /* if we're copying a remote file to a local directory, 989 ** we *really* want to copy to localdir + "/" + remotefilename 990 */ 991 const char *name = adb_dirstop(rpath); 992 if(name == 0) { 993 name = rpath; 994 } else { 995 name++; 996 } 997 int tmplen = strlen(name) + strlen(lpath) + 2; 998 char *tmp = reinterpret_cast<char*>(malloc(tmplen)); 999 if(tmp == 0) return 1; 1000 snprintf(tmp, tmplen, "%s/%s", lpath, name); 1001 lpath = tmp; 1002 } 1003 } 1004 BEGIN(); 1005 if (sync_recv(fd, rpath, lpath, show_progress)) { 1006 return 1; 1007 } else { 1008 if (copy_attrs && set_time_and_mode(lpath, time, mode)) 1009 return 1; 1010 END(); 1011 sync_quit(fd); 1012 return 0; 1013 } 1014 } else if(S_ISDIR(mode)) { 1015 BEGIN(); 1016 if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) { 1017 return 1; 1018 } else { 1019 END(); 1020 sync_quit(fd); 1021 return 0; 1022 } 1023 } else { 1024 fprintf(stderr,"remote object '%s' not a file or directory\n", rpath); 1025 return 1; 1026 } 1027} 1028 1029int do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) 1030{ 1031 fprintf(stderr, "syncing %s...\n", rpath.c_str()); 1032 1033 std::string error; 1034 int fd = adb_connect("sync:", &error); 1035 if (fd < 0) { 1036 fprintf(stderr, "error: %s\n", error.c_str()); 1037 return 1; 1038 } 1039 1040 BEGIN(); 1041 if (copy_local_dir_remote(fd, lpath.c_str(), rpath.c_str(), 1, list_only)) { 1042 return 1; 1043 } else { 1044 END(); 1045 sync_quit(fd); 1046 return 0; 1047 } 1048} 1049