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