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 <functional>
32 #include <memory>
33 #include <vector>
34
35 #include "sysdeps.h"
36
37 #include "adb.h"
38 #include "adb_client.h"
39 #include "adb_io.h"
40 #include "adb_utils.h"
41 #include "file_sync_service.h"
42 #include "line_printer.h"
43
44 #include <android-base/file.h>
45 #include <android-base/strings.h>
46 #include <android-base/stringprintf.h>
47
48 struct syncsendbuf {
49 unsigned id;
50 unsigned size;
51 char data[SYNC_DATA_MAX];
52 };
53
ensure_trailing_separators(std::string & local_path,std::string & remote_path)54 static void ensure_trailing_separators(std::string& local_path, std::string& remote_path) {
55 if (!adb_is_separator(local_path.back())) {
56 local_path.push_back(OS_PATH_SEPARATOR);
57 }
58 if (remote_path.back() != '/') {
59 remote_path.push_back('/');
60 }
61 }
62
should_pull_file(mode_t mode)63 static bool should_pull_file(mode_t mode) {
64 return mode & (S_IFREG | S_IFBLK | S_IFCHR);
65 }
66
should_push_file(mode_t mode)67 static bool should_push_file(mode_t mode) {
68 mode_t mask = S_IFREG;
69 #if !defined(_WIN32)
70 mask |= S_IFLNK;
71 #endif
72 return mode & mask;
73 }
74
75 struct copyinfo {
76 std::string lpath;
77 std::string rpath;
78 unsigned int time = 0;
79 unsigned int mode;
80 uint64_t size = 0;
81 bool skip = false;
82
copyinfocopyinfo83 copyinfo(const std::string& local_path,
84 const std::string& remote_path,
85 const std::string& name,
86 unsigned int mode)
87 : lpath(local_path), rpath(remote_path), mode(mode) {
88 ensure_trailing_separators(lpath, rpath);
89 lpath.append(name);
90 rpath.append(name);
91 if (S_ISDIR(mode)) {
92 ensure_trailing_separators(lpath, rpath);
93 }
94 }
95 };
96
97 class SyncConnection {
98 public:
SyncConnection()99 SyncConnection()
100 : total_bytes_(0),
101 start_time_ms_(CurrentTimeMs()),
102 expected_total_bytes_(0),
103 expect_multiple_files_(false),
104 expect_done_(false) {
105 max = SYNC_DATA_MAX; // TODO: decide at runtime.
106
107 std::string error;
108 fd = adb_connect("sync:", &error);
109 if (fd < 0) {
110 Error("connect failed: %s", error.c_str());
111 }
112 }
113
~SyncConnection()114 ~SyncConnection() {
115 if (!IsValid()) return;
116
117 if (SendQuit()) {
118 // We sent a quit command, so the server should be doing orderly
119 // shutdown soon. But if we encountered an error while we were using
120 // the connection, the server might still be sending data (before
121 // doing orderly shutdown), in which case we won't wait for all of
122 // the data nor the coming orderly shutdown. In the common success
123 // case, this will wait for the server to do orderly shutdown.
124 ReadOrderlyShutdown(fd);
125 }
126 adb_close(fd);
127
128 line_printer_.KeepInfoLine();
129 }
130
IsValid()131 bool IsValid() { return fd >= 0; }
132
ReceivedError(const char * from,const char * to)133 bool ReceivedError(const char* from, const char* to) {
134 adb_pollfd pfd = {.fd = fd, .events = POLLIN};
135 int rc = adb_poll(&pfd, 1, 0);
136 if (rc < 0) {
137 Error("failed to poll: %s", strerror(errno));
138 return true;
139 }
140 return rc != 0;
141 }
142
SendRequest(int id,const char * path_and_mode)143 bool SendRequest(int id, const char* path_and_mode) {
144 size_t path_length = strlen(path_and_mode);
145 if (path_length > 1024) {
146 Error("SendRequest failed: path too long: %zu", path_length);
147 errno = ENAMETOOLONG;
148 return false;
149 }
150
151 // Sending header and payload in a single write makes a noticeable
152 // difference to "adb sync" performance.
153 std::vector<char> buf(sizeof(SyncRequest) + path_length);
154 SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
155 req->id = id;
156 req->path_length = path_length;
157 char* data = reinterpret_cast<char*>(req + 1);
158 memcpy(data, path_and_mode, path_length);
159
160 return WriteFdExactly(fd, &buf[0], buf.size());
161 }
162
163 // Sending header, payload, and footer in a single write makes a huge
164 // difference to "adb sync" performance.
SendSmallFile(const char * path_and_mode,const char * lpath,const char * rpath,unsigned mtime,const char * data,size_t data_length)165 bool SendSmallFile(const char* path_and_mode,
166 const char* lpath, const char* rpath,
167 unsigned mtime,
168 const char* data, size_t data_length) {
169 size_t path_length = strlen(path_and_mode);
170 if (path_length > 1024) {
171 Error("SendSmallFile failed: path too long: %zu", path_length);
172 errno = ENAMETOOLONG;
173 return false;
174 }
175
176 std::vector<char> buf(sizeof(SyncRequest) + path_length +
177 sizeof(SyncRequest) + data_length +
178 sizeof(SyncRequest));
179 char* p = &buf[0];
180
181 SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
182 req_send->id = ID_SEND;
183 req_send->path_length = path_length;
184 p += sizeof(SyncRequest);
185 memcpy(p, path_and_mode, path_length);
186 p += path_length;
187
188 SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p);
189 req_data->id = ID_DATA;
190 req_data->path_length = data_length;
191 p += sizeof(SyncRequest);
192 memcpy(p, data, data_length);
193 p += data_length;
194
195 SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p);
196 req_done->id = ID_DONE;
197 req_done->path_length = mtime;
198 p += sizeof(SyncRequest);
199
200 WriteOrDie(lpath, rpath, &buf[0], (p - &buf[0]));
201 expect_done_ = true;
202 total_bytes_ += data_length;
203 ReportProgress(rpath, data_length, data_length);
204 return true;
205 }
206
SendLargeFile(const char * path_and_mode,const char * lpath,const char * rpath,unsigned mtime)207 bool SendLargeFile(const char* path_and_mode,
208 const char* lpath, const char* rpath,
209 unsigned mtime) {
210 if (!SendRequest(ID_SEND, path_and_mode)) {
211 Error("failed to send ID_SEND message '%s': %s", path_and_mode, strerror(errno));
212 return false;
213 }
214
215 struct stat st;
216 if (stat(lpath, &st) == -1) {
217 Error("cannot stat '%s': %s", lpath, strerror(errno));
218 return false;
219 }
220
221 uint64_t total_size = st.st_size;
222 uint64_t bytes_copied = 0;
223
224 int lfd = adb_open(lpath, O_RDONLY);
225 if (lfd < 0) {
226 Error("opening '%s' locally failed: %s", lpath, strerror(errno));
227 return false;
228 }
229
230 syncsendbuf sbuf;
231 sbuf.id = ID_DATA;
232 while (true) {
233 int bytes_read = adb_read(lfd, sbuf.data, max);
234 if (bytes_read == -1) {
235 Error("reading '%s' locally failed: %s", lpath, strerror(errno));
236 adb_close(lfd);
237 return false;
238 } else if (bytes_read == 0) {
239 break;
240 }
241
242 sbuf.size = bytes_read;
243 WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + bytes_read);
244
245 total_bytes_ += bytes_read;
246 bytes_copied += bytes_read;
247
248 // Check to see if we've received an error from the other side.
249 if (ReceivedError(lpath, rpath)) {
250 break;
251 }
252
253 ReportProgress(rpath, bytes_copied, total_size);
254 }
255
256 adb_close(lfd);
257
258 syncmsg msg;
259 msg.data.id = ID_DONE;
260 msg.data.size = mtime;
261 expect_done_ = true;
262 return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
263 }
264
CopyDone(const char * from,const char * to)265 bool CopyDone(const char* from, const char* to) {
266 syncmsg msg;
267 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
268 Error("failed to copy '%s' to '%s': couldn't read from device", from, to);
269 return false;
270 }
271 if (msg.status.id == ID_OKAY) {
272 if (expect_done_) {
273 expect_done_ = false;
274 return true;
275 } else {
276 Error("failed to copy '%s' to '%s': received premature success", from, to);
277 return true;
278 }
279 }
280 if (msg.status.id != ID_FAIL) {
281 Error("failed to copy '%s' to '%s': unknown reason %d", from, to, msg.status.id);
282 return false;
283 }
284 return ReportCopyFailure(from, to, msg);
285 }
286
ReportCopyFailure(const char * from,const char * to,const syncmsg & msg)287 bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
288 std::vector<char> buf(msg.status.msglen + 1);
289 if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
290 Error("failed to copy '%s' to '%s'; failed to read reason (!): %s",
291 from, to, strerror(errno));
292 return false;
293 }
294 buf[msg.status.msglen] = 0;
295 Error("failed to copy '%s' to '%s': %s", from, to, &buf[0]);
296 return false;
297 }
298
TransferRate()299 std::string TransferRate() {
300 uint64_t ms = CurrentTimeMs() - start_time_ms_;
301 if (total_bytes_ == 0 || ms == 0) return "";
302
303 double s = static_cast<double>(ms) / 1000LL;
304 double rate = (static_cast<double>(total_bytes_) / s) / (1024*1024);
305 return android::base::StringPrintf(" %.1f MB/s (%" PRId64 " bytes in %.3fs)",
306 rate, total_bytes_, s);
307 }
308
ReportProgress(const char * file,uint64_t file_copied_bytes,uint64_t file_total_bytes)309 void ReportProgress(const char* file, uint64_t file_copied_bytes, uint64_t file_total_bytes) {
310 char overall_percentage_str[5] = "?";
311 if (expected_total_bytes_ != 0) {
312 int overall_percentage = static_cast<int>(total_bytes_ * 100 / expected_total_bytes_);
313 // If we're pulling symbolic links, we'll pull the target of the link rather than
314 // just create a local link, and that will cause us to go over 100%.
315 if (overall_percentage <= 100) {
316 snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
317 overall_percentage);
318 }
319 }
320
321 if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
322 // This case can happen if we're racing against something that wrote to the file
323 // between our stat and our read, or if we're reading a magic file that lies about
324 // its size. Just show how much we've copied.
325 Printf("[%4s] %s: %" PRId64 "/?", overall_percentage_str, file, file_copied_bytes);
326 } else {
327 // If we're transferring multiple files, we want to know how far through the current
328 // file we are, as well as the overall percentage.
329 if (expect_multiple_files_) {
330 int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
331 Printf("[%4s] %s: %d%%", overall_percentage_str, file, file_percentage);
332 } else {
333 Printf("[%4s] %s", overall_percentage_str, file);
334 }
335 }
336 }
337
Printf(const char * fmt,...)338 void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
339 std::string s;
340
341 va_list ap;
342 va_start(ap, fmt);
343 android::base::StringAppendV(&s, fmt, ap);
344 va_end(ap);
345
346 line_printer_.Print(s, LinePrinter::INFO);
347 }
348
Error(const char * fmt,...)349 void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
350 std::string s = "adb: error: ";
351
352 va_list ap;
353 va_start(ap, fmt);
354 android::base::StringAppendV(&s, fmt, ap);
355 va_end(ap);
356
357 line_printer_.Print(s, LinePrinter::ERROR);
358 }
359
Warning(const char * fmt,...)360 void Warning(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
361 std::string s = "adb: warning: ";
362
363 va_list ap;
364 va_start(ap, fmt);
365 android::base::StringAppendV(&s, fmt, ap);
366 va_end(ap);
367
368 line_printer_.Print(s, LinePrinter::WARNING);
369 }
370
ComputeExpectedTotalBytes(const std::vector<copyinfo> & file_list)371 void ComputeExpectedTotalBytes(const std::vector<copyinfo>& file_list) {
372 expected_total_bytes_ = 0;
373 for (const copyinfo& ci : file_list) {
374 // Unfortunately, this doesn't work for symbolic links, because we'll copy the
375 // target of the link rather than just creating a link. (But ci.size is the link size.)
376 if (!ci.skip) expected_total_bytes_ += ci.size;
377 }
378 expect_multiple_files_ = true;
379 }
380
SetExpectedTotalBytes(uint64_t expected_total_bytes)381 void SetExpectedTotalBytes(uint64_t expected_total_bytes) {
382 expected_total_bytes_ = expected_total_bytes;
383 expect_multiple_files_ = false;
384 }
385
386 uint64_t total_bytes_;
387
388 // TODO: add a char[max] buffer here, to replace syncsendbuf...
389 int fd;
390 size_t max;
391
392 private:
393 uint64_t start_time_ms_;
394
395 uint64_t expected_total_bytes_;
396 bool expect_multiple_files_;
397 bool expect_done_;
398
399 LinePrinter line_printer_;
400
SendQuit()401 bool SendQuit() {
402 return SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
403 }
404
WriteOrDie(const char * from,const char * to,const void * data,size_t data_length)405 bool WriteOrDie(const char* from, const char* to, const void* data, size_t data_length) {
406 if (!WriteFdExactly(fd, data, data_length)) {
407 if (errno == ECONNRESET) {
408 // Assume adbd told us why it was closing the connection, and
409 // try to read failure reason from adbd.
410 syncmsg msg;
411 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
412 Error("failed to copy '%s' to '%s': no response: %s", from, to, strerror(errno));
413 } else if (msg.status.id != ID_FAIL) {
414 Error("failed to copy '%s' to '%s': not ID_FAIL: %d", from, to, msg.status.id);
415 } else {
416 ReportCopyFailure(from, to, msg);
417 }
418 } else {
419 Error("%zu-byte write failed: %s", data_length, strerror(errno));
420 }
421 _exit(1);
422 }
423 return true;
424 }
425
CurrentTimeMs()426 static uint64_t CurrentTimeMs() {
427 struct timeval tv;
428 gettimeofday(&tv, 0); // (Not clock_gettime because of Mac/Windows.)
429 return static_cast<uint64_t>(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
430 }
431 };
432
433 typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
434
sync_ls(SyncConnection & sc,const char * path,std::function<sync_ls_cb> func)435 static bool sync_ls(SyncConnection& sc, const char* path,
436 std::function<sync_ls_cb> func) {
437 if (!sc.SendRequest(ID_LIST, path)) return false;
438
439 while (true) {
440 syncmsg msg;
441 if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false;
442
443 if (msg.dent.id == ID_DONE) return true;
444 if (msg.dent.id != ID_DENT) return false;
445
446 size_t len = msg.dent.namelen;
447 if (len > 256) return false; // TODO: resize buffer? continue?
448
449 char buf[257];
450 if (!ReadFdExactly(sc.fd, buf, len)) return false;
451 buf[len] = 0;
452
453 func(msg.dent.mode, msg.dent.size, msg.dent.time, buf);
454 }
455 }
456
sync_finish_stat(SyncConnection & sc,unsigned int * timestamp,unsigned int * mode,unsigned int * size)457 static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
458 unsigned int* mode, unsigned int* size) {
459 syncmsg msg;
460 if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) {
461 return false;
462 }
463
464 if (timestamp) *timestamp = msg.stat.time;
465 if (mode) *mode = msg.stat.mode;
466 if (size) *size = msg.stat.size;
467
468 return true;
469 }
470
sync_stat(SyncConnection & sc,const char * path,unsigned int * timestamp,unsigned int * mode,unsigned int * size)471 static bool sync_stat(SyncConnection& sc, const char* path,
472 unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
473 return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
474 }
475
sync_send(SyncConnection & sc,const char * lpath,const char * rpath,unsigned mtime,mode_t mode)476 static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
477 unsigned mtime, mode_t mode)
478 {
479 std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
480
481 if (S_ISLNK(mode)) {
482 #if !defined(_WIN32)
483 char buf[PATH_MAX];
484 ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
485 if (data_length == -1) {
486 sc.Error("readlink '%s' failed: %s", lpath, strerror(errno));
487 return false;
488 }
489 buf[data_length++] = '\0';
490
491 if (!sc.SendSmallFile(path_and_mode.c_str(), lpath, rpath, mtime, buf, data_length)) {
492 return false;
493 }
494 return sc.CopyDone(lpath, rpath);
495 #endif
496 }
497
498 struct stat st;
499 if (stat(lpath, &st) == -1) {
500 sc.Error("failed to stat local file '%s': %s", lpath, strerror(errno));
501 return false;
502 }
503 if (st.st_size < SYNC_DATA_MAX) {
504 std::string data;
505 if (!android::base::ReadFileToString(lpath, &data)) {
506 sc.Error("failed to read all of '%s': %s", lpath, strerror(errno));
507 return false;
508 }
509 if (!sc.SendSmallFile(path_and_mode.c_str(), lpath, rpath, mtime,
510 data.data(), data.size())) {
511 return false;
512 }
513 } else {
514 if (!sc.SendLargeFile(path_and_mode.c_str(), lpath, rpath, mtime)) {
515 return false;
516 }
517 }
518 return sc.CopyDone(lpath, rpath);
519 }
520
sync_recv(SyncConnection & sc,const char * rpath,const char * lpath,const char * name=nullptr)521 static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
522 const char* name=nullptr) {
523 unsigned size = 0;
524 if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
525
526 if (!sc.SendRequest(ID_RECV, rpath)) return false;
527
528 adb_unlink(lpath);
529 int lfd = adb_creat(lpath, 0644);
530 if (lfd < 0) {
531 sc.Error("cannot create '%s': %s", lpath, strerror(errno));
532 return false;
533 }
534
535 uint64_t bytes_copied = 0;
536 while (true) {
537 syncmsg msg;
538 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
539 adb_close(lfd);
540 adb_unlink(lpath);
541 return false;
542 }
543
544 if (msg.data.id == ID_DONE) break;
545
546 if (msg.data.id != ID_DATA) {
547 adb_close(lfd);
548 adb_unlink(lpath);
549 sc.ReportCopyFailure(rpath, lpath, msg);
550 return false;
551 }
552
553 if (msg.data.size > sc.max) {
554 sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
555 adb_close(lfd);
556 adb_unlink(lpath);
557 return false;
558 }
559
560 char buffer[SYNC_DATA_MAX];
561 if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
562 adb_close(lfd);
563 adb_unlink(lpath);
564 return false;
565 }
566
567 if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
568 sc.Error("cannot write '%s': %s", lpath, strerror(errno));
569 adb_close(lfd);
570 adb_unlink(lpath);
571 return false;
572 }
573
574 sc.total_bytes_ += msg.data.size;
575
576 bytes_copied += msg.data.size;
577
578 sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, size);
579 }
580
581 adb_close(lfd);
582 return true;
583 }
584
do_sync_ls(const char * path)585 bool do_sync_ls(const char* path) {
586 SyncConnection sc;
587 if (!sc.IsValid()) return false;
588
589 return sync_ls(sc, path, [](unsigned mode, unsigned size, unsigned time,
590 const char* name) {
591 printf("%08x %08x %08x %s\n", mode, size, time, name);
592 });
593 }
594
IsDotOrDotDot(const char * name)595 static bool IsDotOrDotDot(const char* name) {
596 return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
597 }
598
local_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,const std::string & lpath,const std::string & rpath)599 static bool local_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
600 const std::string& lpath,
601 const std::string& rpath) {
602 std::vector<copyinfo> dirlist;
603 std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(lpath.c_str()), closedir);
604 if (!dir) {
605 sc.Error("cannot open '%s': %s", lpath.c_str(), strerror(errno));
606 return false;
607 }
608
609 bool empty_dir = true;
610 dirent* de;
611 while ((de = readdir(dir.get()))) {
612 if (IsDotOrDotDot(de->d_name)) {
613 continue;
614 }
615
616 empty_dir = false;
617 std::string stat_path = lpath + de->d_name;
618
619 struct stat st;
620 if (lstat(stat_path.c_str(), &st) == -1) {
621 sc.Error("cannot lstat '%s': %s", stat_path.c_str(),
622 strerror(errno));
623 continue;
624 }
625
626 copyinfo ci(lpath, rpath, de->d_name, st.st_mode);
627 if (S_ISDIR(st.st_mode)) {
628 dirlist.push_back(ci);
629 } else {
630 if (!should_push_file(st.st_mode)) {
631 sc.Warning("skipping special file '%s' (mode = 0o%o)", lpath.c_str(), st.st_mode);
632 ci.skip = true;
633 }
634 ci.time = st.st_mtime;
635 ci.size = st.st_size;
636 file_list->push_back(ci);
637 }
638 }
639
640 // Close this directory and recurse.
641 dir.reset();
642
643 // Add the current directory to the list if it was empty, to ensure that
644 // it gets created.
645 if (empty_dir) {
646 // TODO(b/25566053): Make pushing empty directories work.
647 // TODO(b/25457350): We don't preserve permissions on directories.
648 sc.Warning("skipping empty directory '%s'", lpath.c_str());
649 copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(lpath), S_IFDIR);
650 ci.skip = true;
651 file_list->push_back(ci);
652 return true;
653 }
654
655 for (const copyinfo& ci : dirlist) {
656 local_build_list(sc, file_list, ci.lpath, ci.rpath);
657 }
658
659 return true;
660 }
661
copy_local_dir_remote(SyncConnection & sc,std::string lpath,std::string rpath,bool check_timestamps,bool list_only)662 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
663 std::string rpath, bool check_timestamps,
664 bool list_only) {
665 // Make sure that both directory paths end in a slash.
666 // Both paths are known to be nonempty, so we don't need to check.
667 ensure_trailing_separators(lpath, rpath);
668
669 // Recursively build the list of files to copy.
670 std::vector<copyinfo> file_list;
671 int pushed = 0;
672 int skipped = 0;
673 if (!local_build_list(sc, &file_list, lpath, rpath)) {
674 return false;
675 }
676
677 if (check_timestamps) {
678 for (const copyinfo& ci : file_list) {
679 if (!sc.SendRequest(ID_STAT, ci.rpath.c_str())) {
680 return false;
681 }
682 }
683 for (copyinfo& ci : file_list) {
684 unsigned int timestamp, mode, size;
685 if (!sync_finish_stat(sc, ×tamp, &mode, &size)) {
686 return false;
687 }
688 if (size == ci.size) {
689 // For links, we cannot update the atime/mtime.
690 if ((S_ISREG(ci.mode & mode) && timestamp == ci.time) ||
691 (S_ISLNK(ci.mode & mode) && timestamp >= ci.time)) {
692 ci.skip = true;
693 }
694 }
695 }
696 }
697
698 sc.ComputeExpectedTotalBytes(file_list);
699
700 for (const copyinfo& ci : file_list) {
701 if (!ci.skip) {
702 if (list_only) {
703 sc.Error("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
704 } else {
705 if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
706 return false;
707 }
708 }
709 pushed++;
710 } else {
711 skipped++;
712 }
713 }
714
715 sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(),
716 pushed, (pushed == 1) ? "" : "s", skipped,
717 (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
718 return true;
719 }
720
do_sync_push(const std::vector<const char * > & srcs,const char * dst)721 bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
722 SyncConnection sc;
723 if (!sc.IsValid()) return false;
724
725 bool success = true;
726 unsigned dst_mode;
727 if (!sync_stat(sc, dst, nullptr, &dst_mode, nullptr)) return false;
728 bool dst_exists = (dst_mode != 0);
729 bool dst_isdir = S_ISDIR(dst_mode);
730
731 if (!dst_isdir) {
732 if (srcs.size() > 1) {
733 sc.Error("target '%s' is not a directory", dst);
734 return false;
735 } else {
736 size_t dst_len = strlen(dst);
737
738 // A path that ends with a slash doesn't have to be a directory if
739 // it doesn't exist yet.
740 if (dst[dst_len - 1] == '/' && dst_exists) {
741 sc.Error("failed to access '%s': Not a directory", dst);
742 return false;
743 }
744 }
745 }
746
747 for (const char* src_path : srcs) {
748 const char* dst_path = dst;
749 struct stat st;
750 if (stat(src_path, &st) == -1) {
751 sc.Error("cannot stat '%s': %s", src_path, strerror(errno));
752 success = false;
753 continue;
754 }
755
756 if (S_ISDIR(st.st_mode)) {
757 std::string dst_dir = dst;
758
759 // If the destination path existed originally, the source directory
760 // should be copied as a child of the destination.
761 if (dst_exists) {
762 if (!dst_isdir) {
763 sc.Error("target '%s' is not a directory", dst);
764 return false;
765 }
766 // dst is a POSIX path, so we don't want to use the sysdeps
767 // helpers here.
768 if (dst_dir.back() != '/') {
769 dst_dir.push_back('/');
770 }
771 dst_dir.append(adb_basename(src_path));
772 }
773
774 success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(),
775 false, false);
776 continue;
777 } else if (!should_push_file(st.st_mode)) {
778 sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
779 continue;
780 }
781
782 std::string path_holder;
783 if (dst_isdir) {
784 // If we're copying a local file to a remote directory,
785 // we really want to copy to remote_dir + "/" + local_filename.
786 path_holder = dst_path;
787 if (path_holder.back() != '/') {
788 path_holder.push_back('/');
789 }
790 path_holder += adb_basename(src_path);
791 dst_path = path_holder.c_str();
792 }
793 sc.SetExpectedTotalBytes(st.st_size);
794 success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
795 }
796
797 return success;
798 }
799
remote_symlink_isdir(SyncConnection & sc,const std::string & rpath)800 static bool remote_symlink_isdir(SyncConnection& sc, const std::string& rpath) {
801 unsigned mode;
802 std::string dir_path = rpath;
803 dir_path.push_back('/');
804 if (!sync_stat(sc, dir_path.c_str(), nullptr, &mode, nullptr)) {
805 sc.Error("failed to stat remote symlink '%s'", dir_path.c_str());
806 return false;
807 }
808 return S_ISDIR(mode);
809 }
810
remote_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,const std::string & rpath,const std::string & lpath)811 static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
812 const std::string& rpath, const std::string& lpath) {
813 std::vector<copyinfo> dirlist;
814 std::vector<copyinfo> linklist;
815
816 // Add an entry for the current directory to ensure it gets created before pulling its contents.
817 copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(lpath), S_IFDIR);
818 file_list->push_back(ci);
819
820 // Put the files/dirs in rpath on the lists.
821 auto callback = [&](unsigned mode, unsigned size, unsigned time, const char* name) {
822 if (IsDotOrDotDot(name)) {
823 return;
824 }
825
826 copyinfo ci(lpath, rpath, name, mode);
827 if (S_ISDIR(mode)) {
828 dirlist.push_back(ci);
829 } else if (S_ISLNK(mode)) {
830 linklist.push_back(ci);
831 } else {
832 if (!should_pull_file(ci.mode)) {
833 sc.Warning("skipping special file '%s' (mode = 0o%o)", ci.rpath.c_str(), ci.mode);
834 ci.skip = true;
835 }
836 ci.time = time;
837 ci.size = size;
838 file_list->push_back(ci);
839 }
840 };
841
842 if (!sync_ls(sc, rpath.c_str(), callback)) {
843 return false;
844 }
845
846 // Check each symlink we found to see whether it's a file or directory.
847 for (copyinfo& link_ci : linklist) {
848 if (remote_symlink_isdir(sc, link_ci.rpath)) {
849 dirlist.emplace_back(std::move(link_ci));
850 } else {
851 file_list->emplace_back(std::move(link_ci));
852 }
853 }
854
855 // Recurse into each directory we found.
856 while (!dirlist.empty()) {
857 copyinfo current = dirlist.back();
858 dirlist.pop_back();
859 if (!remote_build_list(sc, file_list, current.rpath, current.lpath)) {
860 return false;
861 }
862 }
863
864 return true;
865 }
866
set_time_and_mode(const std::string & lpath,time_t time,unsigned int mode)867 static int set_time_and_mode(const std::string& lpath, time_t time,
868 unsigned int mode) {
869 struct utimbuf times = { time, time };
870 int r1 = utime(lpath.c_str(), ×);
871
872 /* use umask for permissions */
873 mode_t mask = umask(0000);
874 umask(mask);
875 int r2 = chmod(lpath.c_str(), mode & ~mask);
876
877 return r1 ? r1 : r2;
878 }
879
copy_remote_dir_local(SyncConnection & sc,std::string rpath,std::string lpath,bool copy_attrs)880 static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath,
881 std::string lpath, bool copy_attrs) {
882 // Make sure that both directory paths end in a slash.
883 // Both paths are known to be nonempty, so we don't need to check.
884 ensure_trailing_separators(lpath, rpath);
885
886 // Recursively build the list of files to copy.
887 sc.Printf("pull: building file list...");
888 std::vector<copyinfo> file_list;
889 if (!remote_build_list(sc, &file_list, rpath.c_str(), lpath.c_str())) {
890 return false;
891 }
892
893 sc.ComputeExpectedTotalBytes(file_list);
894
895 int pulled = 0;
896 int skipped = 0;
897 for (const copyinfo &ci : file_list) {
898 if (!ci.skip) {
899 if (S_ISDIR(ci.mode)) {
900 // Entry is for an empty directory, create it and continue.
901 // TODO(b/25457350): We don't preserve permissions on directories.
902 if (!mkdirs(ci.lpath)) {
903 sc.Error("failed to create directory '%s': %s",
904 ci.lpath.c_str(), strerror(errno));
905 return false;
906 }
907 pulled++;
908 continue;
909 }
910
911 if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str())) {
912 return false;
913 }
914
915 if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
916 return false;
917 }
918 pulled++;
919 } else {
920 skipped++;
921 }
922 }
923
924 sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(),
925 pulled, (pulled == 1) ? "" : "s", skipped,
926 (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
927 return true;
928 }
929
do_sync_pull(const std::vector<const char * > & srcs,const char * dst,bool copy_attrs,const char * name)930 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
931 bool copy_attrs, const char* name) {
932 SyncConnection sc;
933 if (!sc.IsValid()) return false;
934
935 bool success = true;
936 struct stat st;
937 bool dst_exists = true;
938
939 if (stat(dst, &st) == -1) {
940 dst_exists = false;
941
942 // If we're only pulling one path, the destination path might point to
943 // a path that doesn't exist yet.
944 if (srcs.size() == 1 && errno == ENOENT) {
945 // However, its parent must exist.
946 struct stat parent_st;
947 if (stat(adb_dirname(dst).c_str(), &parent_st) == -1) {
948 sc.Error("cannot create file/directory '%s': %s", dst, strerror(errno));
949 return false;
950 }
951 } else {
952 sc.Error("failed to access '%s': %s", dst, strerror(errno));
953 return false;
954 }
955 }
956
957 bool dst_isdir = dst_exists && S_ISDIR(st.st_mode);
958 if (!dst_isdir) {
959 if (srcs.size() > 1) {
960 sc.Error("target '%s' is not a directory", dst);
961 return false;
962 } else {
963 size_t dst_len = strlen(dst);
964
965 // A path that ends with a slash doesn't have to be a directory if
966 // it doesn't exist yet.
967 if (adb_is_separator(dst[dst_len - 1]) && dst_exists) {
968 sc.Error("failed to access '%s': Not a directory", dst);
969 return false;
970 }
971 }
972 }
973
974 for (const char* src_path : srcs) {
975 const char* dst_path = dst;
976 unsigned src_mode, src_time, src_size;
977 if (!sync_stat(sc, src_path, &src_time, &src_mode, &src_size)) {
978 sc.Error("failed to stat remote object '%s'", src_path);
979 return false;
980 }
981 if (src_mode == 0) {
982 sc.Error("remote object '%s' does not exist", src_path);
983 success = false;
984 continue;
985 }
986
987 bool src_isdir = S_ISDIR(src_mode);
988 if (S_ISLNK(src_mode)) {
989 src_isdir = remote_symlink_isdir(sc, src_path);
990 }
991
992 if (src_isdir) {
993 std::string dst_dir = dst;
994
995 // If the destination path existed originally, the source directory
996 // should be copied as a child of the destination.
997 if (dst_exists) {
998 if (!dst_isdir) {
999 sc.Error("target '%s' is not a directory", dst);
1000 return false;
1001 }
1002 if (!adb_is_separator(dst_dir.back())) {
1003 dst_dir.push_back(OS_PATH_SEPARATOR);
1004 }
1005 dst_dir.append(adb_basename(src_path));
1006 }
1007
1008 success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(), copy_attrs);
1009 continue;
1010 } else if (!should_pull_file(src_mode)) {
1011 sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_mode);
1012 continue;
1013 }
1014
1015 std::string path_holder;
1016 if (dst_isdir) {
1017 // If we're copying a remote file to a local directory, we
1018 // really want to copy to local_dir + OS_PATH_SEPARATOR +
1019 // basename(remote).
1020 path_holder = android::base::StringPrintf("%s%c%s", dst_path, OS_PATH_SEPARATOR,
1021 adb_basename(src_path).c_str());
1022 dst_path = path_holder.c_str();
1023 }
1024
1025 sc.SetExpectedTotalBytes(src_size);
1026 if (!sync_recv(sc, src_path, dst_path, name)) {
1027 success = false;
1028 continue;
1029 }
1030
1031 if (copy_attrs && set_time_and_mode(dst_path, src_time, src_mode) != 0) {
1032 success = false;
1033 continue;
1034 }
1035 }
1036
1037 return success;
1038 }
1039
do_sync_sync(const std::string & lpath,const std::string & rpath,bool list_only)1040 bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
1041 SyncConnection sc;
1042 if (!sc.IsValid()) return false;
1043
1044 return copy_local_dir_remote(sc, lpath, rpath, true, list_only);
1045 }
1046