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