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