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