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 "client/file_sync_client.h"
18
19 #include <dirent.h>
20 #include <inttypes.h>
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.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 <chrono>
32 #include <deque>
33 #include <functional>
34 #include <memory>
35 #include <sstream>
36 #include <string>
37 #include <vector>
38
39 #include "sysdeps.h"
40
41 #include "adb.h"
42 #include "adb_client.h"
43 #include "adb_io.h"
44 #include "adb_utils.h"
45 #include "brotli_utils.h"
46 #include "file_sync_protocol.h"
47 #include "line_printer.h"
48 #include "sysdeps/errno.h"
49 #include "sysdeps/stat.h"
50
51 #include "client/commandline.h"
52
53 #include <android-base/file.h>
54 #include <android-base/strings.h>
55 #include <android-base/stringprintf.h>
56
57 using namespace std::literals;
58
59 typedef void(sync_ls_cb)(unsigned mode, uint64_t size, uint64_t time, const char* name);
60
61 struct syncsendbuf {
62 unsigned id;
63 unsigned size;
64 char data[SYNC_DATA_MAX];
65 };
66
ensure_trailing_separators(std::string & local_path,std::string & remote_path)67 static void ensure_trailing_separators(std::string& local_path, std::string& remote_path) {
68 if (!adb_is_separator(local_path.back())) {
69 local_path.push_back(OS_PATH_SEPARATOR);
70 }
71 if (remote_path.back() != '/') {
72 remote_path.push_back('/');
73 }
74 }
75
should_pull_file(mode_t mode)76 static bool should_pull_file(mode_t mode) {
77 return S_ISREG(mode) || S_ISBLK(mode) || S_ISCHR(mode);
78 }
79
should_push_file(mode_t mode)80 static bool should_push_file(mode_t mode) {
81 return S_ISREG(mode) || S_ISLNK(mode);
82 }
83
84 struct copyinfo {
85 std::string lpath;
86 std::string rpath;
87 int64_t time = 0;
88 uint32_t mode;
89 uint64_t size = 0;
90 bool skip = false;
91
copyinfocopyinfo92 copyinfo(const std::string& local_path,
93 const std::string& remote_path,
94 const std::string& name,
95 unsigned int mode)
96 : lpath(local_path), rpath(remote_path), mode(mode) {
97 ensure_trailing_separators(lpath, rpath);
98 lpath.append(name);
99 rpath.append(name);
100 if (S_ISDIR(mode)) {
101 ensure_trailing_separators(lpath, rpath);
102 }
103 }
104 };
105
106 enum class TransferDirection {
107 push,
108 pull,
109 };
110
111 struct TransferLedger {
112 std::chrono::steady_clock::time_point start_time;
113 uint64_t files_transferred;
114 uint64_t files_skipped;
115 uint64_t bytes_transferred;
116 uint64_t bytes_expected;
117 bool expect_multiple_files;
118
119 private:
120 std::string last_progress_str;
121 std::chrono::steady_clock::time_point last_progress_time;
122
123 public:
TransferLedgerTransferLedger124 TransferLedger() {
125 Reset();
126 }
127
operator ==TransferLedger128 bool operator==(const TransferLedger& other) const {
129 return files_transferred == other.files_transferred &&
130 files_skipped == other.files_skipped && bytes_transferred == other.bytes_transferred;
131 }
132
operator !=TransferLedger133 bool operator!=(const TransferLedger& other) const {
134 return !(*this == other);
135 }
136
ResetTransferLedger137 void Reset() {
138 start_time = std::chrono::steady_clock::now();
139 files_transferred = 0;
140 files_skipped = 0;
141 bytes_transferred = 0;
142 bytes_expected = 0;
143 last_progress_str.clear();
144 last_progress_time = {};
145 }
146
TransferRateTransferLedger147 std::string TransferRate() {
148 if (bytes_transferred == 0) return "";
149
150 std::chrono::duration<double> duration;
151 duration = std::chrono::steady_clock::now() - start_time;
152
153 double s = duration.count();
154 if (s == 0) {
155 return "";
156 }
157 double rate = (static_cast<double>(bytes_transferred) / s) / (1024 * 1024);
158 return android::base::StringPrintf(" %.1f MB/s (%" PRIu64 " bytes in %.3fs)", rate,
159 bytes_transferred, s);
160 }
161
ReportProgressTransferLedger162 void ReportProgress(LinePrinter& lp, const std::string& file, uint64_t file_copied_bytes,
163 uint64_t file_total_bytes) {
164 static constexpr auto kProgressReportInterval = 100ms;
165
166 auto now = std::chrono::steady_clock::now();
167 if (now < last_progress_time + kProgressReportInterval) {
168 return;
169 }
170 char overall_percentage_str[5] = "?";
171 if (bytes_expected != 0 && bytes_transferred <= bytes_expected) {
172 int overall_percentage = static_cast<int>(bytes_transferred * 100 / bytes_expected);
173 // If we're pulling symbolic links, we'll pull the target of the link rather than
174 // just create a local link, and that will cause us to go over 100%.
175 if (overall_percentage <= 100) {
176 snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
177 overall_percentage);
178 }
179 }
180
181 std::string output;
182 if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
183 // This case can happen if we're racing against something that wrote to the file
184 // between our stat and our read, or if we're reading a magic file that lies about
185 // its size. Just show how much we've copied.
186 output = android::base::StringPrintf("[%4s] %s: %" PRId64 "/?", overall_percentage_str,
187 file.c_str(), file_copied_bytes);
188 } else {
189 // If we're transferring multiple files, we want to know how far through the current
190 // file we are, as well as the overall percentage.
191 if (expect_multiple_files) {
192 int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
193 output = android::base::StringPrintf("[%4s] %s: %d%%", overall_percentage_str,
194 file.c_str(), file_percentage);
195 } else {
196 output =
197 android::base::StringPrintf("[%4s] %s", overall_percentage_str, file.c_str());
198 }
199 }
200 if (output != last_progress_str) {
201 lp.Print(output, LinePrinter::LineType::INFO);
202 last_progress_str = std::move(output);
203 last_progress_time = now;
204 }
205 }
206
ReportTransferRateTransferLedger207 void ReportTransferRate(LinePrinter& lp, const std::string& name, TransferDirection direction) {
208 const char* direction_str = (direction == TransferDirection::push) ? "pushed" : "pulled";
209 std::stringstream ss;
210 if (!name.empty()) {
211 std::string_view display_name(name);
212 char* out = getenv("ANDROID_PRODUCT_OUT");
213 if (out) android::base::ConsumePrefix(&display_name, out);
214 ss << display_name << ": ";
215 }
216 ss << files_transferred << " file" << ((files_transferred == 1) ? "" : "s") << " "
217 << direction_str << ", " << files_skipped << " skipped.";
218 ss << TransferRate();
219
220 lp.Print(ss.str(), LinePrinter::LineType::INFO);
221 lp.KeepInfoLine();
222 }
223 };
224
225 class SyncConnection {
226 public:
SyncConnection()227 SyncConnection() : acknowledgement_buffer_(sizeof(sync_status) + SYNC_DATA_MAX) {
228 acknowledgement_buffer_.resize(0);
229 max = SYNC_DATA_MAX; // TODO: decide at runtime.
230
231 std::string error;
232 if (!adb_get_feature_set(&features_, &error)) {
233 Error("failed to get feature set: %s", error.c_str());
234 } else {
235 have_stat_v2_ = CanUseFeature(features_, kFeatureStat2);
236 have_ls_v2_ = CanUseFeature(features_, kFeatureLs2);
237 have_sendrecv_v2_ = CanUseFeature(features_, kFeatureSendRecv2);
238 have_sendrecv_v2_brotli_ = CanUseFeature(features_, kFeatureSendRecv2Brotli);
239 fd.reset(adb_connect("sync:", &error));
240 if (fd < 0) {
241 Error("connect failed: %s", error.c_str());
242 }
243 }
244 }
245
~SyncConnection()246 ~SyncConnection() {
247 if (!IsValid()) return;
248
249 if (SendQuit()) {
250 // We sent a quit command, so the server should be doing orderly
251 // shutdown soon. But if we encountered an error while we were using
252 // the connection, the server might still be sending data (before
253 // doing orderly shutdown), in which case we won't wait for all of
254 // the data nor the coming orderly shutdown. In the common success
255 // case, this will wait for the server to do orderly shutdown.
256 ReadOrderlyShutdown(fd);
257 }
258
259 line_printer_.KeepInfoLine();
260 }
261
HaveSendRecv2() const262 bool HaveSendRecv2() const { return have_sendrecv_v2_; }
HaveSendRecv2Brotli() const263 bool HaveSendRecv2Brotli() const { return have_sendrecv_v2_brotli_; }
264
Features() const265 const FeatureSet& Features() const { return features_; }
266
IsValid()267 bool IsValid() { return fd >= 0; }
268
NewTransfer()269 void NewTransfer() {
270 current_ledger_.Reset();
271 }
272
RecordBytesTransferred(size_t bytes)273 void RecordBytesTransferred(size_t bytes) {
274 current_ledger_.bytes_transferred += bytes;
275 global_ledger_.bytes_transferred += bytes;
276 }
277
RecordFileSent(std::string from,std::string to)278 void RecordFileSent(std::string from, std::string to) {
279 RecordFilesTransferred(1);
280 deferred_acknowledgements_.emplace_back(std::move(from), std::move(to));
281 }
282
RecordFilesTransferred(size_t files)283 void RecordFilesTransferred(size_t files) {
284 current_ledger_.files_transferred += files;
285 global_ledger_.files_transferred += files;
286 }
287
RecordFilesSkipped(size_t files)288 void RecordFilesSkipped(size_t files) {
289 current_ledger_.files_skipped += files;
290 global_ledger_.files_skipped += files;
291 }
292
ReportProgress(const std::string & file,uint64_t file_copied_bytes,uint64_t file_total_bytes)293 void ReportProgress(const std::string& file, uint64_t file_copied_bytes,
294 uint64_t file_total_bytes) {
295 current_ledger_.ReportProgress(line_printer_, file, file_copied_bytes, file_total_bytes);
296 }
297
ReportTransferRate(const std::string & file,TransferDirection direction)298 void ReportTransferRate(const std::string& file, TransferDirection direction) {
299 current_ledger_.ReportTransferRate(line_printer_, file, direction);
300 }
301
ReportOverallTransferRate(TransferDirection direction)302 void ReportOverallTransferRate(TransferDirection direction) {
303 if (current_ledger_ != global_ledger_) {
304 global_ledger_.ReportTransferRate(line_printer_, "", direction);
305 }
306 }
307
SendRequest(int id,const std::string & path)308 bool SendRequest(int id, const std::string& path) {
309 if (path.length() > 1024) {
310 Error("SendRequest failed: path too long: %zu", path.length());
311 errno = ENAMETOOLONG;
312 return false;
313 }
314
315 // Sending header and payload in a single write makes a noticeable
316 // difference to "adb sync" performance.
317 std::vector<char> buf(sizeof(SyncRequest) + path.length());
318 SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
319 req->id = id;
320 req->path_length = path.length();
321 char* data = reinterpret_cast<char*>(req + 1);
322 memcpy(data, path.data(), path.length());
323 return WriteFdExactly(fd, buf.data(), buf.size());
324 }
325
SendSend2(std::string_view path,mode_t mode,bool compressed)326 bool SendSend2(std::string_view path, mode_t mode, bool compressed) {
327 if (path.length() > 1024) {
328 Error("SendRequest failed: path too long: %zu", path.length());
329 errno = ENAMETOOLONG;
330 return false;
331 }
332
333 Block buf;
334
335 SyncRequest req;
336 req.id = ID_SEND_V2;
337 req.path_length = path.length();
338
339 syncmsg msg;
340 msg.send_v2_setup.id = ID_SEND_V2;
341 msg.send_v2_setup.mode = mode;
342 msg.send_v2_setup.flags = compressed ? kSyncFlagBrotli : kSyncFlagNone;
343
344 buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.send_v2_setup));
345
346 void* p = buf.data();
347
348 p = mempcpy(p, &req, sizeof(SyncRequest));
349 p = mempcpy(p, path.data(), path.length());
350 p = mempcpy(p, &msg.send_v2_setup, sizeof(msg.send_v2_setup));
351
352 return WriteFdExactly(fd, buf.data(), buf.size());
353 }
354
SendRecv2(const std::string & path)355 bool SendRecv2(const std::string& path) {
356 if (path.length() > 1024) {
357 Error("SendRequest failed: path too long: %zu", path.length());
358 errno = ENAMETOOLONG;
359 return false;
360 }
361
362 Block buf;
363
364 SyncRequest req;
365 req.id = ID_RECV_V2;
366 req.path_length = path.length();
367
368 syncmsg msg;
369 msg.recv_v2_setup.id = ID_RECV_V2;
370 msg.recv_v2_setup.flags = kSyncFlagBrotli;
371
372 buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.recv_v2_setup));
373
374 void* p = buf.data();
375
376 p = mempcpy(p, &req, sizeof(SyncRequest));
377 p = mempcpy(p, path.data(), path.length());
378 p = mempcpy(p, &msg.recv_v2_setup, sizeof(msg.recv_v2_setup));
379
380 return WriteFdExactly(fd, buf.data(), buf.size());
381 }
382
SendStat(const std::string & path)383 bool SendStat(const std::string& path) {
384 if (!have_stat_v2_) {
385 errno = ENOTSUP;
386 return false;
387 }
388 return SendRequest(ID_STAT_V2, path);
389 }
390
SendLstat(const std::string & path)391 bool SendLstat(const std::string& path) {
392 if (have_stat_v2_) {
393 return SendRequest(ID_LSTAT_V2, path);
394 } else {
395 return SendRequest(ID_LSTAT_V1, path);
396 }
397 }
398
FinishStat(struct stat * st)399 bool FinishStat(struct stat* st) {
400 syncmsg msg;
401
402 memset(st, 0, sizeof(*st));
403 if (have_stat_v2_) {
404 if (!ReadFdExactly(fd.get(), &msg.stat_v2, sizeof(msg.stat_v2))) {
405 PLOG(FATAL) << "protocol fault: failed to read stat response";
406 }
407
408 if (msg.stat_v2.id != ID_LSTAT_V2 && msg.stat_v2.id != ID_STAT_V2) {
409 PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
410 << msg.stat_v2.id;
411 }
412
413 if (msg.stat_v2.error != 0) {
414 errno = errno_from_wire(msg.stat_v2.error);
415 return false;
416 }
417
418 st->st_dev = msg.stat_v2.dev;
419 st->st_ino = msg.stat_v2.ino;
420 st->st_mode = msg.stat_v2.mode;
421 st->st_nlink = msg.stat_v2.nlink;
422 st->st_uid = msg.stat_v2.uid;
423 st->st_gid = msg.stat_v2.gid;
424 st->st_size = msg.stat_v2.size;
425 st->st_atime = msg.stat_v2.atime;
426 st->st_mtime = msg.stat_v2.mtime;
427 st->st_ctime = msg.stat_v2.ctime;
428 return true;
429 } else {
430 if (!ReadFdExactly(fd.get(), &msg.stat_v1, sizeof(msg.stat_v1))) {
431 PLOG(FATAL) << "protocol fault: failed to read stat response";
432 }
433
434 if (msg.stat_v1.id != ID_LSTAT_V1) {
435 LOG(FATAL) << "protocol fault: stat response has wrong message id: "
436 << msg.stat_v1.id;
437 }
438
439 if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.mtime == 0) {
440 // There's no way for us to know what the error was.
441 errno = ENOPROTOOPT;
442 return false;
443 }
444
445 st->st_mode = msg.stat_v1.mode;
446 st->st_size = msg.stat_v1.size;
447 st->st_ctime = msg.stat_v1.mtime;
448 st->st_mtime = msg.stat_v1.mtime;
449 }
450
451 return true;
452 }
453
SendLs(const std::string & path)454 bool SendLs(const std::string& path) {
455 return SendRequest(have_ls_v2_ ? ID_LIST_V2 : ID_LIST_V1, path);
456 }
457
458 private:
459 template <bool v2>
FinishLsImpl(borrowed_fd fd,const std::function<sync_ls_cb> & callback)460 static bool FinishLsImpl(borrowed_fd fd, const std::function<sync_ls_cb>& callback) {
461 using dent_type =
462 std::conditional_t<v2, decltype(syncmsg::dent_v2), decltype(syncmsg::dent_v1)>;
463
464 while (true) {
465 dent_type dent;
466 if (!ReadFdExactly(fd, &dent, sizeof(dent))) return false;
467
468 uint32_t expected_id = v2 ? ID_DENT_V2 : ID_DENT_V1;
469 if (dent.id == ID_DONE) return true;
470 if (dent.id != expected_id) return false;
471
472 // Maximum length of a file name excluding null terminator (NAME_MAX) on Linux is 255.
473 char buf[256];
474 size_t len = dent.namelen;
475 if (len > 255) return false;
476
477 if (!ReadFdExactly(fd, buf, len)) return false;
478 buf[len] = 0;
479
480 callback(dent.mode, dent.size, dent.mtime, buf);
481 }
482 }
483
484 public:
FinishLs(const std::function<sync_ls_cb> & callback)485 bool FinishLs(const std::function<sync_ls_cb>& callback) {
486 if (have_ls_v2_) {
487 return FinishLsImpl<true>(this->fd, callback);
488 } else {
489 return FinishLsImpl<false>(this->fd, callback);
490 }
491 }
492
493 // Sending header, payload, and footer in a single write makes a huge
494 // difference to "adb sync" performance.
SendSmallFile(const std::string & path,mode_t mode,const std::string & lpath,const std::string & rpath,unsigned mtime,const char * data,size_t data_length)495 bool SendSmallFile(const std::string& path, mode_t mode, const std::string& lpath,
496 const std::string& rpath, unsigned mtime, const char* data,
497 size_t data_length) {
498 std::string path_and_mode = android::base::StringPrintf("%s,%d", path.c_str(), mode);
499 if (path_and_mode.length() > 1024) {
500 Error("SendSmallFile failed: path too long: %zu", path_and_mode.length());
501 errno = ENAMETOOLONG;
502 return false;
503 }
504
505 std::vector<char> buf(sizeof(SyncRequest) + path_and_mode.length() + sizeof(SyncRequest) +
506 data_length + sizeof(SyncRequest));
507 char* p = &buf[0];
508
509 SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
510 req_send->id = ID_SEND_V1;
511 req_send->path_length = path_and_mode.length();
512 p += sizeof(SyncRequest);
513 memcpy(p, path_and_mode.data(), path_and_mode.size());
514 p += path_and_mode.length();
515
516 SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p);
517 req_data->id = ID_DATA;
518 req_data->path_length = data_length;
519 p += sizeof(SyncRequest);
520 memcpy(p, data, data_length);
521 p += data_length;
522
523 SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p);
524 req_done->id = ID_DONE;
525 req_done->path_length = mtime;
526 p += sizeof(SyncRequest);
527
528 WriteOrDie(lpath, rpath, &buf[0], (p - &buf[0]));
529
530 RecordFileSent(lpath, rpath);
531 RecordBytesTransferred(data_length);
532 ReportProgress(rpath, data_length, data_length);
533 return true;
534 }
535
SendLargeFileCompressed(const std::string & path,mode_t mode,const std::string & lpath,const std::string & rpath,unsigned mtime)536 bool SendLargeFileCompressed(const std::string& path, mode_t mode, const std::string& lpath,
537 const std::string& rpath, unsigned mtime) {
538 if (!SendSend2(path, mode, true)) {
539 Error("failed to send ID_SEND_V2 message '%s': %s", path.c_str(), strerror(errno));
540 return false;
541 }
542
543 struct stat st;
544 if (stat(lpath.c_str(), &st) == -1) {
545 Error("cannot stat '%s': %s", lpath.c_str(), strerror(errno));
546 return false;
547 }
548
549 uint64_t total_size = st.st_size;
550 uint64_t bytes_copied = 0;
551
552 unique_fd lfd(adb_open(lpath.c_str(), O_RDONLY | O_CLOEXEC));
553 if (lfd < 0) {
554 Error("opening '%s' locally failed: %s", lpath.c_str(), strerror(errno));
555 return false;
556 }
557
558 syncsendbuf sbuf;
559 sbuf.id = ID_DATA;
560
561 BrotliEncoder<SYNC_DATA_MAX> encoder;
562 bool sending = true;
563 while (sending) {
564 Block input(SYNC_DATA_MAX);
565 int r = adb_read(lfd.get(), input.data(), input.size());
566 if (r < 0) {
567 Error("reading '%s' locally failed: %s", lpath.c_str(), strerror(errno));
568 return false;
569 }
570
571 if (r == 0) {
572 encoder.Finish();
573 } else {
574 input.resize(r);
575 encoder.Append(std::move(input));
576 RecordBytesTransferred(r);
577 bytes_copied += r;
578 ReportProgress(rpath, bytes_copied, total_size);
579 }
580
581 while (true) {
582 Block output;
583 BrotliEncodeResult result = encoder.Encode(&output);
584 if (result == BrotliEncodeResult::Error) {
585 Error("compressing '%s' locally failed", lpath.c_str());
586 return false;
587 }
588
589 if (!output.empty()) {
590 sbuf.size = output.size();
591 memcpy(sbuf.data, output.data(), output.size());
592 WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + output.size());
593 }
594
595 if (result == BrotliEncodeResult::Done) {
596 sending = false;
597 break;
598 } else if (result == BrotliEncodeResult::NeedInput) {
599 break;
600 } else if (result == BrotliEncodeResult::MoreOutput) {
601 continue;
602 }
603 }
604 }
605
606 syncmsg msg;
607 msg.data.id = ID_DONE;
608 msg.data.size = mtime;
609 RecordFileSent(lpath, rpath);
610 return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
611 }
612
SendLargeFile(const std::string & path,mode_t mode,const std::string & lpath,const std::string & rpath,unsigned mtime,bool compressed)613 bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath,
614 const std::string& rpath, unsigned mtime, bool compressed) {
615 if (compressed && HaveSendRecv2Brotli()) {
616 return SendLargeFileCompressed(path, mode, lpath, rpath, mtime);
617 }
618
619 std::string path_and_mode = android::base::StringPrintf("%s,%d", path.c_str(), mode);
620 if (!SendRequest(ID_SEND_V1, path_and_mode)) {
621 Error("failed to send ID_SEND_V1 message '%s': %s", path_and_mode.c_str(),
622 strerror(errno));
623 return false;
624 }
625
626 struct stat st;
627 if (stat(lpath.c_str(), &st) == -1) {
628 Error("cannot stat '%s': %s", lpath.c_str(), strerror(errno));
629 return false;
630 }
631
632 uint64_t total_size = st.st_size;
633 uint64_t bytes_copied = 0;
634
635 unique_fd lfd(adb_open(lpath.c_str(), O_RDONLY | O_CLOEXEC));
636 if (lfd < 0) {
637 Error("opening '%s' locally failed: %s", lpath.c_str(), strerror(errno));
638 return false;
639 }
640
641 syncsendbuf sbuf;
642 sbuf.id = ID_DATA;
643
644 while (true) {
645 int bytes_read = adb_read(lfd, sbuf.data, max);
646 if (bytes_read == -1) {
647 Error("reading '%s' locally failed: %s", lpath.c_str(), strerror(errno));
648 return false;
649 } else if (bytes_read == 0) {
650 break;
651 }
652
653 sbuf.size = bytes_read;
654 WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + bytes_read);
655
656 RecordBytesTransferred(bytes_read);
657 bytes_copied += bytes_read;
658 ReportProgress(rpath, bytes_copied, total_size);
659 }
660
661 syncmsg msg;
662 msg.data.id = ID_DONE;
663 msg.data.size = mtime;
664 RecordFileSent(lpath, rpath);
665 return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
666 }
667
ReportCopyFailure(const std::string & from,const std::string & to,const syncmsg & msg)668 bool ReportCopyFailure(const std::string& from, const std::string& to, const syncmsg& msg) {
669 std::vector<char> buf(msg.status.msglen + 1);
670 if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
671 Error("failed to copy '%s' to '%s'; failed to read reason (!): %s", from.c_str(),
672 to.c_str(), strerror(errno));
673 return false;
674 }
675 buf[msg.status.msglen] = 0;
676 Error("failed to copy '%s' to '%s': remote %s", from.c_str(), to.c_str(), &buf[0]);
677 return false;
678 }
679
CopyDone()680 void CopyDone() { deferred_acknowledgements_.pop_front(); }
681
ReportDeferredCopyFailure(const std::string & msg)682 void ReportDeferredCopyFailure(const std::string& msg) {
683 auto& [from, to] = deferred_acknowledgements_.front();
684 Error("failed to copy '%s' to '%s': remote %s", from.c_str(), to.c_str(), msg.c_str());
685 deferred_acknowledgements_.pop_front();
686 }
687
ReadAcknowledgements(bool read_all=false)688 bool ReadAcknowledgements(bool read_all = false) {
689 // We need to read enough such that adbd's intermediate socket's write buffer can't be
690 // full. The default buffer on Linux is 212992 bytes, but there's 576 bytes of bookkeeping
691 // overhead per write. The worst case scenario is a continuous string of failures, since
692 // each logical packet is divided into two writes. If our packet size if conservatively 512
693 // bytes long, this leaves us with space for 128 responses.
694 constexpr size_t max_deferred_acks = 128;
695 auto& buf = acknowledgement_buffer_;
696 adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
697 while (!deferred_acknowledgements_.empty()) {
698 bool should_block = read_all || deferred_acknowledgements_.size() >= max_deferred_acks;
699
700 ssize_t rc = adb_poll(&pfd, 1, should_block ? -1 : 0);
701 if (rc == 0) {
702 CHECK(!should_block);
703 return true;
704 }
705
706 if (acknowledgement_buffer_.size() < sizeof(sync_status)) {
707 const ssize_t header_bytes_left = sizeof(sync_status) - buf.size();
708 ssize_t rc = adb_read(fd, buf.end(), header_bytes_left);
709 if (rc <= 0) {
710 Error("failed to read copy response");
711 return false;
712 }
713
714 buf.resize(buf.size() + rc);
715 if (rc != header_bytes_left) {
716 // Early exit if we run out of data in the socket.
717 return true;
718 }
719
720 if (!should_block) {
721 // We don't want to read again yet, because the socket might be empty.
722 continue;
723 }
724 }
725
726 auto* hdr = reinterpret_cast<sync_status*>(buf.data());
727 if (hdr->id == ID_OKAY) {
728 buf.resize(0);
729 if (hdr->msglen != 0) {
730 Error("received ID_OKAY with msg_len (%" PRIu32 " != 0", hdr->msglen);
731 return false;
732 }
733 CopyDone();
734 continue;
735 } else if (hdr->id != ID_FAIL) {
736 Error("unexpected response from daemon: id = %#" PRIx32, hdr->id);
737 return false;
738 } else if (hdr->msglen > SYNC_DATA_MAX) {
739 Error("too-long message length from daemon: msglen = %" PRIu32, hdr->msglen);
740 return false;
741 }
742
743 const ssize_t msg_bytes_left = hdr->msglen + sizeof(sync_status) - buf.size();
744 CHECK_GE(msg_bytes_left, 0);
745 if (msg_bytes_left > 0) {
746 ssize_t rc = adb_read(fd, buf.end(), msg_bytes_left);
747 if (rc <= 0) {
748 Error("failed to read copy failure message");
749 return false;
750 }
751
752 buf.resize(buf.size() + rc);
753 if (rc != msg_bytes_left) {
754 if (should_block) {
755 continue;
756 } else {
757 return true;
758 }
759 }
760
761 std::string msg(buf.begin() + sizeof(sync_status), buf.end());
762 ReportDeferredCopyFailure(msg);
763 buf.resize(0);
764 return false;
765 }
766 }
767
768 return true;
769 }
770
Printf(const char * fmt,...)771 void Printf(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
772 std::string s;
773
774 va_list ap;
775 va_start(ap, fmt);
776 android::base::StringAppendV(&s, fmt, ap);
777 va_end(ap);
778
779 line_printer_.Print(s, LinePrinter::INFO);
780 }
781
Println(const char * fmt,...)782 void Println(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
783 std::string s;
784
785 va_list ap;
786 va_start(ap, fmt);
787 android::base::StringAppendV(&s, fmt, ap);
788 va_end(ap);
789
790 line_printer_.Print(s, LinePrinter::INFO);
791 line_printer_.KeepInfoLine();
792 }
793
Error(const char * fmt,...)794 void Error(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
795 std::string s = "adb: error: ";
796
797 va_list ap;
798 va_start(ap, fmt);
799 android::base::StringAppendV(&s, fmt, ap);
800 va_end(ap);
801
802 line_printer_.Print(s, LinePrinter::ERROR);
803 }
804
Warning(const char * fmt,...)805 void Warning(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
806 std::string s = "adb: warning: ";
807
808 va_list ap;
809 va_start(ap, fmt);
810 android::base::StringAppendV(&s, fmt, ap);
811 va_end(ap);
812
813 line_printer_.Print(s, LinePrinter::WARNING);
814 }
815
ComputeExpectedTotalBytes(const std::vector<copyinfo> & file_list)816 void ComputeExpectedTotalBytes(const std::vector<copyinfo>& file_list) {
817 current_ledger_.bytes_expected = 0;
818 for (const copyinfo& ci : file_list) {
819 // Unfortunately, this doesn't work for symbolic links, because we'll copy the
820 // target of the link rather than just creating a link. (But ci.size is the link size.)
821 if (!ci.skip) current_ledger_.bytes_expected += ci.size;
822 }
823 current_ledger_.expect_multiple_files = true;
824 }
825
SetExpectedTotalBytes(uint64_t expected_total_bytes)826 void SetExpectedTotalBytes(uint64_t expected_total_bytes) {
827 current_ledger_.bytes_expected = expected_total_bytes;
828 current_ledger_.expect_multiple_files = false;
829 }
830
831 // TODO: add a char[max] buffer here, to replace syncsendbuf...
832 unique_fd fd;
833 size_t max;
834
835 private:
836 std::deque<std::pair<std::string, std::string>> deferred_acknowledgements_;
837 Block acknowledgement_buffer_;
838 FeatureSet features_;
839 bool have_stat_v2_;
840 bool have_ls_v2_;
841 bool have_sendrecv_v2_;
842 bool have_sendrecv_v2_brotli_;
843
844 TransferLedger global_ledger_;
845 TransferLedger current_ledger_;
846 LinePrinter line_printer_;
847
SendQuit()848 bool SendQuit() {
849 return SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
850 }
851
WriteOrDie(const std::string & from,const std::string & to,const void * data,size_t data_length)852 bool WriteOrDie(const std::string& from, const std::string& to, const void* data,
853 size_t data_length) {
854 if (!WriteFdExactly(fd, data, data_length)) {
855 if (errno == ECONNRESET) {
856 // Assume adbd told us why it was closing the connection, and
857 // try to read failure reason from adbd.
858 syncmsg msg;
859 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
860 Error("failed to copy '%s' to '%s': no response: %s", from.c_str(), to.c_str(),
861 strerror(errno));
862 } else if (msg.status.id != ID_FAIL) {
863 Error("failed to copy '%s' to '%s': not ID_FAIL: %d", from.c_str(), to.c_str(),
864 msg.status.id);
865 } else {
866 ReportCopyFailure(from, to, msg);
867 }
868 } else {
869 Error("%zu-byte write failed: %s", data_length, strerror(errno));
870 }
871 _exit(1);
872 }
873 return true;
874 }
875 };
876
sync_ls(SyncConnection & sc,const std::string & path,const std::function<sync_ls_cb> & func)877 static bool sync_ls(SyncConnection& sc, const std::string& path,
878 const std::function<sync_ls_cb>& func) {
879 return sc.SendLs(path) && sc.FinishLs(func);
880 }
881
sync_stat(SyncConnection & sc,const std::string & path,struct stat * st)882 static bool sync_stat(SyncConnection& sc, const std::string& path, struct stat* st) {
883 return sc.SendStat(path) && sc.FinishStat(st);
884 }
885
sync_lstat(SyncConnection & sc,const std::string & path,struct stat * st)886 static bool sync_lstat(SyncConnection& sc, const std::string& path, struct stat* st) {
887 return sc.SendLstat(path) && sc.FinishStat(st);
888 }
889
sync_stat_fallback(SyncConnection & sc,const std::string & path,struct stat * st)890 static bool sync_stat_fallback(SyncConnection& sc, const std::string& path, struct stat* st) {
891 if (sync_stat(sc, path, st)) {
892 return true;
893 }
894
895 if (errno != ENOTSUP) {
896 return false;
897 }
898
899 // Try to emulate the parts we can when talking to older adbds.
900 bool lstat_result = sync_lstat(sc, path, st);
901 if (!lstat_result) {
902 return false;
903 }
904
905 if (S_ISLNK(st->st_mode)) {
906 // If the target is a symlink, figure out whether it's a file or a directory.
907 // Also, zero out the st_size field, since no one actually cares what the path length is.
908 st->st_size = 0;
909 std::string dir_path = path;
910 dir_path.push_back('/');
911 struct stat tmp_st;
912
913 st->st_mode &= ~S_IFMT;
914 if (sync_lstat(sc, dir_path, &tmp_st)) {
915 st->st_mode |= S_IFDIR;
916 } else {
917 st->st_mode |= S_IFREG;
918 }
919 }
920 return true;
921 }
922
sync_send(SyncConnection & sc,const std::string & lpath,const std::string & rpath,unsigned mtime,mode_t mode,bool sync,bool compressed)923 static bool sync_send(SyncConnection& sc, const std::string& lpath, const std::string& rpath,
924 unsigned mtime, mode_t mode, bool sync, bool compressed) {
925 if (sync) {
926 struct stat st;
927 if (sync_lstat(sc, rpath, &st)) {
928 if (st.st_mtime == static_cast<time_t>(mtime)) {
929 sc.RecordFilesSkipped(1);
930 return true;
931 }
932 }
933 }
934
935 if (S_ISLNK(mode)) {
936 #if !defined(_WIN32)
937 char buf[PATH_MAX];
938 ssize_t data_length = readlink(lpath.c_str(), buf, PATH_MAX - 1);
939 if (data_length == -1) {
940 sc.Error("readlink '%s' failed: %s", lpath.c_str(), strerror(errno));
941 return false;
942 }
943 buf[data_length++] = '\0';
944
945 if (!sc.SendSmallFile(rpath, mode, lpath, rpath, mtime, buf, data_length)) {
946 return false;
947 }
948 return sc.ReadAcknowledgements();
949 #endif
950 }
951
952 struct stat st;
953 if (stat(lpath.c_str(), &st) == -1) {
954 sc.Error("failed to stat local file '%s': %s", lpath.c_str(), strerror(errno));
955 return false;
956 }
957 if (st.st_size < SYNC_DATA_MAX) {
958 std::string data;
959 if (!android::base::ReadFileToString(lpath, &data, true)) {
960 sc.Error("failed to read all of '%s': %s", lpath.c_str(), strerror(errno));
961 return false;
962 }
963 if (!sc.SendSmallFile(rpath, mode, lpath, rpath, mtime, data.data(), data.size())) {
964 return false;
965 }
966 } else {
967 if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compressed)) {
968 return false;
969 }
970 }
971 return sc.ReadAcknowledgements();
972 }
973
sync_recv_v1(SyncConnection & sc,const char * rpath,const char * lpath,const char * name,uint64_t expected_size)974 static bool sync_recv_v1(SyncConnection& sc, const char* rpath, const char* lpath, const char* name,
975 uint64_t expected_size) {
976 if (!sc.SendRequest(ID_RECV_V1, rpath)) return false;
977
978 adb_unlink(lpath);
979 unique_fd lfd(adb_creat(lpath, 0644));
980 if (lfd < 0) {
981 sc.Error("cannot create '%s': %s", lpath, strerror(errno));
982 return false;
983 }
984
985 uint64_t bytes_copied = 0;
986 while (true) {
987 syncmsg msg;
988 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
989 adb_unlink(lpath);
990 return false;
991 }
992
993 if (msg.data.id == ID_DONE) break;
994
995 if (msg.data.id != ID_DATA) {
996 adb_unlink(lpath);
997 sc.ReportCopyFailure(rpath, lpath, msg);
998 return false;
999 }
1000
1001 if (msg.data.size > sc.max) {
1002 sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
1003 adb_unlink(lpath);
1004 return false;
1005 }
1006
1007 char buffer[SYNC_DATA_MAX];
1008 if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
1009 adb_unlink(lpath);
1010 return false;
1011 }
1012
1013 if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
1014 sc.Error("cannot write '%s': %s", lpath, strerror(errno));
1015 adb_unlink(lpath);
1016 return false;
1017 }
1018
1019 bytes_copied += msg.data.size;
1020
1021 sc.RecordBytesTransferred(msg.data.size);
1022 sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, expected_size);
1023 }
1024
1025 sc.RecordFilesTransferred(1);
1026 return true;
1027 }
1028
sync_recv_v2(SyncConnection & sc,const char * rpath,const char * lpath,const char * name,uint64_t expected_size)1029 static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpath, const char* name,
1030 uint64_t expected_size) {
1031 if (!sc.SendRecv2(rpath)) return false;
1032
1033 adb_unlink(lpath);
1034 unique_fd lfd(adb_creat(lpath, 0644));
1035 if (lfd < 0) {
1036 sc.Error("cannot create '%s': %s", lpath, strerror(errno));
1037 return false;
1038 }
1039
1040 uint64_t bytes_copied = 0;
1041
1042 Block buffer(SYNC_DATA_MAX);
1043 BrotliDecoder decoder(std::span(buffer.data(), buffer.size()));
1044 bool reading = true;
1045 while (reading) {
1046 syncmsg msg;
1047 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
1048 adb_unlink(lpath);
1049 return false;
1050 }
1051
1052 if (msg.data.id == ID_DONE) {
1053 adb_unlink(lpath);
1054 sc.Error("unexpected ID_DONE");
1055 return false;
1056 }
1057
1058 if (msg.data.id != ID_DATA) {
1059 adb_unlink(lpath);
1060 sc.ReportCopyFailure(rpath, lpath, msg);
1061 return false;
1062 }
1063
1064 if (msg.data.size > sc.max) {
1065 sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
1066 adb_unlink(lpath);
1067 return false;
1068 }
1069
1070 Block block(msg.data.size);
1071 if (!ReadFdExactly(sc.fd, block.data(), msg.data.size)) {
1072 adb_unlink(lpath);
1073 return false;
1074 }
1075 decoder.Append(std::move(block));
1076
1077 while (true) {
1078 std::span<char> output;
1079 BrotliDecodeResult result = decoder.Decode(&output);
1080
1081 if (result == BrotliDecodeResult::Error) {
1082 sc.Error("decompress failed");
1083 adb_unlink(lpath);
1084 return false;
1085 }
1086
1087 if (!output.empty()) {
1088 if (!WriteFdExactly(lfd, output.data(), output.size())) {
1089 sc.Error("cannot write '%s': %s", lpath, strerror(errno));
1090 adb_unlink(lpath);
1091 return false;
1092 }
1093 }
1094
1095 bytes_copied += output.size();
1096
1097 sc.RecordBytesTransferred(msg.data.size);
1098 sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, expected_size);
1099
1100 if (result == BrotliDecodeResult::NeedInput) {
1101 break;
1102 } else if (result == BrotliDecodeResult::MoreOutput) {
1103 continue;
1104 } else if (result == BrotliDecodeResult::Done) {
1105 reading = false;
1106 break;
1107 } else {
1108 LOG(FATAL) << "invalid BrotliDecodeResult: " << static_cast<int>(result);
1109 }
1110 }
1111 }
1112
1113 syncmsg msg;
1114 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
1115 sc.Error("failed to read ID_DONE");
1116 return false;
1117 }
1118
1119 if (msg.data.id != ID_DONE) {
1120 sc.Error("unexpected message after transfer: id = %d (expected ID_DONE)", msg.data.id);
1121 return false;
1122 }
1123
1124 sc.RecordFilesTransferred(1);
1125 return true;
1126 }
1127
sync_recv(SyncConnection & sc,const char * rpath,const char * lpath,const char * name,uint64_t expected_size,bool compressed)1128 static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, const char* name,
1129 uint64_t expected_size, bool compressed) {
1130 if (sc.HaveSendRecv2() && compressed) {
1131 return sync_recv_v2(sc, rpath, lpath, name, expected_size);
1132 } else {
1133 return sync_recv_v1(sc, rpath, lpath, name, expected_size);
1134 }
1135 }
1136
do_sync_ls(const char * path)1137 bool do_sync_ls(const char* path) {
1138 SyncConnection sc;
1139 if (!sc.IsValid()) return false;
1140
1141 return sync_ls(sc, path, [](unsigned mode, uint64_t size, uint64_t time, const char* name) {
1142 printf("%08x %08" PRIx64 " %08" PRIx64 " %s\n", mode, size, time, name);
1143 });
1144 }
1145
IsDotOrDotDot(const char * name)1146 static bool IsDotOrDotDot(const char* name) {
1147 return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
1148 }
1149
local_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,std::vector<std::string> * directory_list,const std::string & lpath,const std::string & rpath)1150 static bool local_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
1151 std::vector<std::string>* directory_list, const std::string& lpath,
1152 const std::string& rpath) {
1153 std::vector<copyinfo> dirlist;
1154 std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(lpath.c_str()), closedir);
1155 if (!dir) {
1156 sc.Error("cannot open '%s': %s", lpath.c_str(), strerror(errno));
1157 return false;
1158 }
1159
1160 bool empty_dir = true;
1161 dirent* de;
1162 while ((de = readdir(dir.get()))) {
1163 if (IsDotOrDotDot(de->d_name)) {
1164 continue;
1165 }
1166
1167 empty_dir = false;
1168 std::string stat_path = lpath + de->d_name;
1169
1170 struct stat st;
1171 if (lstat(stat_path.c_str(), &st) == -1) {
1172 sc.Error("cannot lstat '%s': %s", stat_path.c_str(),
1173 strerror(errno));
1174 continue;
1175 }
1176
1177 copyinfo ci(lpath, rpath, de->d_name, st.st_mode);
1178 if (S_ISDIR(st.st_mode)) {
1179 dirlist.push_back(ci);
1180 } else {
1181 if (!should_push_file(st.st_mode)) {
1182 sc.Warning("skipping special file '%s' (mode = 0o%o)", lpath.c_str(), st.st_mode);
1183 ci.skip = true;
1184 }
1185 ci.time = st.st_mtime;
1186 ci.size = st.st_size;
1187 file_list->push_back(ci);
1188 }
1189 }
1190
1191 // Close this directory and recurse.
1192 dir.reset();
1193
1194 for (const copyinfo& ci : dirlist) {
1195 directory_list->push_back(ci.rpath);
1196 local_build_list(sc, file_list, directory_list, ci.lpath, ci.rpath);
1197 }
1198
1199 return true;
1200 }
1201
1202 // dirname("//foo") returns "//", so we can't do the obvious `path == "/"`.
is_root_dir(std::string_view path)1203 static bool is_root_dir(std::string_view path) {
1204 for (char c : path) {
1205 if (c != '/') {
1206 return false;
1207 }
1208 }
1209 return true;
1210 }
1211
copy_local_dir_remote(SyncConnection & sc,std::string lpath,std::string rpath,bool check_timestamps,bool list_only,bool compressed)1212 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::string rpath,
1213 bool check_timestamps, bool list_only, bool compressed) {
1214 sc.NewTransfer();
1215
1216 // Make sure that both directory paths end in a slash.
1217 // Both paths are known to be nonempty, so we don't need to check.
1218 ensure_trailing_separators(lpath, rpath);
1219
1220 // Recursively build the list of files to copy.
1221 std::vector<copyinfo> file_list;
1222 std::vector<std::string> directory_list;
1223
1224 for (std::string path = rpath; !is_root_dir(path); path = android::base::Dirname(path)) {
1225 directory_list.push_back(path);
1226 }
1227 std::reverse(directory_list.begin(), directory_list.end());
1228
1229 int skipped = 0;
1230 if (!local_build_list(sc, &file_list, &directory_list, lpath, rpath)) {
1231 return false;
1232 }
1233
1234 // b/110953234:
1235 // P shipped with a bug that causes directory creation as a side-effect of a push to fail.
1236 // Work around this by explicitly doing a mkdir via shell.
1237 //
1238 // Devices that don't support shell_v2 are unhappy if we try to send a too-long packet to them,
1239 // but they're not affected by this bug, so only apply the workaround if we have shell_v2.
1240 //
1241 // TODO(b/25457350): We don't preserve permissions on directories.
1242 // TODO: Find all of the leaves and `mkdir -p` them instead?
1243 if (!CanUseFeature(sc.Features(), kFeatureFixedPushMkdir) &&
1244 CanUseFeature(sc.Features(), kFeatureShell2)) {
1245 SilentStandardStreamsCallbackInterface cb;
1246 std::string cmd = "mkdir";
1247 for (const auto& dir : directory_list) {
1248 std::string escaped_path = escape_arg(dir);
1249 if (escaped_path.size() > 16384) {
1250 // Somewhat arbitrarily limit that probably won't ever happen.
1251 sc.Error("path too long: %s", escaped_path.c_str());
1252 return false;
1253 }
1254
1255 // The maximum should be 64kiB, but that's not including other stuff that gets tacked
1256 // onto the command line, so let's be a bit conservative.
1257 if (cmd.size() + escaped_path.size() > 32768) {
1258 // Dispatch the command, ignoring failure (since the directory might already exist).
1259 send_shell_command(cmd, false, &cb);
1260 cmd = "mkdir";
1261 }
1262 cmd += " ";
1263 cmd += escaped_path;
1264 }
1265
1266 if (cmd != "mkdir") {
1267 send_shell_command(cmd, false, &cb);
1268 }
1269 }
1270
1271 if (check_timestamps) {
1272 for (const copyinfo& ci : file_list) {
1273 if (!sc.SendLstat(ci.rpath)) {
1274 sc.Error("failed to send lstat");
1275 return false;
1276 }
1277 }
1278 for (copyinfo& ci : file_list) {
1279 struct stat st;
1280 if (sc.FinishStat(&st)) {
1281 if (st.st_size == static_cast<off_t>(ci.size) && st.st_mtime == ci.time) {
1282 ci.skip = true;
1283 }
1284 }
1285 }
1286 }
1287
1288 sc.ComputeExpectedTotalBytes(file_list);
1289
1290 for (const copyinfo& ci : file_list) {
1291 if (!ci.skip) {
1292 if (list_only) {
1293 sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
1294 } else {
1295 if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compressed)) {
1296 return false;
1297 }
1298 }
1299 } else {
1300 skipped++;
1301 }
1302 }
1303
1304 sc.RecordFilesSkipped(skipped);
1305 bool success = sc.ReadAcknowledgements(true);
1306 sc.ReportTransferRate(lpath, TransferDirection::push);
1307 return success;
1308 }
1309
do_sync_push(const std::vector<const char * > & srcs,const char * dst,bool sync,bool compressed)1310 bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync,
1311 bool compressed) {
1312 SyncConnection sc;
1313 if (!sc.IsValid()) return false;
1314
1315 bool success = true;
1316 bool dst_exists;
1317 bool dst_isdir;
1318
1319 struct stat st;
1320 if (sync_stat_fallback(sc, dst, &st)) {
1321 dst_exists = true;
1322 dst_isdir = S_ISDIR(st.st_mode);
1323 } else {
1324 if (errno == ENOENT || errno == ENOPROTOOPT) {
1325 dst_exists = false;
1326 dst_isdir = false;
1327 } else {
1328 sc.Error("stat failed when trying to push to %s: %s", dst, strerror(errno));
1329 return false;
1330 }
1331 }
1332
1333 if (!dst_isdir) {
1334 if (srcs.size() > 1) {
1335 sc.Error("target '%s' is not a directory", dst);
1336 return false;
1337 } else {
1338 size_t dst_len = strlen(dst);
1339
1340 // A path that ends with a slash doesn't have to be a directory if
1341 // it doesn't exist yet.
1342 if (dst[dst_len - 1] == '/' && dst_exists) {
1343 sc.Error("failed to access '%s': Not a directory", dst);
1344 return false;
1345 }
1346 }
1347 }
1348
1349 for (const char* src_path : srcs) {
1350 const char* dst_path = dst;
1351 struct stat st;
1352 if (stat(src_path, &st) == -1) {
1353 sc.Error("cannot stat '%s': %s", src_path, strerror(errno));
1354 success = false;
1355 continue;
1356 }
1357
1358 if (S_ISDIR(st.st_mode)) {
1359 std::string dst_dir = dst;
1360
1361 // If the destination path existed originally, the source directory
1362 // should be copied as a child of the destination.
1363 if (dst_exists) {
1364 if (!dst_isdir) {
1365 sc.Error("target '%s' is not a directory", dst);
1366 return false;
1367 }
1368 // dst is a POSIX path, so we don't want to use the sysdeps
1369 // helpers here.
1370 if (dst_dir.back() != '/') {
1371 dst_dir.push_back('/');
1372 }
1373 dst_dir.append(android::base::Basename(src_path));
1374 }
1375
1376 success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compressed);
1377 continue;
1378 } else if (!should_push_file(st.st_mode)) {
1379 sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
1380 continue;
1381 }
1382
1383 std::string path_holder;
1384 if (dst_isdir) {
1385 // If we're copying a local file to a remote directory,
1386 // we really want to copy to remote_dir + "/" + local_filename.
1387 path_holder = dst_path;
1388 if (path_holder.back() != '/') {
1389 path_holder.push_back('/');
1390 }
1391 path_holder += android::base::Basename(src_path);
1392 dst_path = path_holder.c_str();
1393 }
1394
1395 sc.NewTransfer();
1396 sc.SetExpectedTotalBytes(st.st_size);
1397 success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compressed);
1398 sc.ReportTransferRate(src_path, TransferDirection::push);
1399 }
1400
1401 success &= sc.ReadAcknowledgements(true);
1402 sc.ReportOverallTransferRate(TransferDirection::push);
1403 return success;
1404 }
1405
remote_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,const std::string & rpath,const std::string & lpath)1406 static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
1407 const std::string& rpath, const std::string& lpath) {
1408 std::vector<copyinfo> dirlist;
1409 std::vector<copyinfo> linklist;
1410
1411 // Add an entry for the current directory to ensure it gets created before pulling its contents.
1412 copyinfo ci(android::base::Dirname(lpath), android::base::Dirname(rpath),
1413 android::base::Basename(lpath), S_IFDIR);
1414 file_list->push_back(ci);
1415
1416 // Put the files/dirs in rpath on the lists.
1417 auto callback = [&](unsigned mode, uint64_t size, uint64_t time, const char* name) {
1418 if (IsDotOrDotDot(name)) {
1419 return;
1420 }
1421
1422 copyinfo ci(lpath, rpath, name, mode);
1423 if (S_ISDIR(mode)) {
1424 dirlist.push_back(ci);
1425 } else if (S_ISLNK(mode)) {
1426 linklist.push_back(ci);
1427 } else {
1428 if (!should_pull_file(ci.mode)) {
1429 sc.Warning("skipping special file '%s' (mode = 0o%o)", ci.rpath.c_str(), ci.mode);
1430 ci.skip = true;
1431 }
1432 ci.time = time;
1433 ci.size = size;
1434 file_list->push_back(ci);
1435 }
1436 };
1437
1438 if (!sync_ls(sc, rpath.c_str(), callback)) {
1439 return false;
1440 }
1441
1442 // Check each symlink we found to see whether it's a file or directory.
1443 for (copyinfo& link_ci : linklist) {
1444 struct stat st;
1445 if (!sync_stat_fallback(sc, link_ci.rpath.c_str(), &st)) {
1446 sc.Warning("stat failed for path %s: %s", link_ci.rpath.c_str(), strerror(errno));
1447 continue;
1448 }
1449
1450 if (S_ISDIR(st.st_mode)) {
1451 dirlist.emplace_back(std::move(link_ci));
1452 } else {
1453 file_list->emplace_back(std::move(link_ci));
1454 }
1455 }
1456
1457 // Recurse into each directory we found.
1458 while (!dirlist.empty()) {
1459 copyinfo current = dirlist.back();
1460 dirlist.pop_back();
1461 if (!remote_build_list(sc, file_list, current.rpath, current.lpath)) {
1462 return false;
1463 }
1464 }
1465
1466 return true;
1467 }
1468
set_time_and_mode(const std::string & lpath,time_t time,unsigned int mode)1469 static int set_time_and_mode(const std::string& lpath, time_t time,
1470 unsigned int mode) {
1471 struct utimbuf times = { time, time };
1472 int r1 = utime(lpath.c_str(), ×);
1473
1474 /* use umask for permissions */
1475 mode_t mask = umask(0000);
1476 umask(mask);
1477 int r2 = chmod(lpath.c_str(), mode & ~mask);
1478
1479 return r1 ? r1 : r2;
1480 }
1481
copy_remote_dir_local(SyncConnection & sc,std::string rpath,std::string lpath,bool copy_attrs,bool compressed)1482 static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::string lpath,
1483 bool copy_attrs, bool compressed) {
1484 sc.NewTransfer();
1485
1486 // Make sure that both directory paths end in a slash.
1487 // Both paths are known to be nonempty, so we don't need to check.
1488 ensure_trailing_separators(lpath, rpath);
1489
1490 // Recursively build the list of files to copy.
1491 sc.Printf("pull: building file list...");
1492 std::vector<copyinfo> file_list;
1493 if (!remote_build_list(sc, &file_list, rpath, lpath)) {
1494 return false;
1495 }
1496
1497 sc.ComputeExpectedTotalBytes(file_list);
1498
1499 int skipped = 0;
1500 for (const copyinfo &ci : file_list) {
1501 if (!ci.skip) {
1502 if (S_ISDIR(ci.mode)) {
1503 // Entry is for an empty directory, create it and continue.
1504 // TODO(b/25457350): We don't preserve permissions on directories.
1505 if (!mkdirs(ci.lpath)) {
1506 sc.Error("failed to create directory '%s': %s",
1507 ci.lpath.c_str(), strerror(errno));
1508 return false;
1509 }
1510 continue;
1511 }
1512
1513 if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compressed)) {
1514 return false;
1515 }
1516
1517 if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
1518 return false;
1519 }
1520 } else {
1521 skipped++;
1522 }
1523 }
1524
1525 sc.RecordFilesSkipped(skipped);
1526 sc.ReportTransferRate(rpath, TransferDirection::pull);
1527 return true;
1528 }
1529
do_sync_pull(const std::vector<const char * > & srcs,const char * dst,bool copy_attrs,bool compressed,const char * name)1530 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
1531 bool compressed, const char* name) {
1532 SyncConnection sc;
1533 if (!sc.IsValid()) return false;
1534
1535 bool success = true;
1536 struct stat st;
1537 bool dst_exists = true;
1538
1539 if (stat(dst, &st) == -1) {
1540 dst_exists = false;
1541
1542 // If we're only pulling one path, the destination path might point to
1543 // a path that doesn't exist yet.
1544 if (srcs.size() == 1 && errno == ENOENT) {
1545 // However, its parent must exist.
1546 struct stat parent_st;
1547 if (stat(android::base::Dirname(dst).c_str(), &parent_st) == -1) {
1548 sc.Error("cannot create file/directory '%s': %s", dst, strerror(errno));
1549 return false;
1550 }
1551 } else {
1552 sc.Error("failed to access '%s': %s", dst, strerror(errno));
1553 return false;
1554 }
1555 }
1556
1557 bool dst_isdir = dst_exists && S_ISDIR(st.st_mode);
1558 if (!dst_isdir) {
1559 if (srcs.size() > 1) {
1560 sc.Error("target '%s' is not a directory", dst);
1561 return false;
1562 } else {
1563 size_t dst_len = strlen(dst);
1564
1565 // A path that ends with a slash doesn't have to be a directory if
1566 // it doesn't exist yet.
1567 if (adb_is_separator(dst[dst_len - 1]) && dst_exists) {
1568 sc.Error("failed to access '%s': Not a directory", dst);
1569 return false;
1570 }
1571 }
1572 }
1573
1574 for (const char* src_path : srcs) {
1575 const char* dst_path = dst;
1576 struct stat src_st;
1577 if (!sync_stat_fallback(sc, src_path, &src_st)) {
1578 if (errno == ENOPROTOOPT) {
1579 sc.Error("remote object '%s' does not exist", src_path);
1580 } else {
1581 sc.Error("failed to stat remote object '%s': %s", src_path, strerror(errno));
1582 }
1583
1584 success = false;
1585 continue;
1586 }
1587
1588 bool src_isdir = S_ISDIR(src_st.st_mode);
1589 if (src_isdir) {
1590 std::string dst_dir = dst;
1591
1592 // If the destination path existed originally, the source directory
1593 // should be copied as a child of the destination.
1594 if (dst_exists) {
1595 if (!dst_isdir) {
1596 sc.Error("target '%s' is not a directory", dst);
1597 return false;
1598 }
1599 if (!adb_is_separator(dst_dir.back())) {
1600 dst_dir.push_back(OS_PATH_SEPARATOR);
1601 }
1602 dst_dir.append(android::base::Basename(src_path));
1603 }
1604
1605 success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compressed);
1606 continue;
1607 } else if (!should_pull_file(src_st.st_mode)) {
1608 sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode);
1609 continue;
1610 }
1611
1612 std::string path_holder;
1613 if (dst_isdir) {
1614 // If we're copying a remote file to a local directory, we
1615 // really want to copy to local_dir + OS_PATH_SEPARATOR +
1616 // basename(remote).
1617 path_holder = android::base::StringPrintf("%s%c%s", dst_path, OS_PATH_SEPARATOR,
1618 android::base::Basename(src_path).c_str());
1619 dst_path = path_holder.c_str();
1620 }
1621
1622 sc.NewTransfer();
1623 sc.SetExpectedTotalBytes(src_st.st_size);
1624 if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compressed)) {
1625 success = false;
1626 continue;
1627 }
1628
1629 if (copy_attrs && set_time_and_mode(dst_path, src_st.st_mtime, src_st.st_mode) != 0) {
1630 success = false;
1631 continue;
1632 }
1633 sc.ReportTransferRate(src_path, TransferDirection::pull);
1634 }
1635
1636 sc.ReportOverallTransferRate(TransferDirection::pull);
1637 return success;
1638 }
1639
do_sync_sync(const std::string & lpath,const std::string & rpath,bool list_only,bool compressed)1640 bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only,
1641 bool compressed) {
1642 SyncConnection sc;
1643 if (!sc.IsValid()) return false;
1644
1645 bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compressed);
1646 if (!list_only) {
1647 sc.ReportOverallTransferRate(TransferDirection::push);
1648 }
1649 return success;
1650 }
1651