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