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