file_sync_client.cpp revision 05786779f390b23cc8611b101458cd174cf4e938
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 <inttypes.h> 20#include <limits.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <sys/stat.h> 25#include <sys/time.h> 26#include <sys/types.h> 27#include <time.h> 28#include <unistd.h> 29#include <utime.h> 30 31#include <memory> 32#include <vector> 33 34#include "sysdeps.h" 35 36#include "adb.h" 37#include "adb_client.h" 38#include "adb_io.h" 39#include "adb_utils.h" 40#include "file_sync_service.h" 41#include "line_printer.h" 42 43#include <base/file.h> 44#include <base/strings.h> 45#include <base/stringprintf.h> 46 47struct syncsendbuf { 48 unsigned id; 49 unsigned size; 50 char data[SYNC_DATA_MAX]; 51}; 52 53class SyncConnection { 54 public: 55 SyncConnection() : total_bytes(0), start_time_ms_(CurrentTimeMs()) { 56 max = SYNC_DATA_MAX; // TODO: decide at runtime. 57 58 std::string error; 59 fd = adb_connect("sync:", &error); 60 if (fd < 0) { 61 Error("connect failed: %s", error.c_str()); 62 } 63 } 64 65 ~SyncConnection() { 66 if (!IsValid()) return; 67 68 if (SendQuit()) { 69 // We sent a quit command, so the server should be doing orderly 70 // shutdown soon. But if we encountered an error while we were using 71 // the connection, the server might still be sending data (before 72 // doing orderly shutdown), in which case we won't wait for all of 73 // the data nor the coming orderly shutdown. In the common success 74 // case, this will wait for the server to do orderly shutdown. 75 ReadOrderlyShutdown(fd); 76 } 77 adb_close(fd); 78 } 79 80 bool IsValid() { return fd >= 0; } 81 82 bool SendRequest(int id, const char* path_and_mode) { 83 size_t path_length = strlen(path_and_mode); 84 if (path_length > 1024) { 85 Error("SendRequest failed: path too long: %zu", path_length); 86 errno = ENAMETOOLONG; 87 return false; 88 } 89 90 // Sending header and payload in a single write makes a noticeable 91 // difference to "adb sync" performance. 92 std::vector<char> buf(sizeof(SyncRequest) + path_length); 93 SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]); 94 req->id = id; 95 req->path_length = path_length; 96 char* data = reinterpret_cast<char*>(req + 1); 97 memcpy(data, path_and_mode, path_length); 98 99 return WriteFdExactly(fd, &buf[0], buf.size()); 100 } 101 102 // Sending header, payload, and footer in a single write makes a huge 103 // difference to "adb sync" performance. 104 bool SendSmallFile(const char* path_and_mode, 105 const char* rpath, 106 const char* data, size_t data_length, 107 unsigned mtime) { 108 Print(rpath); 109 110 size_t path_length = strlen(path_and_mode); 111 if (path_length > 1024) { 112 Error("SendSmallFile failed: path too long: %zu", path_length); 113 errno = ENAMETOOLONG; 114 return false; 115 } 116 117 std::vector<char> buf(sizeof(SyncRequest) + path_length + 118 sizeof(SyncRequest) + data_length + 119 sizeof(SyncRequest)); 120 char* p = &buf[0]; 121 122 SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p); 123 req_send->id = ID_SEND; 124 req_send->path_length = path_length; 125 p += sizeof(SyncRequest); 126 memcpy(p, path_and_mode, path_length); 127 p += path_length; 128 129 SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p); 130 req_data->id = ID_DATA; 131 req_data->path_length = data_length; 132 p += sizeof(SyncRequest); 133 memcpy(p, data, data_length); 134 p += data_length; 135 136 SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p); 137 req_done->id = ID_DONE; 138 req_done->path_length = mtime; 139 p += sizeof(SyncRequest); 140 141 if (!WriteFdExactly(fd, &buf[0], (p - &buf[0]))) return false; 142 143 total_bytes += data_length; 144 return true; 145 } 146 147 bool CopyDone(const char* from, const char* to) { 148 syncmsg msg; 149 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) { 150 Error("failed to copy '%s' to '%s': no ID_DONE: %s", from, to, strerror(errno)); 151 return false; 152 } 153 if (msg.status.id == ID_OKAY) { 154 return true; 155 } 156 if (msg.status.id != ID_FAIL) { 157 Error("failed to copy '%s' to '%s': unknown reason %d", from, to, msg.status.id); 158 return false; 159 } 160 return ReportCopyFailure(from, to, msg); 161 } 162 163 bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) { 164 std::vector<char> buf(msg.status.msglen + 1); 165 if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) { 166 Error("failed to copy '%s' to '%s'; failed to read reason (!): %s", 167 from, to, strerror(errno)); 168 return false; 169 } 170 buf[msg.status.msglen] = 0; 171 Error("failed to copy '%s' to '%s': %s", from, to, &buf[0]); 172 return false; 173 } 174 175 std::string TransferRate() { 176 uint64_t ms = CurrentTimeMs() - start_time_ms_; 177 if (total_bytes == 0 || ms == 0) return ""; 178 179 double s = static_cast<double>(ms) / 1000LL; 180 double rate = (static_cast<double>(total_bytes) / s) / (1024*1024); 181 return android::base::StringPrintf(" %.1f MB/s (%" PRId64 " bytes in %.3fs)", 182 rate, total_bytes, s); 183 } 184 185 void Print(const std::string& s) { 186 // TODO: we actually don't want ELIDE; we want "ELIDE if smart, FULL if dumb". 187 line_printer_.Print(s, LinePrinter::ELIDE); 188 } 189 190 void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) { 191 std::string s = "adb: error: "; 192 193 va_list ap; 194 va_start(ap, fmt); 195 android::base::StringAppendV(&s, fmt, ap); 196 va_end(ap); 197 198 line_printer_.Print(s, LinePrinter::FULL); 199 } 200 201 uint64_t total_bytes; 202 203 // TODO: add a char[max] buffer here, to replace syncsendbuf... 204 int fd; 205 size_t max; 206 207 private: 208 uint64_t start_time_ms_; 209 210 LinePrinter line_printer_; 211 212 bool SendQuit() { 213 return SendRequest(ID_QUIT, ""); // TODO: add a SendResponse? 214 } 215 216 static uint64_t CurrentTimeMs() { 217 struct timeval tv; 218 gettimeofday(&tv, 0); // (Not clock_gettime because of Mac/Windows.) 219 return static_cast<uint64_t>(tv.tv_sec) * 1000 + tv.tv_usec / 1000; 220 } 221}; 222 223typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name, void* cookie); 224 225static bool sync_ls(SyncConnection& sc, const char* path, sync_ls_cb func, void* cookie) { 226 if (!sc.SendRequest(ID_LIST, path)) return false; 227 228 while (true) { 229 syncmsg msg; 230 if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false; 231 232 if (msg.dent.id == ID_DONE) return true; 233 if (msg.dent.id != ID_DENT) return false; 234 235 size_t len = msg.dent.namelen; 236 if (len > 256) return false; // TODO: resize buffer? continue? 237 238 char buf[257]; 239 if (!ReadFdExactly(sc.fd, buf, len)) return false; 240 buf[len] = 0; 241 242 func(msg.dent.mode, msg.dent.size, msg.dent.time, buf, cookie); 243 } 244} 245 246static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp, 247 unsigned int* mode, unsigned int* size) { 248 syncmsg msg; 249 if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) { 250 return false; 251 } 252 253 if (timestamp) *timestamp = msg.stat.time; 254 if (mode) *mode = msg.stat.mode; 255 if (size) *size = msg.stat.size; 256 257 return true; 258} 259 260static bool sync_stat(SyncConnection& sc, const char* path, 261 unsigned int* timestamp, unsigned int* mode, unsigned int* size) { 262 return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size); 263} 264 265static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, 266 const char* lpath, const char* rpath, 267 unsigned mtime) { 268 if (!sc.SendRequest(ID_SEND, path_and_mode)) { 269 sc.Error("failed to send ID_SEND message '%s': %s", path_and_mode, strerror(errno)); 270 return false; 271 } 272 273 struct stat st; 274 if (stat(lpath, &st) == -1) { 275 sc.Error("cannot stat '%s': %s", lpath, strerror(errno)); 276 return false; 277 } 278 279 uint64_t total_size = st.st_size; 280 uint64_t bytes_copied = 0; 281 282 int lfd = adb_open(lpath, O_RDONLY); 283 if (lfd < 0) { 284 sc.Error("cannot open '%s': %s", lpath, strerror(errno)); 285 return false; 286 } 287 288 syncsendbuf sbuf; 289 sbuf.id = ID_DATA; 290 while (true) { 291 int ret = adb_read(lfd, sbuf.data, sc.max); 292 if (ret <= 0) { 293 if (ret < 0) { 294 sc.Error("cannot read '%s': %s", lpath, strerror(errno)); 295 adb_close(lfd); 296 return false; 297 } 298 break; 299 } 300 301 sbuf.size = ret; 302 if (!WriteFdExactly(sc.fd, &sbuf, sizeof(unsigned) * 2 + ret)) { 303 adb_close(lfd); 304 return false; 305 } 306 sc.total_bytes += ret; 307 308 bytes_copied += ret; 309 310 int percentage = static_cast<int>(bytes_copied * 100 / total_size); 311 sc.Print(android::base::StringPrintf("%s: %d%%", rpath, percentage)); 312 } 313 314 adb_close(lfd); 315 316 syncmsg msg; 317 msg.data.id = ID_DONE; 318 msg.data.size = mtime; 319 if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) { 320 sc.Error("failed to send ID_DONE message for '%s': %s", rpath, strerror(errno)); 321 return false; 322 } 323 324 return true; 325} 326 327static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath, 328 unsigned mtime, mode_t mode) 329{ 330 std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode); 331 332 if (S_ISLNK(mode)) { 333#if !defined(_WIN32) 334 char buf[PATH_MAX]; 335 ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1); 336 if (data_length == -1) { 337 sc.Error("readlink '%s' failed: %s", lpath, strerror(errno)); 338 return false; 339 } 340 buf[data_length++] = '\0'; 341 342 if (!sc.SendSmallFile(path_and_mode.c_str(), rpath, buf, data_length, mtime)) return false; 343 return sc.CopyDone(lpath, rpath); 344#endif 345 } 346 347 if (!S_ISREG(mode)) { 348 sc.Error("local file '%s' has unsupported mode: 0o%o", lpath, mode); 349 return false; 350 } 351 352 struct stat st; 353 if (stat(lpath, &st) == -1) { 354 sc.Error("failed to stat local file '%s': %s", lpath, strerror(errno)); 355 return false; 356 } 357 if (st.st_size < SYNC_DATA_MAX) { 358 std::string data; 359 if (!android::base::ReadFileToString(lpath, &data)) { 360 sc.Error("failed to read all of '%s': %s", lpath, strerror(errno)); 361 return false; 362 } 363 if (!sc.SendSmallFile(path_and_mode.c_str(), rpath, data.data(), data.size(), mtime)) { 364 return false; 365 } 366 } else { 367 if (!SendLargeFile(sc, path_and_mode.c_str(), lpath, rpath, mtime)) { 368 return false; 369 } 370 } 371 return sc.CopyDone(lpath, rpath); 372} 373 374static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath) { 375 sc.Print(rpath); 376 377 unsigned size = 0; 378 if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false; 379 380 if (!sc.SendRequest(ID_RECV, rpath)) return false; 381 382 adb_unlink(lpath); 383 mkdirs(lpath); 384 int lfd = adb_creat(lpath, 0644); 385 if (lfd < 0) { 386 sc.Error("cannot create '%s': %s", lpath, strerror(errno)); 387 return false; 388 } 389 390 uint64_t bytes_copied = 0; 391 while (true) { 392 syncmsg msg; 393 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) { 394 adb_close(lfd); 395 adb_unlink(lpath); 396 return false; 397 } 398 399 if (msg.data.id == ID_DONE) break; 400 401 if (msg.data.id != ID_DATA) { 402 adb_close(lfd); 403 adb_unlink(lpath); 404 sc.ReportCopyFailure(rpath, lpath, msg); 405 return false; 406 } 407 408 if (msg.data.size > sc.max) { 409 sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max); 410 adb_close(lfd); 411 adb_unlink(lpath); 412 return false; 413 } 414 415 char buffer[SYNC_DATA_MAX]; 416 if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) { 417 adb_close(lfd); 418 adb_unlink(lpath); 419 return false; 420 } 421 422 if (!WriteFdExactly(lfd, buffer, msg.data.size)) { 423 sc.Error("cannot write '%s': %s", lpath, strerror(errno)); 424 adb_close(lfd); 425 adb_unlink(lpath); 426 return false; 427 } 428 429 sc.total_bytes += msg.data.size; 430 431 bytes_copied += msg.data.size; 432 433 int percentage = static_cast<int>(bytes_copied * 100 / size); 434 sc.Print(android::base::StringPrintf("%s: %d%%", rpath, percentage)); 435 } 436 437 adb_close(lfd); 438 return true; 439} 440 441static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time, 442 const char* name, void* /*cookie*/) { 443 printf("%08x %08x %08x %s\n", mode, size, time, name); 444} 445 446bool do_sync_ls(const char* path) { 447 SyncConnection sc; 448 if (!sc.IsValid()) return false; 449 450 return sync_ls(sc, path, do_sync_ls_cb, 0); 451} 452 453struct copyinfo 454{ 455 copyinfo *next; 456 const char *src; 457 const char *dst; 458 unsigned int time; 459 unsigned int mode; 460 uint64_t size; 461 int flag; 462}; 463 464static copyinfo* mkcopyinfo(const char* spath, const char* dpath, const char* name, int isdir) { 465 int slen = strlen(spath); 466 int dlen = strlen(dpath); 467 int nlen = strlen(name); 468 int ssize = slen + nlen + 2; 469 int dsize = dlen + nlen + 2; 470 471 copyinfo *ci = reinterpret_cast<copyinfo*>(malloc(sizeof(copyinfo) + ssize + dsize)); 472 if (ci == 0) { 473 fprintf(stderr, "out of memory\n"); 474 abort(); 475 } 476 477 ci->next = 0; 478 ci->time = 0; 479 ci->mode = 0; 480 ci->size = 0; 481 ci->flag = 0; 482 ci->src = (const char*)(ci + 1); 483 ci->dst = ci->src + ssize; 484 snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name); 485 snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name); 486 487 return ci; 488} 489 490static bool IsDotOrDotDot(const char* name) { 491 return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')); 492} 493 494static int local_build_list(SyncConnection& sc, 495 copyinfo** filelist, const char* lpath, const char* rpath) { 496 copyinfo *dirlist = 0; 497 copyinfo *ci, *next; 498 499 std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir); 500 if (!dir) { 501 sc.Error("cannot open '%s': %s", lpath, strerror(errno)); 502 return -1; 503 } 504 505 dirent* de; 506 while ((de = readdir(dir.get()))) { 507 if (IsDotOrDotDot(de->d_name)) continue; 508 509 char stat_path[PATH_MAX]; 510 if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) { 511 sc.Error("skipping long path '%s%s'", lpath, de->d_name); 512 continue; 513 } 514 strcpy(stat_path, lpath); 515 strcat(stat_path, de->d_name); 516 517 struct stat st; 518 if (!lstat(stat_path, &st)) { 519 if (S_ISDIR(st.st_mode)) { 520 ci = mkcopyinfo(lpath, rpath, de->d_name, 1); 521 ci->next = dirlist; 522 dirlist = ci; 523 } else { 524 ci = mkcopyinfo(lpath, rpath, de->d_name, 0); 525 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { 526 sc.Error("skipping special file '%s'", ci->src); 527 free(ci); 528 } else { 529 ci->time = st.st_mtime; 530 ci->mode = st.st_mode; 531 ci->size = st.st_size; 532 ci->next = *filelist; 533 *filelist = ci; 534 } 535 } 536 } else { 537 sc.Error("cannot lstat '%s': %s",stat_path , strerror(errno)); 538 } 539 } 540 541 // Close this directory and recurse. 542 dir.reset(); 543 for (ci = dirlist; ci != 0; ci = next) { 544 next = ci->next; 545 local_build_list(sc, filelist, ci->src, ci->dst); 546 free(ci); 547 } 548 549 return 0; 550} 551 552static bool copy_local_dir_remote(SyncConnection& sc, const char* lpath, const char* rpath, 553 bool check_timestamps, bool list_only) { 554 copyinfo *filelist = 0; 555 copyinfo *ci, *next; 556 int pushed = 0; 557 int skipped = 0; 558 559 if ((lpath[0] == 0) || (rpath[0] == 0)) return false; 560 if (lpath[strlen(lpath) - 1] != '/') { 561 int tmplen = strlen(lpath)+2; 562 char *tmp = reinterpret_cast<char*>(malloc(tmplen)); 563 if(tmp == 0) return false; 564 snprintf(tmp, tmplen, "%s/",lpath); 565 lpath = tmp; 566 } 567 if (rpath[strlen(rpath) - 1] != '/') { 568 int tmplen = strlen(rpath)+2; 569 char *tmp = reinterpret_cast<char*>(malloc(tmplen)); 570 if(tmp == 0) return false; 571 snprintf(tmp, tmplen, "%s/",rpath); 572 rpath = tmp; 573 } 574 575 if (local_build_list(sc, &filelist, lpath, rpath)) { 576 return false; 577 } 578 579 if (check_timestamps) { 580 for (ci = filelist; ci != 0; ci = ci->next) { 581 if (!sc.SendRequest(ID_STAT, ci->dst)) return false; 582 } 583 for(ci = filelist; ci != 0; ci = ci->next) { 584 unsigned int timestamp, mode, size; 585 if (!sync_finish_stat(sc, ×tamp, &mode, &size)) return false; 586 if (size == ci->size) { 587 /* for links, we cannot update the atime/mtime */ 588 if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) || 589 (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) { 590 ci->flag = 1; 591 } 592 } 593 } 594 } 595 for (ci = filelist; ci != 0; ci = next) { 596 next = ci->next; 597 if (ci->flag == 0) { 598 if (list_only) { 599 fprintf(stderr, "would push: %s -> %s\n", ci->src, ci->dst); 600 } else { 601 if (!sync_send(sc, ci->src, ci->dst, ci->time, ci->mode)) { 602 return false; 603 } 604 } 605 pushed++; 606 } else { 607 skipped++; 608 } 609 free(ci); 610 } 611 612 sc.Print(android::base::StringPrintf("%s: %d file%s pushed. %d file%s skipped.%s\n", 613 rpath, 614 pushed, (pushed == 1) ? "" : "s", 615 skipped, (skipped == 1) ? "" : "s", 616 sc.TransferRate().c_str())); 617 return true; 618} 619 620bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) { 621 SyncConnection sc; 622 if (!sc.IsValid()) return false; 623 624 bool success = true; 625 unsigned mode; 626 if (!sync_stat(sc, dst, nullptr, &mode, nullptr)) return false; 627 bool dst_isdir = mode != 0 && S_ISDIR(mode); 628 629 if (!dst_isdir) { 630 if (srcs.size() > 1) { 631 sc.Error("target '%s' is not a directory", dst); 632 return false; 633 } else { 634 size_t dst_len = strlen(dst); 635 if (dst[dst_len - 1] == '/') { 636 sc.Error("failed to access '%s': Not a directory", dst); 637 return false; 638 } 639 } 640 } 641 642 for (const char* src_path : srcs) { 643 const char* dst_path = dst; 644 struct stat st; 645 if (stat(src_path, &st)) { 646 sc.Error("cannot stat '%s': %s", src_path, strerror(errno)); 647 success = false; 648 continue; 649 } 650 651 if (S_ISDIR(st.st_mode)) { 652 success &= copy_local_dir_remote(sc, src_path, dst, false, false); 653 continue; 654 } 655 656 std::string path_holder; 657 if (mode != 0 && S_ISDIR(mode)) { 658 // If we're copying a local file to a remote directory, 659 // we really want to copy to remote_dir + "/" + local_filename. 660 path_holder = android::base::StringPrintf( 661 "%s/%s", dst_path, adb_basename(src_path).c_str()); 662 dst_path = path_holder.c_str(); 663 } 664 success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode); 665 } 666 667 sc.Print("\n"); 668 return success; 669} 670 671struct sync_ls_build_list_cb_args { 672 SyncConnection* sc; 673 copyinfo** filelist; 674 copyinfo** dirlist; 675 const char* rpath; 676 const char* lpath; 677}; 678 679static void sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time, 680 const char* name, void* cookie) 681{ 682 sync_ls_build_list_cb_args* args = static_cast<sync_ls_build_list_cb_args*>(cookie); 683 copyinfo *ci; 684 685 if (S_ISDIR(mode)) { 686 copyinfo **dirlist = args->dirlist; 687 688 // Don't try recursing down "." or "..". 689 if (IsDotOrDotDot(name)) return; 690 691 ci = mkcopyinfo(args->rpath, args->lpath, name, 1); 692 ci->next = *dirlist; 693 *dirlist = ci; 694 } else if (S_ISREG(mode) || S_ISLNK(mode)) { 695 copyinfo **filelist = args->filelist; 696 697 ci = mkcopyinfo(args->rpath, args->lpath, name, 0); 698 ci->time = time; 699 ci->mode = mode; 700 ci->size = size; 701 ci->next = *filelist; 702 *filelist = ci; 703 } else { 704 args->sc->Print(android::base::StringPrintf("skipping special file '%s'\n", name)); 705 } 706} 707 708static bool remote_build_list(SyncConnection& sc, copyinfo **filelist, 709 const char *rpath, const char *lpath) { 710 copyinfo* dirlist = nullptr; 711 712 sync_ls_build_list_cb_args args; 713 args.sc = ≻ 714 args.filelist = filelist; 715 args.dirlist = &dirlist; 716 args.rpath = rpath; 717 args.lpath = lpath; 718 719 // Put the files/dirs in rpath on the lists. 720 if (!sync_ls(sc, rpath, sync_ls_build_list_cb, &args)) { 721 return false; 722 } 723 724 // Recurse into each directory we found. 725 while (dirlist != NULL) { 726 copyinfo* next = dirlist->next; 727 if (!remote_build_list(sc, filelist, dirlist->src, dirlist->dst)) { 728 return false; 729 } 730 free(dirlist); 731 dirlist = next; 732 } 733 734 return true; 735} 736 737static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode) 738{ 739 struct utimbuf times = { time, time }; 740 int r1 = utime(lpath, ×); 741 742 /* use umask for permissions */ 743 mode_t mask=umask(0000); 744 umask(mask); 745 int r2 = chmod(lpath, mode & ~mask); 746 747 return r1 ? : r2; 748} 749 750static bool copy_remote_dir_local(SyncConnection& sc, const char* rpath, const char* lpath, 751 bool copy_attrs) { 752 // Make sure that both directory paths end in a slash. 753 std::string rpath_clean(rpath); 754 std::string lpath_clean(lpath); 755 if (rpath_clean.empty() || lpath_clean.empty()) return false; 756 if (rpath_clean.back() != '/') rpath_clean.push_back('/'); 757 if (lpath_clean.back() != '/') lpath_clean.push_back('/'); 758 759 // Recursively build the list of files to copy. 760 sc.Print("pull: building file list..."); 761 copyinfo* filelist = nullptr; 762 if (!remote_build_list(sc, &filelist, rpath_clean.c_str(), lpath_clean.c_str())) return false; 763 764 int pulled = 0; 765 int skipped = 0; 766 copyinfo* ci = filelist; 767 while (ci) { 768 copyinfo* next = ci->next; 769 if (ci->flag == 0) { 770 sc.Print(android::base::StringPrintf("pull: %s -> %s", ci->src, ci->dst)); 771 if (!sync_recv(sc, ci->src, ci->dst)) { 772 return false; 773 } 774 775 if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) { 776 return false; 777 } 778 pulled++; 779 } else { 780 skipped++; 781 } 782 free(ci); 783 ci = next; 784 } 785 786 sc.Print(android::base::StringPrintf("%s: %d file%s pulled. %d file%s skipped.%s\n", 787 rpath, 788 pulled, (pulled == 1) ? "" : "s", 789 skipped, (skipped == 1) ? "" : "s", 790 sc.TransferRate().c_str())); 791 return true; 792} 793 794bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, 795 bool copy_attrs) { 796 SyncConnection sc; 797 if (!sc.IsValid()) return false; 798 799 bool success = true; 800 unsigned mode, time; 801 struct stat st; 802 if (stat(dst, &st)) { 803 // If we're only pulling one file, the destination path might point to 804 // a path that doesn't exist yet. 805 if (srcs.size() != 1 || errno != ENOENT) { 806 sc.Error("cannot stat '%s': %s", dst, strerror(errno)); 807 return false; 808 } 809 } 810 811 bool dst_isdir = S_ISDIR(st.st_mode); 812 if (!dst_isdir) { 813 if (srcs.size() > 1) { 814 sc.Error("target '%s' is not a directory", dst); 815 return false; 816 } else { 817 size_t dst_len = strlen(dst); 818 if (dst[dst_len - 1] == '/') { 819 sc.Error("failed to access '%s': Not a directory", dst); 820 return false; 821 } 822 } 823 } 824 825 for (const char* src_path : srcs) { 826 const char* dst_path = dst; 827 if (!sync_stat(sc, src_path, &time, &mode, nullptr)) return false; 828 if (mode == 0) { 829 sc.Error("remote object '%s' does not exist", src_path); 830 success = false; 831 continue; 832 } 833 834 if (S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) { 835 std::string path_holder; 836 struct stat st; 837 if (stat(dst_path, &st) == 0) { 838 if (S_ISDIR(st.st_mode)) { 839 // If we're copying a remote file to a local directory, 840 // we really want to copy to local_dir + "/" + 841 // basename(remote). 842 path_holder = android::base::StringPrintf( 843 "%s/%s", dst_path, adb_basename(src_path).c_str()); 844 dst_path = path_holder.c_str(); 845 } 846 } 847 if (!sync_recv(sc, src_path, dst_path)) { 848 success = false; 849 continue; 850 } else { 851 if (copy_attrs && set_time_and_mode(dst_path, time, mode)) { 852 success = false; 853 continue; 854 } 855 } 856 } else if (S_ISDIR(mode)) { 857 success &= copy_remote_dir_local(sc, src_path, dst_path, copy_attrs); 858 continue; 859 } else { 860 sc.Error("remote object '%s' not a file or directory", src_path); 861 success = false; 862 continue; 863 } 864 } 865 866 sc.Print("\n"); 867 return success; 868} 869 870bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) { 871 SyncConnection sc; 872 if (!sc.IsValid()) return false; 873 874 return copy_local_dir_remote(sc, lpath.c_str(), rpath.c_str(), true, list_only); 875} 876