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 <dirent.h>
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.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 <functional>
32 #include <memory>
33 #include <vector>
34 
35 #include "sysdeps.h"
36 
37 #include "adb.h"
38 #include "adb_client.h"
39 #include "adb_io.h"
40 #include "adb_utils.h"
41 #include "file_sync_service.h"
42 #include "line_printer.h"
43 
44 #include <android-base/file.h>
45 #include <android-base/strings.h>
46 #include <android-base/stringprintf.h>
47 
48 struct syncsendbuf {
49     unsigned id;
50     unsigned size;
51     char data[SYNC_DATA_MAX];
52 };
53 
ensure_trailing_separators(std::string & local_path,std::string & remote_path)54 static void ensure_trailing_separators(std::string& local_path, std::string& remote_path) {
55     if (!adb_is_separator(local_path.back())) {
56         local_path.push_back(OS_PATH_SEPARATOR);
57     }
58     if (remote_path.back() != '/') {
59         remote_path.push_back('/');
60     }
61 }
62 
should_pull_file(mode_t mode)63 static bool should_pull_file(mode_t mode) {
64     return mode & (S_IFREG | S_IFBLK | S_IFCHR);
65 }
66 
should_push_file(mode_t mode)67 static bool should_push_file(mode_t mode) {
68     mode_t mask = S_IFREG;
69 #if !defined(_WIN32)
70     mask |= S_IFLNK;
71 #endif
72     return mode & mask;
73 }
74 
75 struct copyinfo {
76     std::string lpath;
77     std::string rpath;
78     unsigned int time = 0;
79     unsigned int mode;
80     uint64_t size = 0;
81     bool skip = false;
82 
copyinfocopyinfo83     copyinfo(const std::string& local_path,
84              const std::string& remote_path,
85              const std::string& name,
86              unsigned int mode)
87             : lpath(local_path), rpath(remote_path), mode(mode) {
88         ensure_trailing_separators(lpath, rpath);
89         lpath.append(name);
90         rpath.append(name);
91         if (S_ISDIR(mode)) {
92             ensure_trailing_separators(lpath, rpath);
93         }
94     }
95 };
96 
97 class SyncConnection {
98   public:
SyncConnection()99     SyncConnection()
100             : total_bytes_(0),
101               start_time_ms_(CurrentTimeMs()),
102               expected_total_bytes_(0),
103               expect_multiple_files_(false),
104               expect_done_(false) {
105         max = SYNC_DATA_MAX; // TODO: decide at runtime.
106 
107         std::string error;
108         fd = adb_connect("sync:", &error);
109         if (fd < 0) {
110             Error("connect failed: %s", error.c_str());
111         }
112     }
113 
~SyncConnection()114     ~SyncConnection() {
115         if (!IsValid()) return;
116 
117         if (SendQuit()) {
118             // We sent a quit command, so the server should be doing orderly
119             // shutdown soon. But if we encountered an error while we were using
120             // the connection, the server might still be sending data (before
121             // doing orderly shutdown), in which case we won't wait for all of
122             // the data nor the coming orderly shutdown. In the common success
123             // case, this will wait for the server to do orderly shutdown.
124             ReadOrderlyShutdown(fd);
125         }
126         adb_close(fd);
127 
128         line_printer_.KeepInfoLine();
129     }
130 
IsValid()131     bool IsValid() { return fd >= 0; }
132 
ReceivedError(const char * from,const char * to)133     bool ReceivedError(const char* from, const char* to) {
134         adb_pollfd pfd = {.fd = fd, .events = POLLIN};
135         int rc = adb_poll(&pfd, 1, 0);
136         if (rc < 0) {
137             Error("failed to poll: %s", strerror(errno));
138             return true;
139         }
140         return rc != 0;
141     }
142 
SendRequest(int id,const char * path_and_mode)143     bool SendRequest(int id, const char* path_and_mode) {
144         size_t path_length = strlen(path_and_mode);
145         if (path_length > 1024) {
146             Error("SendRequest failed: path too long: %zu", path_length);
147             errno = ENAMETOOLONG;
148             return false;
149         }
150 
151         // Sending header and payload in a single write makes a noticeable
152         // difference to "adb sync" performance.
153         std::vector<char> buf(sizeof(SyncRequest) + path_length);
154         SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
155         req->id = id;
156         req->path_length = path_length;
157         char* data = reinterpret_cast<char*>(req + 1);
158         memcpy(data, path_and_mode, path_length);
159 
160         return WriteFdExactly(fd, &buf[0], buf.size());
161     }
162 
163     // Sending header, payload, and footer in a single write makes a huge
164     // 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)165     bool SendSmallFile(const char* path_and_mode,
166                        const char* lpath, const char* rpath,
167                        unsigned mtime,
168                        const char* data, size_t data_length) {
169         size_t path_length = strlen(path_and_mode);
170         if (path_length > 1024) {
171             Error("SendSmallFile failed: path too long: %zu", path_length);
172             errno = ENAMETOOLONG;
173             return false;
174         }
175 
176         std::vector<char> buf(sizeof(SyncRequest) + path_length +
177                               sizeof(SyncRequest) + data_length +
178                               sizeof(SyncRequest));
179         char* p = &buf[0];
180 
181         SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
182         req_send->id = ID_SEND;
183         req_send->path_length = path_length;
184         p += sizeof(SyncRequest);
185         memcpy(p, path_and_mode, path_length);
186         p += path_length;
187 
188         SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p);
189         req_data->id = ID_DATA;
190         req_data->path_length = data_length;
191         p += sizeof(SyncRequest);
192         memcpy(p, data, data_length);
193         p += data_length;
194 
195         SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p);
196         req_done->id = ID_DONE;
197         req_done->path_length = mtime;
198         p += sizeof(SyncRequest);
199 
200         WriteOrDie(lpath, rpath, &buf[0], (p - &buf[0]));
201         expect_done_ = true;
202         total_bytes_ += data_length;
203         ReportProgress(rpath, data_length, data_length);
204         return true;
205     }
206 
SendLargeFile(const char * path_and_mode,const char * lpath,const char * rpath,unsigned mtime)207     bool SendLargeFile(const char* path_and_mode,
208                        const char* lpath, const char* rpath,
209                        unsigned mtime) {
210         if (!SendRequest(ID_SEND, path_and_mode)) {
211             Error("failed to send ID_SEND message '%s': %s", path_and_mode, strerror(errno));
212             return false;
213         }
214 
215         struct stat st;
216         if (stat(lpath, &st) == -1) {
217             Error("cannot stat '%s': %s", lpath, strerror(errno));
218             return false;
219         }
220 
221         uint64_t total_size = st.st_size;
222         uint64_t bytes_copied = 0;
223 
224         int lfd = adb_open(lpath, O_RDONLY);
225         if (lfd < 0) {
226             Error("opening '%s' locally failed: %s", lpath, strerror(errno));
227             return false;
228         }
229 
230         syncsendbuf sbuf;
231         sbuf.id = ID_DATA;
232         while (true) {
233             int bytes_read = adb_read(lfd, sbuf.data, max);
234             if (bytes_read == -1) {
235                 Error("reading '%s' locally failed: %s", lpath, strerror(errno));
236                 adb_close(lfd);
237                 return false;
238             } else if (bytes_read == 0) {
239                 break;
240             }
241 
242             sbuf.size = bytes_read;
243             WriteOrDie(lpath, rpath, &sbuf, sizeof(SyncRequest) + bytes_read);
244 
245             total_bytes_ += bytes_read;
246             bytes_copied += bytes_read;
247 
248             // Check to see if we've received an error from the other side.
249             if (ReceivedError(lpath, rpath)) {
250                 break;
251             }
252 
253             ReportProgress(rpath, bytes_copied, total_size);
254         }
255 
256         adb_close(lfd);
257 
258         syncmsg msg;
259         msg.data.id = ID_DONE;
260         msg.data.size = mtime;
261         expect_done_ = true;
262         return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
263     }
264 
CopyDone(const char * from,const char * to)265     bool CopyDone(const char* from, const char* to) {
266         syncmsg msg;
267         if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
268             Error("failed to copy '%s' to '%s': couldn't read from device", from, to);
269             return false;
270         }
271         if (msg.status.id == ID_OKAY) {
272             if (expect_done_) {
273                 expect_done_ = false;
274                 return true;
275             } else {
276                 Error("failed to copy '%s' to '%s': received premature success", from, to);
277                 return true;
278             }
279         }
280         if (msg.status.id != ID_FAIL) {
281             Error("failed to copy '%s' to '%s': unknown reason %d", from, to, msg.status.id);
282             return false;
283         }
284         return ReportCopyFailure(from, to, msg);
285     }
286 
ReportCopyFailure(const char * from,const char * to,const syncmsg & msg)287     bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
288         std::vector<char> buf(msg.status.msglen + 1);
289         if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
290             Error("failed to copy '%s' to '%s'; failed to read reason (!): %s",
291                   from, to, strerror(errno));
292             return false;
293         }
294         buf[msg.status.msglen] = 0;
295         Error("failed to copy '%s' to '%s': %s", from, to, &buf[0]);
296         return false;
297     }
298 
TransferRate()299     std::string TransferRate() {
300         uint64_t ms = CurrentTimeMs() - start_time_ms_;
301         if (total_bytes_ == 0 || ms == 0) return "";
302 
303         double s = static_cast<double>(ms) / 1000LL;
304         double rate = (static_cast<double>(total_bytes_) / s) / (1024*1024);
305         return android::base::StringPrintf(" %.1f MB/s (%" PRId64 " bytes in %.3fs)",
306                                            rate, total_bytes_, s);
307     }
308 
ReportProgress(const char * file,uint64_t file_copied_bytes,uint64_t file_total_bytes)309     void ReportProgress(const char* file, uint64_t file_copied_bytes, uint64_t file_total_bytes) {
310         char overall_percentage_str[5] = "?";
311         if (expected_total_bytes_ != 0) {
312             int overall_percentage = static_cast<int>(total_bytes_ * 100 / expected_total_bytes_);
313             // If we're pulling symbolic links, we'll pull the target of the link rather than
314             // just create a local link, and that will cause us to go over 100%.
315             if (overall_percentage <= 100) {
316                 snprintf(overall_percentage_str, sizeof(overall_percentage_str), "%d%%",
317                          overall_percentage);
318             }
319         }
320 
321         if (file_copied_bytes > file_total_bytes || file_total_bytes == 0) {
322             // This case can happen if we're racing against something that wrote to the file
323             // between our stat and our read, or if we're reading a magic file that lies about
324             // its size. Just show how much we've copied.
325             Printf("[%4s] %s: %" PRId64 "/?", overall_percentage_str, file, file_copied_bytes);
326         } else {
327             // If we're transferring multiple files, we want to know how far through the current
328             // file we are, as well as the overall percentage.
329             if (expect_multiple_files_) {
330                 int file_percentage = static_cast<int>(file_copied_bytes * 100 / file_total_bytes);
331                 Printf("[%4s] %s: %d%%", overall_percentage_str, file, file_percentage);
332             } else {
333                 Printf("[%4s] %s", overall_percentage_str, file);
334             }
335         }
336     }
337 
Printf(const char * fmt,...)338     void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
339         std::string s;
340 
341         va_list ap;
342         va_start(ap, fmt);
343         android::base::StringAppendV(&s, fmt, ap);
344         va_end(ap);
345 
346         line_printer_.Print(s, LinePrinter::INFO);
347     }
348 
Error(const char * fmt,...)349     void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
350         std::string s = "adb: error: ";
351 
352         va_list ap;
353         va_start(ap, fmt);
354         android::base::StringAppendV(&s, fmt, ap);
355         va_end(ap);
356 
357         line_printer_.Print(s, LinePrinter::ERROR);
358     }
359 
Warning(const char * fmt,...)360     void Warning(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
361         std::string s = "adb: warning: ";
362 
363         va_list ap;
364         va_start(ap, fmt);
365         android::base::StringAppendV(&s, fmt, ap);
366         va_end(ap);
367 
368         line_printer_.Print(s, LinePrinter::WARNING);
369     }
370 
ComputeExpectedTotalBytes(const std::vector<copyinfo> & file_list)371     void ComputeExpectedTotalBytes(const std::vector<copyinfo>& file_list) {
372         expected_total_bytes_ = 0;
373         for (const copyinfo& ci : file_list) {
374             // Unfortunately, this doesn't work for symbolic links, because we'll copy the
375             // target of the link rather than just creating a link. (But ci.size is the link size.)
376             if (!ci.skip) expected_total_bytes_ += ci.size;
377         }
378         expect_multiple_files_ = true;
379     }
380 
SetExpectedTotalBytes(uint64_t expected_total_bytes)381     void SetExpectedTotalBytes(uint64_t expected_total_bytes) {
382         expected_total_bytes_ = expected_total_bytes;
383         expect_multiple_files_ = false;
384     }
385 
386     uint64_t total_bytes_;
387 
388     // TODO: add a char[max] buffer here, to replace syncsendbuf...
389     int fd;
390     size_t max;
391 
392   private:
393     uint64_t start_time_ms_;
394 
395     uint64_t expected_total_bytes_;
396     bool expect_multiple_files_;
397     bool expect_done_;
398 
399     LinePrinter line_printer_;
400 
SendQuit()401     bool SendQuit() {
402         return SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
403     }
404 
WriteOrDie(const char * from,const char * to,const void * data,size_t data_length)405     bool WriteOrDie(const char* from, const char* to, const void* data, size_t data_length) {
406         if (!WriteFdExactly(fd, data, data_length)) {
407             if (errno == ECONNRESET) {
408                 // Assume adbd told us why it was closing the connection, and
409                 // try to read failure reason from adbd.
410                 syncmsg msg;
411                 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
412                     Error("failed to copy '%s' to '%s': no response: %s", from, to, strerror(errno));
413                 } else if (msg.status.id != ID_FAIL) {
414                     Error("failed to copy '%s' to '%s': not ID_FAIL: %d", from, to, msg.status.id);
415                 } else {
416                     ReportCopyFailure(from, to, msg);
417                 }
418             } else {
419                 Error("%zu-byte write failed: %s", data_length, strerror(errno));
420             }
421             _exit(1);
422         }
423         return true;
424     }
425 
CurrentTimeMs()426     static uint64_t CurrentTimeMs() {
427         struct timeval tv;
428         gettimeofday(&tv, 0); // (Not clock_gettime because of Mac/Windows.)
429         return static_cast<uint64_t>(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
430     }
431 };
432 
433 typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
434 
sync_ls(SyncConnection & sc,const char * path,std::function<sync_ls_cb> func)435 static bool sync_ls(SyncConnection& sc, const char* path,
436                     std::function<sync_ls_cb> func) {
437     if (!sc.SendRequest(ID_LIST, path)) return false;
438 
439     while (true) {
440         syncmsg msg;
441         if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false;
442 
443         if (msg.dent.id == ID_DONE) return true;
444         if (msg.dent.id != ID_DENT) return false;
445 
446         size_t len = msg.dent.namelen;
447         if (len > 256) return false; // TODO: resize buffer? continue?
448 
449         char buf[257];
450         if (!ReadFdExactly(sc.fd, buf, len)) return false;
451         buf[len] = 0;
452 
453         func(msg.dent.mode, msg.dent.size, msg.dent.time, buf);
454     }
455 }
456 
sync_finish_stat(SyncConnection & sc,unsigned int * timestamp,unsigned int * mode,unsigned int * size)457 static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
458                              unsigned int* mode, unsigned int* size) {
459     syncmsg msg;
460     if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) {
461         return false;
462     }
463 
464     if (timestamp) *timestamp = msg.stat.time;
465     if (mode) *mode = msg.stat.mode;
466     if (size) *size = msg.stat.size;
467 
468     return true;
469 }
470 
sync_stat(SyncConnection & sc,const char * path,unsigned int * timestamp,unsigned int * mode,unsigned int * size)471 static bool sync_stat(SyncConnection& sc, const char* path,
472                       unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
473     return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
474 }
475 
sync_send(SyncConnection & sc,const char * lpath,const char * rpath,unsigned mtime,mode_t mode)476 static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
477                       unsigned mtime, mode_t mode)
478 {
479     std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
480 
481     if (S_ISLNK(mode)) {
482 #if !defined(_WIN32)
483         char buf[PATH_MAX];
484         ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
485         if (data_length == -1) {
486             sc.Error("readlink '%s' failed: %s", lpath, strerror(errno));
487             return false;
488         }
489         buf[data_length++] = '\0';
490 
491         if (!sc.SendSmallFile(path_and_mode.c_str(), lpath, rpath, mtime, buf, data_length)) {
492             return false;
493         }
494         return sc.CopyDone(lpath, rpath);
495 #endif
496     }
497 
498     struct stat st;
499     if (stat(lpath, &st) == -1) {
500         sc.Error("failed to stat local file '%s': %s", lpath, strerror(errno));
501         return false;
502     }
503     if (st.st_size < SYNC_DATA_MAX) {
504         std::string data;
505         if (!android::base::ReadFileToString(lpath, &data)) {
506             sc.Error("failed to read all of '%s': %s", lpath, strerror(errno));
507             return false;
508         }
509         if (!sc.SendSmallFile(path_and_mode.c_str(), lpath, rpath, mtime,
510                               data.data(), data.size())) {
511             return false;
512         }
513     } else {
514         if (!sc.SendLargeFile(path_and_mode.c_str(), lpath, rpath, mtime)) {
515             return false;
516         }
517     }
518     return sc.CopyDone(lpath, rpath);
519 }
520 
sync_recv(SyncConnection & sc,const char * rpath,const char * lpath,const char * name=nullptr)521 static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
522                       const char* name=nullptr) {
523     unsigned size = 0;
524     if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
525 
526     if (!sc.SendRequest(ID_RECV, rpath)) return false;
527 
528     adb_unlink(lpath);
529     int lfd = adb_creat(lpath, 0644);
530     if (lfd < 0) {
531         sc.Error("cannot create '%s': %s", lpath, strerror(errno));
532         return false;
533     }
534 
535     uint64_t bytes_copied = 0;
536     while (true) {
537         syncmsg msg;
538         if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
539             adb_close(lfd);
540             adb_unlink(lpath);
541             return false;
542         }
543 
544         if (msg.data.id == ID_DONE) break;
545 
546         if (msg.data.id != ID_DATA) {
547             adb_close(lfd);
548             adb_unlink(lpath);
549             sc.ReportCopyFailure(rpath, lpath, msg);
550             return false;
551         }
552 
553         if (msg.data.size > sc.max) {
554             sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
555             adb_close(lfd);
556             adb_unlink(lpath);
557             return false;
558         }
559 
560         char buffer[SYNC_DATA_MAX];
561         if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
562             adb_close(lfd);
563             adb_unlink(lpath);
564             return false;
565         }
566 
567         if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
568             sc.Error("cannot write '%s': %s", lpath, strerror(errno));
569             adb_close(lfd);
570             adb_unlink(lpath);
571             return false;
572         }
573 
574         sc.total_bytes_ += msg.data.size;
575 
576         bytes_copied += msg.data.size;
577 
578         sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, size);
579     }
580 
581     adb_close(lfd);
582     return true;
583 }
584 
do_sync_ls(const char * path)585 bool do_sync_ls(const char* path) {
586     SyncConnection sc;
587     if (!sc.IsValid()) return false;
588 
589     return sync_ls(sc, path, [](unsigned mode, unsigned size, unsigned time,
590                                 const char* name) {
591         printf("%08x %08x %08x %s\n", mode, size, time, name);
592     });
593 }
594 
IsDotOrDotDot(const char * name)595 static bool IsDotOrDotDot(const char* name) {
596     return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
597 }
598 
local_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,const std::string & lpath,const std::string & rpath)599 static bool local_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
600                              const std::string& lpath,
601                              const std::string& rpath) {
602     std::vector<copyinfo> dirlist;
603     std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(lpath.c_str()), closedir);
604     if (!dir) {
605         sc.Error("cannot open '%s': %s", lpath.c_str(), strerror(errno));
606         return false;
607     }
608 
609     bool empty_dir = true;
610     dirent* de;
611     while ((de = readdir(dir.get()))) {
612         if (IsDotOrDotDot(de->d_name)) {
613             continue;
614         }
615 
616         empty_dir = false;
617         std::string stat_path = lpath + de->d_name;
618 
619         struct stat st;
620         if (lstat(stat_path.c_str(), &st) == -1) {
621             sc.Error("cannot lstat '%s': %s", stat_path.c_str(),
622                      strerror(errno));
623             continue;
624         }
625 
626         copyinfo ci(lpath, rpath, de->d_name, st.st_mode);
627         if (S_ISDIR(st.st_mode)) {
628             dirlist.push_back(ci);
629         } else {
630             if (!should_push_file(st.st_mode)) {
631                 sc.Warning("skipping special file '%s' (mode = 0o%o)", lpath.c_str(), st.st_mode);
632                 ci.skip = true;
633             }
634             ci.time = st.st_mtime;
635             ci.size = st.st_size;
636             file_list->push_back(ci);
637         }
638     }
639 
640     // Close this directory and recurse.
641     dir.reset();
642 
643     // Add the current directory to the list if it was empty, to ensure that
644     // it gets created.
645     if (empty_dir) {
646         // TODO(b/25566053): Make pushing empty directories work.
647         // TODO(b/25457350): We don't preserve permissions on directories.
648         sc.Warning("skipping empty directory '%s'", lpath.c_str());
649         copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(lpath), S_IFDIR);
650         ci.skip = true;
651         file_list->push_back(ci);
652         return true;
653     }
654 
655     for (const copyinfo& ci : dirlist) {
656         local_build_list(sc, file_list, ci.lpath, ci.rpath);
657     }
658 
659     return true;
660 }
661 
copy_local_dir_remote(SyncConnection & sc,std::string lpath,std::string rpath,bool check_timestamps,bool list_only)662 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
663                                   std::string rpath, bool check_timestamps,
664                                   bool list_only) {
665     // Make sure that both directory paths end in a slash.
666     // Both paths are known to be nonempty, so we don't need to check.
667     ensure_trailing_separators(lpath, rpath);
668 
669     // Recursively build the list of files to copy.
670     std::vector<copyinfo> file_list;
671     int pushed = 0;
672     int skipped = 0;
673     if (!local_build_list(sc, &file_list, lpath, rpath)) {
674         return false;
675     }
676 
677     if (check_timestamps) {
678         for (const copyinfo& ci : file_list) {
679             if (!sc.SendRequest(ID_STAT, ci.rpath.c_str())) {
680                 return false;
681             }
682         }
683         for (copyinfo& ci : file_list) {
684             unsigned int timestamp, mode, size;
685             if (!sync_finish_stat(sc, &timestamp, &mode, &size)) {
686                 return false;
687             }
688             if (size == ci.size) {
689                 // For links, we cannot update the atime/mtime.
690                 if ((S_ISREG(ci.mode & mode) && timestamp == ci.time) ||
691                         (S_ISLNK(ci.mode & mode) && timestamp >= ci.time)) {
692                     ci.skip = true;
693                 }
694             }
695         }
696     }
697 
698     sc.ComputeExpectedTotalBytes(file_list);
699 
700     for (const copyinfo& ci : file_list) {
701         if (!ci.skip) {
702             if (list_only) {
703                 sc.Error("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
704             } else {
705                 if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
706                     return false;
707                 }
708             }
709             pushed++;
710         } else {
711             skipped++;
712         }
713     }
714 
715     sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(),
716               pushed, (pushed == 1) ? "" : "s", skipped,
717               (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
718     return true;
719 }
720 
do_sync_push(const std::vector<const char * > & srcs,const char * dst)721 bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
722     SyncConnection sc;
723     if (!sc.IsValid()) return false;
724 
725     bool success = true;
726     unsigned dst_mode;
727     if (!sync_stat(sc, dst, nullptr, &dst_mode, nullptr)) return false;
728     bool dst_exists = (dst_mode != 0);
729     bool dst_isdir = S_ISDIR(dst_mode);
730 
731     if (!dst_isdir) {
732         if (srcs.size() > 1) {
733             sc.Error("target '%s' is not a directory", dst);
734             return false;
735         } else {
736             size_t dst_len = strlen(dst);
737 
738             // A path that ends with a slash doesn't have to be a directory if
739             // it doesn't exist yet.
740             if (dst[dst_len - 1] == '/' && dst_exists) {
741                 sc.Error("failed to access '%s': Not a directory", dst);
742                 return false;
743             }
744         }
745     }
746 
747     for (const char* src_path : srcs) {
748         const char* dst_path = dst;
749         struct stat st;
750         if (stat(src_path, &st) == -1) {
751             sc.Error("cannot stat '%s': %s", src_path, strerror(errno));
752             success = false;
753             continue;
754         }
755 
756         if (S_ISDIR(st.st_mode)) {
757             std::string dst_dir = dst;
758 
759             // If the destination path existed originally, the source directory
760             // should be copied as a child of the destination.
761             if (dst_exists) {
762                 if (!dst_isdir) {
763                     sc.Error("target '%s' is not a directory", dst);
764                     return false;
765                 }
766                 // dst is a POSIX path, so we don't want to use the sysdeps
767                 // helpers here.
768                 if (dst_dir.back() != '/') {
769                     dst_dir.push_back('/');
770                 }
771                 dst_dir.append(adb_basename(src_path));
772             }
773 
774             success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(),
775                                              false, false);
776             continue;
777         } else if (!should_push_file(st.st_mode)) {
778             sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
779             continue;
780         }
781 
782         std::string path_holder;
783         if (dst_isdir) {
784             // If we're copying a local file to a remote directory,
785             // we really want to copy to remote_dir + "/" + local_filename.
786             path_holder = dst_path;
787             if (path_holder.back() != '/') {
788                 path_holder.push_back('/');
789             }
790             path_holder += adb_basename(src_path);
791             dst_path = path_holder.c_str();
792         }
793         sc.SetExpectedTotalBytes(st.st_size);
794         success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
795     }
796 
797     return success;
798 }
799 
remote_symlink_isdir(SyncConnection & sc,const std::string & rpath)800 static bool remote_symlink_isdir(SyncConnection& sc, const std::string& rpath) {
801     unsigned mode;
802     std::string dir_path = rpath;
803     dir_path.push_back('/');
804     if (!sync_stat(sc, dir_path.c_str(), nullptr, &mode, nullptr)) {
805         sc.Error("failed to stat remote symlink '%s'", dir_path.c_str());
806         return false;
807     }
808     return S_ISDIR(mode);
809 }
810 
remote_build_list(SyncConnection & sc,std::vector<copyinfo> * file_list,const std::string & rpath,const std::string & lpath)811 static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
812                               const std::string& rpath, const std::string& lpath) {
813     std::vector<copyinfo> dirlist;
814     std::vector<copyinfo> linklist;
815 
816     // Add an entry for the current directory to ensure it gets created before pulling its contents.
817     copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(lpath), S_IFDIR);
818     file_list->push_back(ci);
819 
820     // Put the files/dirs in rpath on the lists.
821     auto callback = [&](unsigned mode, unsigned size, unsigned time, const char* name) {
822         if (IsDotOrDotDot(name)) {
823             return;
824         }
825 
826         copyinfo ci(lpath, rpath, name, mode);
827         if (S_ISDIR(mode)) {
828             dirlist.push_back(ci);
829         } else if (S_ISLNK(mode)) {
830             linklist.push_back(ci);
831         } else {
832             if (!should_pull_file(ci.mode)) {
833                 sc.Warning("skipping special file '%s' (mode = 0o%o)", ci.rpath.c_str(), ci.mode);
834                 ci.skip = true;
835             }
836             ci.time = time;
837             ci.size = size;
838             file_list->push_back(ci);
839         }
840     };
841 
842     if (!sync_ls(sc, rpath.c_str(), callback)) {
843         return false;
844     }
845 
846     // Check each symlink we found to see whether it's a file or directory.
847     for (copyinfo& link_ci : linklist) {
848         if (remote_symlink_isdir(sc, link_ci.rpath)) {
849             dirlist.emplace_back(std::move(link_ci));
850         } else {
851             file_list->emplace_back(std::move(link_ci));
852         }
853     }
854 
855     // Recurse into each directory we found.
856     while (!dirlist.empty()) {
857         copyinfo current = dirlist.back();
858         dirlist.pop_back();
859         if (!remote_build_list(sc, file_list, current.rpath, current.lpath)) {
860             return false;
861         }
862     }
863 
864     return true;
865 }
866 
set_time_and_mode(const std::string & lpath,time_t time,unsigned int mode)867 static int set_time_and_mode(const std::string& lpath, time_t time,
868                              unsigned int mode) {
869     struct utimbuf times = { time, time };
870     int r1 = utime(lpath.c_str(), &times);
871 
872     /* use umask for permissions */
873     mode_t mask = umask(0000);
874     umask(mask);
875     int r2 = chmod(lpath.c_str(), mode & ~mask);
876 
877     return r1 ? r1 : r2;
878 }
879 
copy_remote_dir_local(SyncConnection & sc,std::string rpath,std::string lpath,bool copy_attrs)880 static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath,
881                                   std::string lpath, bool copy_attrs) {
882     // Make sure that both directory paths end in a slash.
883     // Both paths are known to be nonempty, so we don't need to check.
884     ensure_trailing_separators(lpath, rpath);
885 
886     // Recursively build the list of files to copy.
887     sc.Printf("pull: building file list...");
888     std::vector<copyinfo> file_list;
889     if (!remote_build_list(sc, &file_list, rpath.c_str(), lpath.c_str())) {
890         return false;
891     }
892 
893     sc.ComputeExpectedTotalBytes(file_list);
894 
895     int pulled = 0;
896     int skipped = 0;
897     for (const copyinfo &ci : file_list) {
898         if (!ci.skip) {
899             if (S_ISDIR(ci.mode)) {
900                 // Entry is for an empty directory, create it and continue.
901                 // TODO(b/25457350): We don't preserve permissions on directories.
902                 if (!mkdirs(ci.lpath))  {
903                     sc.Error("failed to create directory '%s': %s",
904                              ci.lpath.c_str(), strerror(errno));
905                     return false;
906                 }
907                 pulled++;
908                 continue;
909             }
910 
911             if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str())) {
912                 return false;
913             }
914 
915             if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
916                 return false;
917             }
918             pulled++;
919         } else {
920             skipped++;
921         }
922     }
923 
924     sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(),
925               pulled, (pulled == 1) ? "" : "s", skipped,
926               (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
927     return true;
928 }
929 
do_sync_pull(const std::vector<const char * > & srcs,const char * dst,bool copy_attrs,const char * name)930 bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
931                   bool copy_attrs, const char* name) {
932     SyncConnection sc;
933     if (!sc.IsValid()) return false;
934 
935     bool success = true;
936     struct stat st;
937     bool dst_exists = true;
938 
939     if (stat(dst, &st) == -1) {
940         dst_exists = false;
941 
942         // If we're only pulling one path, the destination path might point to
943         // a path that doesn't exist yet.
944         if (srcs.size() == 1 && errno == ENOENT) {
945             // However, its parent must exist.
946             struct stat parent_st;
947             if (stat(adb_dirname(dst).c_str(), &parent_st) == -1) {
948                 sc.Error("cannot create file/directory '%s': %s", dst, strerror(errno));
949                 return false;
950             }
951         } else {
952             sc.Error("failed to access '%s': %s", dst, strerror(errno));
953             return false;
954         }
955     }
956 
957     bool dst_isdir = dst_exists && S_ISDIR(st.st_mode);
958     if (!dst_isdir) {
959         if (srcs.size() > 1) {
960             sc.Error("target '%s' is not a directory", dst);
961             return false;
962         } else {
963             size_t dst_len = strlen(dst);
964 
965             // A path that ends with a slash doesn't have to be a directory if
966             // it doesn't exist yet.
967             if (adb_is_separator(dst[dst_len - 1]) && dst_exists) {
968                 sc.Error("failed to access '%s': Not a directory", dst);
969                 return false;
970             }
971         }
972     }
973 
974     for (const char* src_path : srcs) {
975         const char* dst_path = dst;
976         unsigned src_mode, src_time, src_size;
977         if (!sync_stat(sc, src_path, &src_time, &src_mode, &src_size)) {
978             sc.Error("failed to stat remote object '%s'", src_path);
979             return false;
980         }
981         if (src_mode == 0) {
982             sc.Error("remote object '%s' does not exist", src_path);
983             success = false;
984             continue;
985         }
986 
987         bool src_isdir = S_ISDIR(src_mode);
988         if (S_ISLNK(src_mode)) {
989             src_isdir = remote_symlink_isdir(sc, src_path);
990         }
991 
992         if (src_isdir) {
993             std::string dst_dir = dst;
994 
995             // If the destination path existed originally, the source directory
996             // should be copied as a child of the destination.
997             if (dst_exists) {
998                 if (!dst_isdir) {
999                     sc.Error("target '%s' is not a directory", dst);
1000                     return false;
1001                 }
1002                 if (!adb_is_separator(dst_dir.back())) {
1003                     dst_dir.push_back(OS_PATH_SEPARATOR);
1004                 }
1005                 dst_dir.append(adb_basename(src_path));
1006             }
1007 
1008             success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(), copy_attrs);
1009             continue;
1010         } else if (!should_pull_file(src_mode)) {
1011             sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_mode);
1012             continue;
1013         }
1014 
1015         std::string path_holder;
1016         if (dst_isdir) {
1017             // If we're copying a remote file to a local directory, we
1018             // really want to copy to local_dir + OS_PATH_SEPARATOR +
1019             // basename(remote).
1020             path_holder = android::base::StringPrintf("%s%c%s", dst_path, OS_PATH_SEPARATOR,
1021                                                       adb_basename(src_path).c_str());
1022             dst_path = path_holder.c_str();
1023         }
1024 
1025         sc.SetExpectedTotalBytes(src_size);
1026         if (!sync_recv(sc, src_path, dst_path, name)) {
1027             success = false;
1028             continue;
1029         }
1030 
1031         if (copy_attrs && set_time_and_mode(dst_path, src_time, src_mode) != 0) {
1032             success = false;
1033             continue;
1034         }
1035     }
1036 
1037     return success;
1038 }
1039 
do_sync_sync(const std::string & lpath,const std::string & rpath,bool list_only)1040 bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
1041     SyncConnection sc;
1042     if (!sc.IsValid()) return false;
1043 
1044     return copy_local_dir_remote(sc, lpath, rpath, true, list_only);
1045 }
1046