file_sync_client.cpp revision 379612b1283c7289fbf21e1105b8bec9b0fed7ae
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
48struct syncsendbuf {
49    unsigned id;
50    unsigned size;
51    char data[SYNC_DATA_MAX];
52};
53
54static 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
63static bool should_pull_file(mode_t mode) {
64    return mode & (S_IFREG | S_IFBLK | S_IFCHR);
65}
66
67static 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
75struct 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
83    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
97class SyncConnection {
98  public:
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
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
131    bool IsValid() { return fd >= 0; }
132
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
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.
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
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
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
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
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
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
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
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
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
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
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
401    bool SendQuit() {
402        return SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
403    }
404
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
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
433typedef void (sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name);
434
435static 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
457static 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
471static 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
476static 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
521static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath) {
522    unsigned size = 0;
523    if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
524
525    if (!sc.SendRequest(ID_RECV, rpath)) return false;
526
527    adb_unlink(lpath);
528    int lfd = adb_creat(lpath, 0644);
529    if (lfd < 0) {
530        sc.Error("cannot create '%s': %s", lpath, strerror(errno));
531        return false;
532    }
533
534    uint64_t bytes_copied = 0;
535    while (true) {
536        syncmsg msg;
537        if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
538            adb_close(lfd);
539            adb_unlink(lpath);
540            return false;
541        }
542
543        if (msg.data.id == ID_DONE) break;
544
545        if (msg.data.id != ID_DATA) {
546            adb_close(lfd);
547            adb_unlink(lpath);
548            sc.ReportCopyFailure(rpath, lpath, msg);
549            return false;
550        }
551
552        if (msg.data.size > sc.max) {
553            sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
554            adb_close(lfd);
555            adb_unlink(lpath);
556            return false;
557        }
558
559        char buffer[SYNC_DATA_MAX];
560        if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
561            adb_close(lfd);
562            adb_unlink(lpath);
563            return false;
564        }
565
566        if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
567            sc.Error("cannot write '%s': %s", lpath, strerror(errno));
568            adb_close(lfd);
569            adb_unlink(lpath);
570            return false;
571        }
572
573        sc.total_bytes_ += msg.data.size;
574
575        bytes_copied += msg.data.size;
576
577        sc.ReportProgress(rpath, bytes_copied, size);
578    }
579
580    adb_close(lfd);
581    return true;
582}
583
584bool do_sync_ls(const char* path) {
585    SyncConnection sc;
586    if (!sc.IsValid()) return false;
587
588    return sync_ls(sc, path, [](unsigned mode, unsigned size, unsigned time,
589                                const char* name) {
590        printf("%08x %08x %08x %s\n", mode, size, time, name);
591    });
592}
593
594static bool IsDotOrDotDot(const char* name) {
595    return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
596}
597
598static bool local_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
599                             const std::string& lpath,
600                             const std::string& rpath) {
601    std::vector<copyinfo> dirlist;
602    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(lpath.c_str()), closedir);
603    if (!dir) {
604        sc.Error("cannot open '%s': %s", lpath.c_str(), strerror(errno));
605        return false;
606    }
607
608    bool empty_dir = true;
609    dirent* de;
610    while ((de = readdir(dir.get()))) {
611        if (IsDotOrDotDot(de->d_name)) {
612            continue;
613        }
614
615        empty_dir = false;
616        std::string stat_path = lpath + de->d_name;
617
618        struct stat st;
619        if (lstat(stat_path.c_str(), &st) == -1) {
620            sc.Error("cannot lstat '%s': %s", stat_path.c_str(),
621                     strerror(errno));
622            continue;
623        }
624
625        copyinfo ci(lpath, rpath, de->d_name, st.st_mode);
626        if (S_ISDIR(st.st_mode)) {
627            dirlist.push_back(ci);
628        } else {
629            if (!should_push_file(st.st_mode)) {
630                sc.Warning("skipping special file '%s' (mode = 0o%o)", lpath.c_str(), st.st_mode);
631                ci.skip = true;
632            }
633            ci.time = st.st_mtime;
634            ci.size = st.st_size;
635            file_list->push_back(ci);
636        }
637    }
638
639    // Close this directory and recurse.
640    dir.reset();
641
642    // Add the current directory to the list if it was empty, to ensure that
643    // it gets created.
644    if (empty_dir) {
645        // TODO(b/25566053): Make pushing empty directories work.
646        // TODO(b/25457350): We don't preserve permissions on directories.
647        sc.Warning("skipping empty directory '%s'", lpath.c_str());
648        copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(lpath), S_IFDIR);
649        ci.skip = true;
650        file_list->push_back(ci);
651        return true;
652    }
653
654    for (const copyinfo& ci : dirlist) {
655        local_build_list(sc, file_list, ci.lpath, ci.rpath);
656    }
657
658    return true;
659}
660
661static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
662                                  std::string rpath, bool check_timestamps,
663                                  bool list_only) {
664    // Make sure that both directory paths end in a slash.
665    // Both paths are known to be nonempty, so we don't need to check.
666    ensure_trailing_separators(lpath, rpath);
667
668    // Recursively build the list of files to copy.
669    std::vector<copyinfo> file_list;
670    int pushed = 0;
671    int skipped = 0;
672    if (!local_build_list(sc, &file_list, lpath, rpath)) {
673        return false;
674    }
675
676    if (check_timestamps) {
677        for (const copyinfo& ci : file_list) {
678            if (!sc.SendRequest(ID_STAT, ci.rpath.c_str())) {
679                return false;
680            }
681        }
682        for (copyinfo& ci : file_list) {
683            unsigned int timestamp, mode, size;
684            if (!sync_finish_stat(sc, &timestamp, &mode, &size)) {
685                return false;
686            }
687            if (size == ci.size) {
688                // For links, we cannot update the atime/mtime.
689                if ((S_ISREG(ci.mode & mode) && timestamp == ci.time) ||
690                        (S_ISLNK(ci.mode & mode) && timestamp >= ci.time)) {
691                    ci.skip = true;
692                }
693            }
694        }
695    }
696
697    sc.ComputeExpectedTotalBytes(file_list);
698
699    for (const copyinfo& ci : file_list) {
700        if (!ci.skip) {
701            if (list_only) {
702                sc.Error("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
703            } else {
704                if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time, ci.mode)) {
705                    return false;
706                }
707            }
708            pushed++;
709        } else {
710            skipped++;
711        }
712    }
713
714    sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(),
715              pushed, (pushed == 1) ? "" : "s", skipped,
716              (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
717    return true;
718}
719
720bool do_sync_push(const std::vector<const char*>& srcs, const char* dst) {
721    SyncConnection sc;
722    if (!sc.IsValid()) return false;
723
724    bool success = true;
725    unsigned dst_mode;
726    if (!sync_stat(sc, dst, nullptr, &dst_mode, nullptr)) return false;
727    bool dst_exists = (dst_mode != 0);
728    bool dst_isdir = S_ISDIR(dst_mode);
729
730    if (!dst_isdir) {
731        if (srcs.size() > 1) {
732            sc.Error("target '%s' is not a directory", dst);
733            return false;
734        } else {
735            size_t dst_len = strlen(dst);
736
737            // A path that ends with a slash doesn't have to be a directory if
738            // it doesn't exist yet.
739            if (dst[dst_len - 1] == '/' && dst_exists) {
740                sc.Error("failed to access '%s': Not a directory", dst);
741                return false;
742            }
743        }
744    }
745
746    for (const char* src_path : srcs) {
747        const char* dst_path = dst;
748        struct stat st;
749        if (stat(src_path, &st) == -1) {
750            sc.Error("cannot stat '%s': %s", src_path, strerror(errno));
751            success = false;
752            continue;
753        }
754
755        if (S_ISDIR(st.st_mode)) {
756            std::string dst_dir = dst;
757
758            // If the destination path existed originally, the source directory
759            // should be copied as a child of the destination.
760            if (dst_exists) {
761                if (!dst_isdir) {
762                    sc.Error("target '%s' is not a directory", dst);
763                    return false;
764                }
765                // dst is a POSIX path, so we don't want to use the sysdeps
766                // helpers here.
767                if (dst_dir.back() != '/') {
768                    dst_dir.push_back('/');
769                }
770                dst_dir.append(adb_basename(src_path));
771            }
772
773            success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(),
774                                             false, false);
775            continue;
776        } else if (!should_push_file(st.st_mode)) {
777            sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
778            continue;
779        }
780
781        std::string path_holder;
782        if (dst_isdir) {
783            // If we're copying a local file to a remote directory,
784            // we really want to copy to remote_dir + "/" + local_filename.
785            path_holder = dst_path;
786            if (path_holder.back() != '/') {
787                path_holder.push_back('/');
788            }
789            path_holder += adb_basename(src_path);
790            dst_path = path_holder.c_str();
791        }
792        sc.SetExpectedTotalBytes(st.st_size);
793        success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode);
794    }
795
796    return success;
797}
798
799static bool remote_symlink_isdir(SyncConnection& sc, const std::string& rpath) {
800    unsigned mode;
801    std::string dir_path = rpath;
802    dir_path.push_back('/');
803    if (!sync_stat(sc, dir_path.c_str(), nullptr, &mode, nullptr)) {
804        sc.Error("failed to stat remote symlink '%s'", dir_path.c_str());
805        return false;
806    }
807    return S_ISDIR(mode);
808}
809
810static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
811                              const std::string& rpath, const std::string& lpath) {
812    std::vector<copyinfo> dirlist;
813    std::vector<copyinfo> linklist;
814
815    // Add an entry for the current directory to ensure it gets created before pulling its contents.
816    copyinfo ci(adb_dirname(lpath), adb_dirname(rpath), adb_basename(lpath), S_IFDIR);
817    file_list->push_back(ci);
818
819    // Put the files/dirs in rpath on the lists.
820    auto callback = [&](unsigned mode, unsigned size, unsigned time, const char* name) {
821        if (IsDotOrDotDot(name)) {
822            return;
823        }
824
825        copyinfo ci(lpath, rpath, name, mode);
826        if (S_ISDIR(mode)) {
827            dirlist.push_back(ci);
828        } else if (S_ISLNK(mode)) {
829            linklist.push_back(ci);
830        } else {
831            if (!should_pull_file(ci.mode)) {
832                sc.Warning("skipping special file '%s' (mode = 0o%o)", ci.rpath.c_str(), ci.mode);
833                ci.skip = true;
834            }
835            ci.time = time;
836            ci.size = size;
837            file_list->push_back(ci);
838        }
839    };
840
841    if (!sync_ls(sc, rpath.c_str(), callback)) {
842        return false;
843    }
844
845    // Check each symlink we found to see whether it's a file or directory.
846    for (copyinfo& link_ci : linklist) {
847        if (remote_symlink_isdir(sc, link_ci.rpath)) {
848            dirlist.emplace_back(std::move(link_ci));
849        } else {
850            file_list->emplace_back(std::move(link_ci));
851        }
852    }
853
854    // Recurse into each directory we found.
855    while (!dirlist.empty()) {
856        copyinfo current = dirlist.back();
857        dirlist.pop_back();
858        if (!remote_build_list(sc, file_list, current.rpath, current.lpath)) {
859            return false;
860        }
861    }
862
863    return true;
864}
865
866static int set_time_and_mode(const std::string& lpath, time_t time,
867                             unsigned int mode) {
868    struct utimbuf times = { time, time };
869    int r1 = utime(lpath.c_str(), &times);
870
871    /* use umask for permissions */
872    mode_t mask = umask(0000);
873    umask(mask);
874    int r2 = chmod(lpath.c_str(), mode & ~mask);
875
876    return r1 ? r1 : r2;
877}
878
879static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath,
880                                  std::string lpath, bool copy_attrs) {
881    // Make sure that both directory paths end in a slash.
882    // Both paths are known to be nonempty, so we don't need to check.
883    ensure_trailing_separators(lpath, rpath);
884
885    // Recursively build the list of files to copy.
886    sc.Printf("pull: building file list...");
887    std::vector<copyinfo> file_list;
888    if (!remote_build_list(sc, &file_list, rpath.c_str(), lpath.c_str())) {
889        return false;
890    }
891
892    sc.ComputeExpectedTotalBytes(file_list);
893
894    int pulled = 0;
895    int skipped = 0;
896    for (const copyinfo &ci : file_list) {
897        if (!ci.skip) {
898            if (S_ISDIR(ci.mode)) {
899                // Entry is for an empty directory, create it and continue.
900                // TODO(b/25457350): We don't preserve permissions on directories.
901                if (!mkdirs(ci.lpath))  {
902                    sc.Error("failed to create directory '%s': %s",
903                             ci.lpath.c_str(), strerror(errno));
904                    return false;
905                }
906                pulled++;
907                continue;
908            }
909
910            if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str())) {
911                return false;
912            }
913
914            if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
915                return false;
916            }
917            pulled++;
918        } else {
919            skipped++;
920        }
921    }
922
923    sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(),
924              pulled, (pulled == 1) ? "" : "s", skipped,
925              (skipped == 1) ? "" : "s", sc.TransferRate().c_str());
926    return true;
927}
928
929bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst,
930                  bool copy_attrs) {
931    SyncConnection sc;
932    if (!sc.IsValid()) return false;
933
934    bool success = true;
935    struct stat st;
936    bool dst_exists = true;
937
938    if (stat(dst, &st) == -1) {
939        dst_exists = false;
940
941        // If we're only pulling one path, the destination path might point to
942        // a path that doesn't exist yet.
943        if (srcs.size() == 1 && errno == ENOENT) {
944            // However, its parent must exist.
945            struct stat parent_st;
946            if (stat(adb_dirname(dst).c_str(), &parent_st) == -1) {
947                sc.Error("cannot create file/directory '%s': %s", dst, strerror(errno));
948                return false;
949            }
950        } else {
951            sc.Error("failed to access '%s': %s", dst, strerror(errno));
952            return false;
953        }
954    }
955
956    bool dst_isdir = dst_exists && S_ISDIR(st.st_mode);
957    if (!dst_isdir) {
958        if (srcs.size() > 1) {
959            sc.Error("target '%s' is not a directory", dst);
960            return false;
961        } else {
962            size_t dst_len = strlen(dst);
963
964            // A path that ends with a slash doesn't have to be a directory if
965            // it doesn't exist yet.
966            if (adb_is_separator(dst[dst_len - 1]) && dst_exists) {
967                sc.Error("failed to access '%s': Not a directory", dst);
968                return false;
969            }
970        }
971    }
972
973    for (const char* src_path : srcs) {
974        const char* dst_path = dst;
975        unsigned src_mode, src_time, src_size;
976        if (!sync_stat(sc, src_path, &src_time, &src_mode, &src_size)) {
977            sc.Error("failed to stat remote object '%s'", src_path);
978            return false;
979        }
980        if (src_mode == 0) {
981            sc.Error("remote object '%s' does not exist", src_path);
982            success = false;
983            continue;
984        }
985
986        bool src_isdir = S_ISDIR(src_mode);
987        if (S_ISLNK(src_mode)) {
988            src_isdir = remote_symlink_isdir(sc, src_path);
989        }
990
991        if (src_isdir) {
992            std::string dst_dir = dst;
993
994            // If the destination path existed originally, the source directory
995            // should be copied as a child of the destination.
996            if (dst_exists) {
997                if (!dst_isdir) {
998                    sc.Error("target '%s' is not a directory", dst);
999                    return false;
1000                }
1001                if (!adb_is_separator(dst_dir.back())) {
1002                    dst_dir.push_back(OS_PATH_SEPARATOR);
1003                }
1004                dst_dir.append(adb_basename(src_path));
1005            }
1006
1007            success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(), copy_attrs);
1008            continue;
1009        } else if (!should_pull_file(src_mode)) {
1010            sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_mode);
1011            continue;
1012        }
1013
1014        std::string path_holder;
1015        if (dst_isdir) {
1016            // If we're copying a remote file to a local directory, we
1017            // really want to copy to local_dir + OS_PATH_SEPARATOR +
1018            // basename(remote).
1019            path_holder = android::base::StringPrintf("%s%c%s", dst_path, OS_PATH_SEPARATOR,
1020                                                      adb_basename(src_path).c_str());
1021            dst_path = path_holder.c_str();
1022        }
1023
1024        sc.SetExpectedTotalBytes(src_size);
1025        if (!sync_recv(sc, src_path, dst_path)) {
1026            success = false;
1027            continue;
1028        }
1029
1030        if (copy_attrs && set_time_and_mode(dst_path, src_time, src_mode) != 0) {
1031            success = false;
1032            continue;
1033        }
1034    }
1035
1036    return success;
1037}
1038
1039bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
1040    SyncConnection sc;
1041    if (!sc.IsValid()) return false;
1042
1043    return copy_local_dir_remote(sc, lpath, rpath, true, list_only);
1044}
1045