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(), &times);
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