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 <functional>
33 #include <memory>
34 #include <sstream>
35 #include <string>
36 #include <vector>
37
38 #include "sysdeps.h"
39
40 #include "adb.h"
41 #include "adb_client.h"
42 #include "adb_io.h"
43 #include "adb_utils.h"
44 #include "file_sync_protocol.h"
45 #include "line_printer.h"
46 #include "sysdeps/errno.h"
47 #include "sysdeps/stat.h"
48
49 #include "client/commandline.h"
50
51 #include <android-base/file.h>
52 #include <android-base/strings.h>
53 #include <android-base/stringprintf.h>
54
55 struct syncsendbuf {
56 unsigned id;
57 unsigned size;
58 char data[SYNC_DATA_MAX];
59 };
60
ensure_trailing_separators(std::string & local_path,std::string & remote_path)61 static void ensure_trailing_separators(std::string& local_path, std::string& remote_path) {
62 if (!adb_is_separator(local_path.back())) {
63 local_path.push_back(OS_PATH_SEPARATOR);
64 }
65 if (remote_path.back() != '/') {
66 remote_path.push_back('/');
67 }
68 }
69
should_pull_file(mode_t mode)70 static bool should_pull_file(mode_t mode) {
71 return S_ISREG(mode) || S_ISBLK(mode) || S_ISCHR(mode);
72 }
73
should_push_file(mode_t mode)74 static bool should_push_file(mode_t mode) {
75 return S_ISREG(mode) || S_ISLNK(mode);
76 }
77
78 struct copyinfo {
79 std::string lpath;
80 std::string rpath;
81 int64_t time = 0;
82 uint32_t mode;
83 uint64_t size = 0;
84 bool skip = false;
85
copyinfocopyinfo86 copyinfo(const std::string& local_path,
87 const std::string& remote_path,
88 const std::string& name,
89 unsigned int mode)
90 : lpath(local_path), rpath(remote_path), mode(mode) {
91 ensure_trailing_separators(lpath, rpath);
92 lpath.append(name);
93 rpath.append(name);
94 if (S_ISDIR(mode)) {
95 ensure_trailing_separators(lpath, rpath);
96 }
97 }
98 };
99
100 enum class TransferDirection {
101 push,
102 pull,
103 };
104
105 struct TransferLedger {
106 std::chrono::steady_clock::time_point start_time;
107 uint64_t files_transferred;
108 uint64_t files_skipped;
109 uint64_t bytes_transferred;
110 uint64_t bytes_expected;
111 bool expect_multiple_files;
112
TransferLedgerTransferLedger113 TransferLedger() {
114 Reset();
115 }
116
operator ==TransferLedger117 bool operator==(const TransferLedger& other) const {
118 return files_transferred == other.files_transferred &&
119 files_skipped == other.files_skipped && bytes_transferred == other.bytes_transferred;
120 }
121
operator !=TransferLedger122 bool operator!=(const TransferLedger& other) const {
123 return !(*this == other);
124 }
125
ResetTransferLedger126 void Reset() {
127 start_time = std::chrono::steady_clock::now();
128 files_transferred = 0;
129 files_skipped = 0;
130 bytes_transferred = 0;
131 bytes_expected = 0;
132 }
133
TransferRateTransferLedger134 std::string TransferRate() {
135 if (bytes_transferred == 0) return "";
136
137 std::chrono::duration<double> duration;
138 duration = std::chrono::steady_clock::now() - start_time;
139
140 double s = duration.count();
141 if (s == 0) {
142 return "";
143 }
144 double rate = (static_cast<double>(bytes_transferred) / s) / (1024 * 1024);
145 return android::base::StringPrintf(" %.1f MB/s (%" PRIu64 " bytes in %.3fs)", rate,
146 bytes_transferred, s);
147 }
148
ReportProgressTransferLedger149 void ReportProgress(LinePrinter& lp, const std::string& file, uint64_t file_copied_bytes,
150 uint64_t file_total_bytes) {
151 char overall_percentage_str[5] = "?";
152 if (bytes_expected != 0 && bytes_transferred <= bytes_expected) {
153 int overall_percentage = static_cast<int>(bytes_transferred * 100 / bytes_expected);
154 // If we're pulling symbolic links, we'll pull the target of the link rather than
155 // just create a local link, and that will cause us to go over 100%.
156 if (overall_percentage <= 100) {
157 snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
158 overall_percentage);
159 }
160 }
161
162 std::string output;
163 if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
164 // This case can happen if we're racing against something that wrote to the file
165 // between our stat and our read, or if we're reading a magic file that lies about
166 // its size. Just show how much we've copied.
167 output = android::base::StringPrintf("[%4s] %s: %" PRId64 "/?", overall_percentage_str,
168 file.c_str(), file_copied_bytes);
169 } else {
170 // If we're transferring multiple files, we want to know how far through the current
171 // file we are, as well as the overall percentage.
172 if (expect_multiple_files) {
173 int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
174 output = android::base::StringPrintf("[%4s] %s: %d%%", overall_percentage_str,
175 file.c_str(), file_percentage);
176 } else {
177 output =
178 android::base::StringPrintf("[%4s] %s", overall_percentage_str, file.c_str());
179 }
180 }
181 lp.Print(output, LinePrinter::LineType::INFO);
182 }
183
ReportTransferRateTransferLedger184 void ReportTransferRate(LinePrinter& lp, const std::string& name, TransferDirection direction) {
185 const char* direction_str = (direction == TransferDirection::push) ? "pushed" : "pulled";
186 std::stringstream ss;
187 if (!name.empty()) {
188 ss << name << ": ";
189 }
190 ss << files_transferred << " file" << ((files_transferred == 1) ? "" : "s") << " "
191 << direction_str << ".";
192 if (files_skipped > 0) {
193 ss << " " << files_skipped << " file" << ((files_skipped == 1) ? "" : "s")
194 << " skipped.";
195 }
196 ss << TransferRate();
197
198 lp.Print(ss.str(), LinePrinter::LineType::INFO);
199 lp.KeepInfoLine();
200 }
201 };
202
203 class SyncConnection {
204 public:
SyncConnection()205 SyncConnection() : expect_done_(false) {
206 max = SYNC_DATA_MAX; // TODO: decide at runtime.
207
208 std::string error;
209 if (!adb_get_feature_set(&features_, &error)) {
210 Error("failed to get feature set: %s", error.c_str());
211 } else {
212 have_stat_v2_ = CanUseFeature(features_, kFeatureStat2);
213 fd.reset(adb_connect("sync:", &error));
214 if (fd < 0) {
215 Error("connect failed: %s", error.c_str());
216 }
217 }
218 }
219
~SyncConnection()220 ~SyncConnection() {
221 if (!IsValid()) return;
222
223 if (SendQuit()) {
224 // We sent a quit command, so the server should be doing orderly
225 // shutdown soon. But if we encountered an error while we were using
226 // the connection, the server might still be sending data (before
227 // doing orderly shutdown), in which case we won't wait for all of
228 // the data nor the coming orderly shutdown. In the common success
229 // case, this will wait for the server to do orderly shutdown.
230 ReadOrderlyShutdown(fd);
231 }
232
233 line_printer_.KeepInfoLine();
234 }
235
Features() const236 const FeatureSet& Features() const { return features_; }
237
IsValid()238 bool IsValid() { return fd >= 0; }
239
ReceivedError(const char * from,const char * to)240 bool ReceivedError(const char* from, const char* to) {
241 adb_pollfd pfd = {.fd = fd.get(), .events = POLLIN};
242 int rc = adb_poll(&pfd, 1, 0);
243 if (rc < 0) {
244 Error("failed to poll: %s", strerror(errno));
245 return true;
246 }
247 return rc != 0;
248 }
249
NewTransfer()250 void NewTransfer() {
251 current_ledger_.Reset();
252 }
253
RecordBytesTransferred(size_t bytes)254 void RecordBytesTransferred(size_t bytes) {
255 current_ledger_.bytes_transferred += bytes;
256 global_ledger_.bytes_transferred += bytes;
257 }
258
RecordFilesTransferred(size_t files)259 void RecordFilesTransferred(size_t files) {
260 current_ledger_.files_transferred += files;
261 global_ledger_.files_transferred += files;
262 }
263
RecordFilesSkipped(size_t files)264 void RecordFilesSkipped(size_t files) {
265 current_ledger_.files_skipped += files;
266 global_ledger_.files_skipped += files;
267 }
268
ReportProgress(const std::string & file,uint64_t file_copied_bytes,uint64_t file_total_bytes)269 void ReportProgress(const std::string& file, uint64_t file_copied_bytes,
270 uint64_t file_total_bytes) {
271 current_ledger_.ReportProgress(line_printer_, file, file_copied_bytes, file_total_bytes);
272 }
273
ReportTransferRate(const std::string & file,TransferDirection direction)274 void ReportTransferRate(const std::string& file, TransferDirection direction) {
275 current_ledger_.ReportTransferRate(line_printer_, file, direction);
276 }
277
ReportOverallTransferRate(TransferDirection direction)278 void ReportOverallTransferRate(TransferDirection direction) {
279 if (current_ledger_ != global_ledger_) {
280 global_ledger_.ReportTransferRate(line_printer_, "", direction);
281 }
282 }
283
SendRequest(int id,const char * path_and_mode)284 bool SendRequest(int id, const char* path_and_mode) {
285 size_t path_length = strlen(path_and_mode);
286 if (path_length > 1024) {
287 Error("SendRequest failed: path too long: %zu", path_length);
288 errno = ENAMETOOLONG;
289 return false;
290 }
291
292 // Sending header and payload in a single write makes a noticeable
293 // difference to "adb sync" performance.
294 std::vector<char> buf(sizeof(SyncRequest) + path_length);
295 SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
296 req->id = id;
297 req->path_length = path_length;
298 char* data = reinterpret_cast<char*>(req + 1);
299 memcpy(data, path_and_mode, path_length);
300
301 return WriteFdExactly(fd, &buf[0], buf.size());
302 }
303
SendStat(const char * path_and_mode)304 bool SendStat(const char* path_and_mode) {
305 if (!have_stat_v2_) {
306 errno = ENOTSUP;
307 return false;
308 }
309 return SendRequest(ID_STAT_V2, path_and_mode);
310 }
311
SendLstat(const char * path_and_mode)312 bool SendLstat(const char* path_and_mode) {
313 if (have_stat_v2_) {
314 return SendRequest(ID_LSTAT_V2, path_and_mode);
315 } else {
316 return SendRequest(ID_LSTAT_V1, path_and_mode);
317 }
318 }
319
FinishStat(struct stat * st)320 bool FinishStat(struct stat* st) {
321 syncmsg msg;
322
323 memset(st, 0, sizeof(*st));
324 if (have_stat_v2_) {
325 if (!ReadFdExactly(fd.get(), &msg.stat_v2, sizeof(msg.stat_v2))) {
326 PLOG(FATAL) << "protocol fault: failed to read stat response";
327 }
328
329 if (msg.stat_v2.id != ID_LSTAT_V2 && msg.stat_v2.id != ID_STAT_V2) {
330 PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
331 << msg.stat_v2.id;
332 }
333
334 if (msg.stat_v2.error != 0) {
335 errno = errno_from_wire(msg.stat_v2.error);
336 return false;
337 }
338
339 st->st_dev = msg.stat_v2.dev;
340 st->st_ino = msg.stat_v2.ino;
341 st->st_mode = msg.stat_v2.mode;
342 st->st_nlink = msg.stat_v2.nlink;
343 st->st_uid = msg.stat_v2.uid;
344 st->st_gid = msg.stat_v2.gid;
345 st->st_size = msg.stat_v2.size;
346 st->st_atime = msg.stat_v2.atime;
347 st->st_mtime = msg.stat_v2.mtime;
348 st->st_ctime = msg.stat_v2.ctime;
349 return true;
350 } else {
351 if (!ReadFdExactly(fd.get(), &msg.stat_v1, sizeof(msg.stat_v1))) {
352 PLOG(FATAL) << "protocol fault: failed to read stat response";
353 }
354
355 if (msg.stat_v1.id != ID_LSTAT_V1) {
356 PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
357 << msg.stat_v1.id;
358 }
359
360 if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.time == 0) {
361 // There's no way for us to know what the error was.
362 errno = ENOPROTOOPT;
363 return false;
364 }
365
366 st->st_mode = msg.stat_v1.mode;
367 st->st_size = msg.stat_v1.size;
368 st->st_ctime = msg.stat_v1.time;
369 st->st_mtime = msg.stat_v1.time;
370 }
371
372 return true;
373 }
374
375 // Sending header, payload, and footer in a single write makes a huge
376 // difference to "adb sync" performance.
SendSmallFile(const char * path_and_mode,const char * lpath,const char * rpath,unsigned mtime,const char * data,size_t data_length)377 bool SendSmallFile(const char* path_and_mode,
378 const char* lpath, const char* rpath,
379 unsigned mtime,
380 const char* data, size_t data_length) {
381 size_t path_length = strlen(path_and_mode);
382 if (path_length > 1024) {
383 Error("SendSmallFile failed: path too long: %zu", path_length);
384 errno = ENAMETOOLONG;
385 return false;
386 }
387
388 std::vector<char> buf(sizeof(SyncRequest) + path_length +
389 sizeof(SyncRequest) + data_length +
390 sizeof(SyncRequest));
391 char* p = &buf[0];
392
393 SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
394 req_send->id = ID_SEND;
395 req_send->path_length = path_length;
396 p += sizeof(SyncRequest);
397 memcpy(p, path_and_mode, path_length);
398 p += path_length;
399
400 SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p);
401 req_data->id = ID_DATA;
402 req_data->path_length = data_length;
403 p += sizeof(SyncRequest);
404 memcpy(p, data, data_length);
405 p += data_length;
406
407 SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p);
408 req_done->id = ID_DONE;
409 req_done->path_length = mtime;
410 p += sizeof(SyncRequest);
411
412 WriteOrDie(lpath, rpath, &buf[0], (p - &buf[0]));
413 expect_done_ = true;
414
415 // RecordFilesTransferred gets called in CopyDone.
416 RecordBytesTransferred(data_length);
417 ReportProgress(rpath, data_length, data_length);
418 return true;
419 }
420
SendLargeFile(const char * path_and_mode,const char * lpath,const char * rpath,unsigned mtime)421 bool SendLargeFile(const char* path_and_mode,
422 const char* lpath, const char* rpath,
423 unsigned mtime) {
424 if (!SendRequest(ID_SEND, path_and_mode)) {
425 Error("failed to send ID_SEND message '%s': %s", path_and_mode, strerror(errno));
426 return false;
427 }
428
429 struct stat st;
430 if (stat(lpath, &st) == -1) {
431 Error("cannot stat '%s': %s", lpath, strerror(errno));
432 return false;
433 }
434
435 uint64_t total_size = st.st_size;
436 uint64_t bytes_copied = 0;
437
438 unique_fd lfd(adb_open(lpath, O_RDONLY));
439 if (lfd < 0) {
440 Error("opening '%s' locally failed: %s", lpath, strerror(errno));
441 return false;
442 }
443
444 syncsendbuf sbuf;
445 sbuf.id = ID_DATA;
446 while (true) {
447 int bytes_read = adb_read(lfd, sbuf.data, max - sizeof(SyncRequest));
448 if (bytes_read == -1) {
449 Error("reading '%s' locally failed: %s", lpath, strerror(errno));
450 return false;
451 } else if (bytes_read == 0) {
452 break;
453 }
454
455 sbuf.size = bytes_read;
456 WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + bytes_read);
457
458 RecordBytesTransferred(bytes_read);
459 bytes_copied += bytes_read;
460
461 // Check to see if we've received an error from the other side.
462 if (ReceivedError(lpath, rpath)) {
463 break;
464 }
465
466 ReportProgress(rpath, bytes_copied, total_size);
467 }
468
469 syncmsg msg;
470 msg.data.id = ID_DONE;
471 msg.data.size = mtime;
472 expect_done_ = true;
473
474 // RecordFilesTransferred gets called in CopyDone.
475 return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
476 }
477
CopyDone(const char * from,const char * to)478 bool CopyDone(const char* from, const char* to) {
479 syncmsg msg;
480 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
481 Error("failed to copy '%s' to '%s': couldn't read from device", from, to);
482 return false;
483 }
484 if (msg.status.id == ID_OKAY) {
485 if (expect_done_) {
486 expect_done_ = false;
487 RecordFilesTransferred(1);
488 return true;
489 } else {
490 Error("failed to copy '%s' to '%s': received premature success", from, to);
491 return true;
492 }
493 }
494 if (msg.status.id != ID_FAIL) {
495 Error("failed to copy '%s' to '%s': unknown reason %d", from, to, msg.status.id);
496 return false;
497 }
498 return ReportCopyFailure(from, to, msg);
499 }
500
ReportCopyFailure(const char * from,const char * to,const syncmsg & msg)501 bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
502 std::vector<char> buf(msg.status.msglen + 1);
503 if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
504 Error("failed to copy '%s' to '%s'; failed to read reason (!): %s",
505 from, to, strerror(errno));
506 return false;
507 }
508 buf[msg.status.msglen] = 0;
509 Error("failed to copy '%s' to '%s': remote %s", from, to, &buf[0]);
510 return false;
511 }
512
Printf(const char * fmt,...)513 void Printf(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
514 std::string s;
515
516 va_list ap;
517 va_start(ap, fmt);
518 android::base::StringAppendV(&s, fmt, ap);
519 va_end(ap);
520
521 line_printer_.Print(s, LinePrinter::INFO);
522 }
523
Println(const char * fmt,...)524 void Println(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
525 std::string s;
526
527 va_list ap;
528 va_start(ap, fmt);
529 android::base::StringAppendV(&s, fmt, ap);
530 va_end(ap);
531
532 line_printer_.Print(s, LinePrinter::INFO);
533 line_printer_.KeepInfoLine();
534 }
535
Error(const char * fmt,...)536 void Error(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
537 std::string s = "adb: error: ";
538
539 va_list ap;
540 va_start(ap, fmt);
541 android::base::StringAppendV(&s, fmt, ap);
542 va_end(ap);
543
544 line_printer_.Print(s, LinePrinter::ERROR);
545 }
546
Warning(const char * fmt,...)547 void Warning(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
548 std::string s = "adb: warning: ";
549
550 va_list ap;
551 va_start(ap, fmt);
552 android::base::StringAppendV(&s, fmt, ap);
553 va_end(ap);
554
555 line_printer_.Print(s, LinePrinter::WARNING);
556 }
557
ComputeExpectedTotalBytes(const std::vector<copyinfo> & file_list)558 void ComputeExpectedTotalBytes(const std::vector<copyinfo>& file_list) {
559 current_ledger_.bytes_expected = 0;
560 for (const copyinfo& ci : file_list) {
561 // Unfortunately, this doesn't work for symbolic links, because we'll copy the
562 // target of the link rather than just creating a link. (But ci.size is the link size.)
563 if (!ci.skip) current_ledger_.bytes_expected += ci.size;
564 }
565 current_ledger_.expect_multiple_files = true;
566 }
567
SetExpectedTotalBytes(uint64_t expected_total_bytes)568 void SetExpectedTotalBytes(uint64_t expected_total_bytes) {
569 current_ledger_.bytes_expected = expected_total_bytes;
570 current_ledger_.expect_multiple_files = false;
571 }
572
573 // TODO: add a char[max] buffer here, to replace syncsendbuf...
574 unique_fd fd;
575 size_t max;
576
577 private:
578 bool expect_done_;
579 FeatureSet features_;
580 bool have_stat_v2_;
581
582 TransferLedger global_ledger_;
583 TransferLedger current_ledger_;
584 LinePrinter line_printer_;
585
SendQuit()586 bool SendQuit() {
587 return SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
588 }
589
WriteOrDie(const char * from,const char * to,const void * data,size_t data_length)590 bool WriteOrDie(const char* from, const char* to, const void* data, size_t data_length) {
591 if (!WriteFdExactly(fd, data, data_length)) {
592 if (errno == ECONNRESET) {
593 // Assume adbd told us why it was closing the connection, and
594 // try to read failure reason from adbd.
595 syncmsg msg;
596 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
597 Error("failed to copy '%s' to '%s': no response: %s", from, to, strerror(errno));
598 } else if (msg.status.id != ID_FAIL) {
599 Error("failed to copy '%s' to '%s': not ID_FAIL: %d", from, to, msg.status.id);
600 } else {
601 ReportCopyFailure(from, to, msg);
602 }
603 } else {
604 Error("%zu-byte write failed: %s", data_length, strerror(errno));
605 }
606 _exit(1);
607 }
608 return true;
609 }
610 };
611
612 typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
613
sync_ls(SyncConnection & sc,const char * path,const std::function<sync_ls_cb> & func)614 static bool sync_ls(SyncConnection& sc, const char* path,
615 const std::function<sync_ls_cb>& func) {
616 if (!sc.SendRequest(ID_LIST, path)) return false;
617
618 while (true) {
619 syncmsg msg;
620 if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false;
621
622 if (msg.dent.id == ID_DONE) return true;
623 if (msg.dent.id != ID_DENT) return false;
624
625 size_t len = msg.dent.namelen;
626 if (len > 256) return false; // TODO: resize buffer? continue?
627
628 char buf[257];
629 if (!ReadFdExactly(sc.fd, buf, len)) return false;
630 buf[len] = 0;
631
632 func(msg.dent.mode, msg.dent.size, msg.dent.time, buf);
633 }
634 }
635
sync_stat(SyncConnection & sc,const char * path,struct stat * st)636 static bool sync_stat(SyncConnection& sc, const char* path, struct stat* st) {
637 return sc.SendStat(path) && sc.FinishStat(st);
638 }
639
sync_lstat(SyncConnection & sc,const char * path,struct stat * st)640 static bool sync_lstat(SyncConnection& sc, const char* path, struct stat* st) {
641 return sc.SendLstat(path) && sc.FinishStat(st);
642 }
643
sync_stat_fallback(SyncConnection & sc,const char * path,struct stat * st)644 static bool sync_stat_fallback(SyncConnection& sc, const char* path, struct stat* st) {
645 if (sync_stat(sc, path, st)) {
646 return true;
647 }
648
649 if (errno != ENOTSUP) {
650 return false;
651 }
652
653 // Try to emulate the parts we can when talking to older adbds.
654 bool lstat_result = sync_lstat(sc, path, st);
655 if (!lstat_result) {
656 return false;
657 }
658
659 if (S_ISLNK(st->st_mode)) {
660 // If the target is a symlink, figure out whether it's a file or a directory.
661 // Also, zero out the st_size field, since no one actually cares what the path length is.
662 st->st_size = 0;
663 std::string dir_path = path;
664 dir_path.push_back('/');
665 struct stat tmp_st;
666
667 st->st_mode &= ~S_IFMT;
668 if (sync_lstat(sc, dir_path.c_str(), &tmp_st)) {
669 st->st_mode |= S_IFDIR;
670 } else {
671 st->st_mode |= S_IFREG;
672 }
673 }
674 return true;
675 }
676
sync_send(SyncConnection & sc,const char * lpath,const char * rpath,unsigned mtime,mode_t mode,bool sync)677 static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath, unsigned mtime,
678 mode_t mode, bool sync) {
679 std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
680
681 if (sync) {
682 struct stat st;
683 if (sync_lstat(sc, rpath, &st)) {
684 if (st.st_mtime == static_cast<time_t>(mtime)) {
685 sc.RecordFilesSkipped(1);
686 return true;
687 }
688 }
689 }
690
691 if (S_ISLNK(mode)) {
692 #if !defined(_WIN32)
693 char buf[PATH_MAX];
694 ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
695 if (data_length == -1) {
696 sc.Error("readlink '%s' failed: %s", lpath, strerror(errno));
697 return false;
698 }
699 buf[data_length++] = '\0';
700
701 if (!sc.SendSmallFile(path_and_mode.c_str(), lpath, rpath, mtime, buf, data_length)) {
702 return false;
703 }
704 return sc.CopyDone(lpath, rpath);
705 #endif
706 }
707
708 struct stat st;
709 if (stat(lpath, &st) == -1) {
710 sc.Error("failed to stat local file '%s': %s", lpath, strerror(errno));
711 return false;
712 }
713 if (st.st_size < SYNC_DATA_MAX) {
714 std::string data;
715 if (!android::base::ReadFileToString(lpath, &data, true)) {
716 sc.Error("failed to read all of '%s': %s", lpath, strerror(errno));
717 return false;
718 }
719 if (!sc.SendSmallFile(path_and_mode.c_str(), lpath, rpath, mtime,
720 data.data(), data.size())) {
721 return false;
722 }
723 } else {
724 if (!sc.SendLargeFile(path_and_mode.c_str(), lpath, rpath, mtime)) {
725 return false;
726 }
727 }
728 return sc.CopyDone(lpath, rpath);
729 }
730
sync_recv(SyncConnection & sc,const char * rpath,const char * lpath,const char * name,uint64_t expected_size)731 static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
732 const char* name, uint64_t expected_size) {
733 if (!sc.SendRequest(ID_RECV, rpath)) return false;
734
735 adb_unlink(lpath);
736 unique_fd lfd(adb_creat(lpath, 0644));
737 if (lfd < 0) {
738 sc.Error("cannot create '%s': %s", lpath, strerror(errno));
739 return false;
740 }
741
742 uint64_t bytes_copied = 0;
743 while (true) {
744 syncmsg msg;
745 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
746 adb_unlink(lpath);
747 return false;
748 }
749
750 if (msg.data.id == ID_DONE) break;
751
752 if (msg.data.id != ID_DATA) {
753 adb_unlink(lpath);
754 sc.ReportCopyFailure(rpath, lpath, msg);
755 return false;
756 }
757
758 if (msg.data.size > sc.max) {
759 sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
760 adb_unlink(lpath);
761 return false;
762 }
763
764 char buffer[SYNC_DATA_MAX];
765 if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
766 adb_unlink(lpath);
767 return false;
768 }
769
770 if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
771 sc.Error("cannot write '%s': %s", lpath, strerror(errno));
772 adb_unlink(lpath);
773 return false;
774 }
775
776 bytes_copied += msg.data.size;
777
778 sc.RecordBytesTransferred(msg.data.size);
779 sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, expected_size);
780 }
781
782 sc.RecordFilesTransferred(1);
783 return true;
784 }
785
do_sync_ls(const char * path)786 bool do_sync_ls(const char* path) {
787 SyncConnection sc;
788 if (!sc.IsValid()) return false;
789
790 return sync_ls(sc, path, [](unsigned mode, unsigned size, unsigned time,
791 const char* name) {
792 printf("%08x %08x %08x %s\n", mode, size, time, name);
793 });
794 }
795
IsDotOrDotDot(const char * name)796 static bool IsDotOrDotDot(const char* name) {
797 return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
798 }
799
local_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,std::vector<std::string> * directory_list,const std::string & lpath,const std::string & rpath)800 static bool local_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
801 std::vector<std::string>* directory_list, const std::string& lpath,
802 const std::string& rpath) {
803 std::vector<copyinfo> dirlist;
804 std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(lpath.c_str()), closedir);
805 if (!dir) {
806 sc.Error("cannot open '%s': %s", lpath.c_str(), strerror(errno));
807 return false;
808 }
809
810 bool empty_dir = true;
811 dirent* de;
812 while ((de = readdir(dir.get()))) {
813 if (IsDotOrDotDot(de->d_name)) {
814 continue;
815 }
816
817 empty_dir = false;
818 std::string stat_path = lpath + de->d_name;
819
820 struct stat st;
821 if (lstat(stat_path.c_str(), &st) == -1) {
822 sc.Error("cannot lstat '%s': %s", stat_path.c_str(),
823 strerror(errno));
824 continue;
825 }
826
827 copyinfo ci(lpath, rpath, de->d_name, st.st_mode);
828 if (S_ISDIR(st.st_mode)) {
829 dirlist.push_back(ci);
830 } else {
831 if (!should_push_file(st.st_mode)) {
832 sc.Warning("skipping special file '%s' (mode = 0o%o)", lpath.c_str(), st.st_mode);
833 ci.skip = true;
834 }
835 ci.time = st.st_mtime;
836 ci.size = st.st_size;
837 file_list->push_back(ci);
838 }
839 }
840
841 // Close this directory and recurse.
842 dir.reset();
843
844 for (const copyinfo& ci : dirlist) {
845 directory_list->push_back(ci.rpath);
846 local_build_list(sc, file_list, directory_list, ci.lpath, ci.rpath);
847 }
848
849 return true;
850 }
851
copy_local_dir_remote(SyncConnection & sc,std::string lpath,std::string rpath,bool check_timestamps,bool list_only)852 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
853 std::string rpath, bool check_timestamps,
854 bool list_only) {
855 sc.NewTransfer();
856
857 // Make sure that both directory paths end in a slash.
858 // Both paths are known to be nonempty, so we don't need to check.
859 ensure_trailing_separators(lpath, rpath);
860
861 // Recursively build the list of files to copy.
862 std::vector<copyinfo> file_list;
863 std::vector<std::string> directory_list;
864
865 for (std::string dirpath = rpath; dirpath != "/"; dirpath = android::base::Dirname(dirpath)) {
866 directory_list.push_back(dirpath);
867 }
868 std::reverse(directory_list.begin(), directory_list.end());
869
870 int skipped = 0;
871 if (!local_build_list(sc, &file_list, &directory_list, lpath, rpath)) {
872 return false;
873 }
874
875 // b/110953234:
876 // P shipped with a bug that causes directory creation as a side-effect of a push to fail.
877 // Work around this by explicitly doing a mkdir via shell.
878 //
879 // Devices that don't support shell_v2 are unhappy if we try to send a too-long packet to them,
880 // but they're not affected by this bug, so only apply the workaround if we have shell_v2.
881 //
882 // TODO(b/25457350): We don't preserve permissions on directories.
883 // TODO: Find all of the leaves and `mkdir -p` them instead?
884 if (!CanUseFeature(sc.Features(), kFeatureFixedPushMkdir) &&
885 CanUseFeature(sc.Features(), kFeatureShell2)) {
886 SilentStandardStreamsCallbackInterface cb;
887 std::string cmd = "mkdir";
888 for (const auto& dir : directory_list) {
889 std::string escaped_path = escape_arg(dir);
890 if (escaped_path.size() > 16384) {
891 // Somewhat arbitrarily limit that probably won't ever happen.
892 sc.Error("path too long: %s", escaped_path.c_str());
893 return false;
894 }
895
896 // The maximum should be 64kiB, but that's not including other stuff that gets tacked
897 // onto the command line, so let's be a bit conservative.
898 if (cmd.size() + escaped_path.size() > 32768) {
899 // Dispatch the command, ignoring failure (since the directory might already exist).
900 send_shell_command(cmd, false, &cb);
901 cmd = "mkdir";
902 }
903 cmd += " ";
904 cmd += escaped_path;
905 }
906
907 if (cmd != "mkdir") {
908 send_shell_command(cmd, false, &cb);
909 }
910 }
911
912 if (check_timestamps) {
913 for (const copyinfo& ci : file_list) {
914 if (!sc.SendLstat(ci.rpath.c_str())) {
915 sc.Error("failed to send lstat");
916 return false;
917 }
918 }
919 for (copyinfo& ci : file_list) {
920 struct stat st;
921 if (sc.FinishStat(&st)) {
922 if (st.st_size == static_cast<off_t>(ci.size) && st.st_mtime == ci.time) {
923 ci.skip = true;
924 }
925 }
926 }
927 }
928
929 sc.ComputeExpectedTotalBytes(file_list);
930
931 for (const copyinfo& ci : file_list) {
932 if (!ci.skip) {
933 if (list_only) {
934 sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
935 } else {
936 if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode, false)) {
937 return false;
938 }
939 }
940 } else {
941 skipped++;
942 }
943 }
944
945 sc.RecordFilesSkipped(skipped);
946 sc.ReportTransferRate(lpath, TransferDirection::push);
947 return true;
948 }
949
do_sync_push(const std::vector<const char * > & srcs,const char * dst,bool sync)950 bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync) {
951 SyncConnection sc;
952 if (!sc.IsValid()) return false;
953
954 bool success = true;
955 bool dst_exists;
956 bool dst_isdir;
957
958 struct stat st;
959 if (sync_stat_fallback(sc, dst, &st)) {
960 dst_exists = true;
961 dst_isdir = S_ISDIR(st.st_mode);
962 } else {
963 if (errno == ENOENT || errno == ENOPROTOOPT) {
964 dst_exists = false;
965 dst_isdir = false;
966 } else {
967 sc.Error("stat failed when trying to push to %s: %s", dst, strerror(errno));
968 return false;
969 }
970 }
971
972 if (!dst_isdir) {
973 if (srcs.size() > 1) {
974 sc.Error("target '%s' is not a directory", dst);
975 return false;
976 } else {
977 size_t dst_len = strlen(dst);
978
979 // A path that ends with a slash doesn't have to be a directory if
980 // it doesn't exist yet.
981 if (dst[dst_len - 1] == '/' && dst_exists) {
982 sc.Error("failed to access '%s': Not a directory", dst);
983 return false;
984 }
985 }
986 }
987
988 for (const char* src_path : srcs) {
989 const char* dst_path = dst;
990 struct stat st;
991 if (stat(src_path, &st) == -1) {
992 sc.Error("cannot stat '%s': %s", src_path, strerror(errno));
993 success = false;
994 continue;
995 }
996
997 if (S_ISDIR(st.st_mode)) {
998 std::string dst_dir = dst;
999
1000 // If the destination path existed originally, the source directory
1001 // should be copied as a child of the destination.
1002 if (dst_exists) {
1003 if (!dst_isdir) {
1004 sc.Error("target '%s' is not a directory", dst);
1005 return false;
1006 }
1007 // dst is a POSIX path, so we don't want to use the sysdeps
1008 // helpers here.
1009 if (dst_dir.back() != '/') {
1010 dst_dir.push_back('/');
1011 }
1012 dst_dir.append(android::base::Basename(src_path));
1013 }
1014
1015 success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false);
1016 continue;
1017 } else if (!should_push_file(st.st_mode)) {
1018 sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
1019 continue;
1020 }
1021
1022 std::string path_holder;
1023 if (dst_isdir) {
1024 // If we're copying a local file to a remote directory,
1025 // we really want to copy to remote_dir + "/" + local_filename.
1026 path_holder = dst_path;
1027 if (path_holder.back() != '/') {
1028 path_holder.push_back('/');
1029 }
1030 path_holder += android::base::Basename(src_path);
1031 dst_path = path_holder.c_str();
1032 }
1033
1034 sc.NewTransfer();
1035 sc.SetExpectedTotalBytes(st.st_size);
1036 success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync);
1037 sc.ReportTransferRate(src_path, TransferDirection::push);
1038 }
1039
1040 sc.ReportOverallTransferRate(TransferDirection::push);
1041 return success;
1042 }
1043
remote_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,const std::string & rpath,const std::string & lpath)1044 static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
1045 const std::string& rpath, const std::string& lpath) {
1046 std::vector<copyinfo> dirlist;
1047 std::vector<copyinfo> linklist;
1048
1049 // Add an entry for the current directory to ensure it gets created before pulling its contents.
1050 copyinfo ci(android::base::Dirname(lpath), android::base::Dirname(rpath),
1051 android::base::Basename(lpath), S_IFDIR);
1052 file_list->push_back(ci);
1053
1054 // Put the files/dirs in rpath on the lists.
1055 auto callback = [&](unsigned mode, unsigned size, unsigned time, const char* name) {
1056 if (IsDotOrDotDot(name)) {
1057 return;
1058 }
1059
1060 copyinfo ci(lpath, rpath, name, mode);
1061 if (S_ISDIR(mode)) {
1062 dirlist.push_back(ci);
1063 } else if (S_ISLNK(mode)) {
1064 linklist.push_back(ci);
1065 } else {
1066 if (!should_pull_file(ci.mode)) {
1067 sc.Warning("skipping special file '%s' (mode = 0o%o)", ci.rpath.c_str(), ci.mode);
1068 ci.skip = true;
1069 }
1070 ci.time = time;
1071 ci.size = size;
1072 file_list->push_back(ci);
1073 }
1074 };
1075
1076 if (!sync_ls(sc, rpath.c_str(), callback)) {
1077 return false;
1078 }
1079
1080 // Check each symlink we found to see whether it's a file or directory.
1081 for (copyinfo& link_ci : linklist) {
1082 struct stat st;
1083 if (!sync_stat_fallback(sc, link_ci.rpath.c_str(), &st)) {
1084 sc.Warning("stat failed for path %s: %s", link_ci.rpath.c_str(), strerror(errno));
1085 continue;
1086 }
1087
1088 if (S_ISDIR(st.st_mode)) {
1089 dirlist.emplace_back(std::move(link_ci));
1090 } else {
1091 file_list->emplace_back(std::move(link_ci));
1092 }
1093 }
1094
1095 // Recurse into each directory we found.
1096 while (!dirlist.empty()) {
1097 copyinfo current = dirlist.back();
1098 dirlist.pop_back();
1099 if (!remote_build_list(sc, file_list, current.rpath, current.lpath)) {
1100 return false;
1101 }
1102 }
1103
1104 return true;
1105 }
1106
set_time_and_mode(const std::string & lpath,time_t time,unsigned int mode)1107 static int set_time_and_mode(const std::string& lpath, time_t time,
1108 unsigned int mode) {
1109 struct utimbuf times = { time, time };
1110 int r1 = utime(lpath.c_str(), ×);
1111
1112 /* use umask for permissions */
1113 mode_t mask = umask(0000);
1114 umask(mask);
1115 int r2 = chmod(lpath.c_str(), mode & ~mask);
1116
1117 return r1 ? r1 : r2;
1118 }
1119
copy_remote_dir_local(SyncConnection & sc,std::string rpath,std::string lpath,bool copy_attrs)1120 static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath,
1121 std::string lpath, bool copy_attrs) {
1122 sc.NewTransfer();
1123
1124 // Make sure that both directory paths end in a slash.
1125 // Both paths are known to be nonempty, so we don't need to check.
1126 ensure_trailing_separators(lpath, rpath);
1127
1128 // Recursively build the list of files to copy.
1129 sc.Printf("pull: building file list...");
1130 std::vector<copyinfo> file_list;
1131 if (!remote_build_list(sc, &file_list, rpath, lpath)) {
1132 return false;
1133 }
1134
1135 sc.ComputeExpectedTotalBytes(file_list);
1136
1137 int skipped = 0;
1138 for (const copyinfo &ci : file_list) {
1139 if (!ci.skip) {
1140 if (S_ISDIR(ci.mode)) {
1141 // Entry is for an empty directory, create it and continue.
1142 // TODO(b/25457350): We don't preserve permissions on directories.
1143 if (!mkdirs(ci.lpath)) {
1144 sc.Error("failed to create directory '%s': %s",
1145 ci.lpath.c_str(), strerror(errno));
1146 return false;
1147 }
1148 continue;
1149 }
1150
1151 if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size)) {
1152 return false;
1153 }
1154
1155 if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
1156 return false;
1157 }
1158 } else {
1159 skipped++;
1160 }
1161 }
1162
1163 sc.RecordFilesSkipped(skipped);
1164 sc.ReportTransferRate(rpath, TransferDirection::pull);
1165 return true;
1166 }
1167
do_sync_pull(const std::vector<const char * > & srcs,const char * dst,bool copy_attrs,const char * name)1168 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
1169 bool copy_attrs, const char* name) {
1170 SyncConnection sc;
1171 if (!sc.IsValid()) return false;
1172
1173 bool success = true;
1174 struct stat st;
1175 bool dst_exists = true;
1176
1177 if (stat(dst, &st) == -1) {
1178 dst_exists = false;
1179
1180 // If we're only pulling one path, the destination path might point to
1181 // a path that doesn't exist yet.
1182 if (srcs.size() == 1 && errno == ENOENT) {
1183 // However, its parent must exist.
1184 struct stat parent_st;
1185 if (stat(android::base::Dirname(dst).c_str(), &parent_st) == -1) {
1186 sc.Error("cannot create file/directory '%s': %s", dst, strerror(errno));
1187 return false;
1188 }
1189 } else {
1190 sc.Error("failed to access '%s': %s", dst, strerror(errno));
1191 return false;
1192 }
1193 }
1194
1195 bool dst_isdir = dst_exists && S_ISDIR(st.st_mode);
1196 if (!dst_isdir) {
1197 if (srcs.size() > 1) {
1198 sc.Error("target '%s' is not a directory", dst);
1199 return false;
1200 } else {
1201 size_t dst_len = strlen(dst);
1202
1203 // A path that ends with a slash doesn't have to be a directory if
1204 // it doesn't exist yet.
1205 if (adb_is_separator(dst[dst_len - 1]) && dst_exists) {
1206 sc.Error("failed to access '%s': Not a directory", dst);
1207 return false;
1208 }
1209 }
1210 }
1211
1212 for (const char* src_path : srcs) {
1213 const char* dst_path = dst;
1214 struct stat src_st;
1215 if (!sync_stat_fallback(sc, src_path, &src_st)) {
1216 if (errno == ENOPROTOOPT) {
1217 sc.Error("remote object '%s' does not exist", src_path);
1218 } else {
1219 sc.Error("failed to stat remote object '%s': %s", src_path, strerror(errno));
1220 }
1221
1222 success = false;
1223 continue;
1224 }
1225
1226 bool src_isdir = S_ISDIR(src_st.st_mode);
1227 if (src_isdir) {
1228 std::string dst_dir = dst;
1229
1230 // If the destination path existed originally, the source directory
1231 // should be copied as a child of the destination.
1232 if (dst_exists) {
1233 if (!dst_isdir) {
1234 sc.Error("target '%s' is not a directory", dst);
1235 return false;
1236 }
1237 if (!adb_is_separator(dst_dir.back())) {
1238 dst_dir.push_back(OS_PATH_SEPARATOR);
1239 }
1240 dst_dir.append(android::base::Basename(src_path));
1241 }
1242
1243 success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs);
1244 continue;
1245 } else if (!should_pull_file(src_st.st_mode)) {
1246 sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode);
1247 continue;
1248 }
1249
1250 std::string path_holder;
1251 if (dst_isdir) {
1252 // If we're copying a remote file to a local directory, we
1253 // really want to copy to local_dir + OS_PATH_SEPARATOR +
1254 // basename(remote).
1255 path_holder = android::base::StringPrintf("%s%c%s", dst_path, OS_PATH_SEPARATOR,
1256 android::base::Basename(src_path).c_str());
1257 dst_path = path_holder.c_str();
1258 }
1259
1260 sc.NewTransfer();
1261 sc.SetExpectedTotalBytes(src_st.st_size);
1262 if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size)) {
1263 success = false;
1264 continue;
1265 }
1266
1267 if (copy_attrs && set_time_and_mode(dst_path, src_st.st_mtime, src_st.st_mode) != 0) {
1268 success = false;
1269 continue;
1270 }
1271 sc.ReportTransferRate(src_path, TransferDirection::pull);
1272 }
1273
1274 sc.ReportOverallTransferRate(TransferDirection::pull);
1275 return success;
1276 }
1277
do_sync_sync(const std::string & lpath,const std::string & rpath,bool list_only)1278 bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
1279 SyncConnection sc;
1280 if (!sc.IsValid()) return false;
1281
1282 bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only);
1283 if (!list_only) {
1284 sc.ReportOverallTransferRate(TransferDirection::push);
1285 }
1286 return success;
1287 }
1288