Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b708d162 authored by Elliott Hughes's avatar Elliott Hughes
Browse files

Show transfer progress in adb sync/pull/push.

Change-Id: If5439877d060f9bab29cf84be996071cf680c2d4
parent bb51fbc4
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -213,12 +213,13 @@ LOCAL_STATIC_LIBRARIES_windows := AdbWinApi
LOCAL_REQUIRED_MODULES_windows := AdbWinApi AdbWinUsbApi

LOCAL_SRC_FILES := \
    adb_client.cpp \
    client/main.cpp \
    console.cpp \
    commandline.cpp \
    adb_client.cpp \
    services.cpp \
    file_sync_client.cpp \
    line_printer.cpp \
    services.cpp \
    shell_service_protocol.cpp \

LOCAL_CFLAGS += \
+10 −15
Original line number Diff line number Diff line
@@ -101,12 +101,10 @@ static void help() {
        "                                 will disconnect from all connected TCP/IP devices.\n"
        "\n"
        "device commands:\n"
        "  adb push [-p] <local> <remote>\n"
        "  adb push <local> <remote>\n"
        "                               - copy file/dir to device\n"
        "                                 ('-p' to display the transfer progress)\n"
        "  adb pull [-p] [-a] <remote> [<local>]\n"
        "  adb pull [-a] <remote> [<local>]\n"
        "                               - copy file/dir from device\n"
        "                                 ('-p' to display the transfer progress)\n"
        "                                 ('-a' means copy timestamp and mode)\n"
        "  adb sync [ <directory> ]     - copy host->device only if changed\n"
        "                                 (-l means list but don't copy)\n"
@@ -1065,15 +1063,14 @@ static std::string find_product_out_path(const std::string& hint) {
    return path;
}

static void parse_push_pull_args(const char **arg, int narg, char const **path1,
                                 char const **path2, bool* show_progress,
static void parse_push_pull_args(const char **arg, int narg,
                                 char const **path1, char const **path2,
                                 int *copy_attrs) {
    *show_progress = false;
    *copy_attrs = 0;

    while (narg > 0) {
        if (!strcmp(*arg, "-p")) {
            *show_progress = true;
            // Silently ignore for backwards compatibility.
        } else if (!strcmp(*arg, "-a")) {
            *copy_attrs = 1;
        } else {
@@ -1561,22 +1558,20 @@ int adb_commandline(int argc, const char **argv) {
        return do_sync_ls(argv[1]) ? 0 : 1;
    }
    else if (!strcmp(argv[0], "push")) {
        bool show_progress = false;
        int copy_attrs = 0;
        const char* lpath = NULL, *rpath = NULL;

        parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
        parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &copy_attrs);
        if (!lpath || !rpath || copy_attrs != 0) return usage();
        return do_sync_push(lpath, rpath, show_progress) ? 0 : 1;
        return do_sync_push(lpath, rpath) ? 0 : 1;
    }
    else if (!strcmp(argv[0], "pull")) {
        bool show_progress = false;
        int copy_attrs = 0;
        const char* rpath = NULL, *lpath = ".";

        parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
        parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &copy_attrs);
        if (!rpath) return usage();
        return do_sync_pull(rpath, lpath, show_progress, copy_attrs) ? 0 : 1;
        return do_sync_pull(rpath, lpath, copy_attrs) ? 0 : 1;
    }
    else if (!strcmp(argv[0], "install")) {
        if (argc < 2) return usage();
@@ -1768,7 +1763,7 @@ static int install_app(TransportType transport, const char* serial, int argc, co
    int result = -1;
    const char* apk_file = argv[last_apk];
    std::string apk_dest = android::base::StringPrintf(where, adb_basename(apk_file).c_str());
    if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
    if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
    argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
    result = pm_command(transport, serial, argc, argv);

+140 −123
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#include "adb_io.h"
#include "adb_utils.h"
#include "file_sync_service.h"
#include "line_printer.h"

#include <base/file.h>
#include <base/strings.h>
@@ -49,36 +50,15 @@ struct syncsendbuf {
    char data[SYNC_DATA_MAX];
};

static long long NOW() {
    struct timeval tv;
    gettimeofday(&tv, 0);
    return ((long long) tv.tv_usec) + 1000000LL * ((long long) tv.tv_sec);
}

static void print_transfer_progress(uint64_t bytes_current,
                                    uint64_t bytes_total) {
    if (bytes_total == 0) return;

    fprintf(stderr, "\rTransferring: %" PRIu64 "/%" PRIu64 " (%d%%)",
            bytes_current, bytes_total,
            (int) (bytes_current * 100 / bytes_total));

    if (bytes_current == bytes_total) {
        fputc('\n', stderr);
    }

    fflush(stderr);
}

class SyncConnection {
  public:
    SyncConnection() : total_bytes(0), start_time_(NOW()) {
    SyncConnection() : total_bytes(0), start_time_ms_(CurrentTimeMs()) {
        max = SYNC_DATA_MAX; // TODO: decide at runtime.

        std::string error;
        fd = adb_connect("sync:", &error);
        if (fd < 0) {
            fprintf(stderr, "adb: error: %s\n", error.c_str());
            Error("connect failed: %s", error.c_str());
        }
    }

@@ -86,7 +66,6 @@ class SyncConnection {
        if (!IsValid()) return;

        SendQuit();
        ShowTransferRate();
        adb_close(fd);
    }

@@ -95,7 +74,7 @@ class SyncConnection {
    bool SendRequest(int id, const char* path_and_mode) {
        size_t path_length = strlen(path_and_mode);
        if (path_length > 1024) {
            fprintf(stderr, "adb: SendRequest failed: path too long: %zu\n", path_length);
            Error("SendRequest failed: path too long: %zu", path_length);
            errno = ENAMETOOLONG;
            return false;
        }
@@ -115,11 +94,14 @@ class SyncConnection {
    // Sending header, payload, and footer in a single write makes a huge
    // difference to "adb sync" performance.
    bool SendSmallFile(const char* path_and_mode,
                       const char* rpath,
                       const char* data, size_t data_length,
                       unsigned mtime) {
        Print(rpath);

        size_t path_length = strlen(path_and_mode);
        if (path_length > 1024) {
            fprintf(stderr, "adb: SendSmallFile failed: path too long: %zu\n", path_length);
            Error("SendSmallFile failed: path too long: %zu", path_length);
            errno = ENAMETOOLONG;
            return false;
        }
@@ -157,16 +139,14 @@ class SyncConnection {
    bool CopyDone(const char* from, const char* to) {
        syncmsg msg;
        if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
            fprintf(stderr, "adb: failed to copy '%s' to '%s': no ID_DONE: %s\n",
                    from, to, strerror(errno));
            Error("failed to copy '%s' to '%s': no ID_DONE: %s", from, to, strerror(errno));
            return false;
        }
        if (msg.status.id == ID_OKAY) {
            return true;
        }
        if (msg.status.id != ID_FAIL) {
            fprintf(stderr, "adb: failed to copy '%s' to '%s': unknown reason %d\n",
                    from, to, msg.status.id);
            Error("failed to copy '%s' to '%s': unknown reason %d", from, to, msg.status.id);
            return false;
        }
        return ReportCopyFailure(from, to, msg);
@@ -175,15 +155,41 @@ class SyncConnection {
    bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
        std::vector<char> buf(msg.status.msglen + 1);
        if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
            fprintf(stderr, "adb: failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
            Error("failed to copy '%s' to '%s'; failed to read reason (!): %s",
                  from, to, strerror(errno));
            return false;
        }
        buf[msg.status.msglen] = 0;
        fprintf(stderr, "adb: failed to copy '%s' to '%s': %s\n", from, to, &buf[0]);
        Error("failed to copy '%s' to '%s': %s", from, to, &buf[0]);
        return false;
    }

    std::string TransferRate() {
        uint64_t ms = CurrentTimeMs() - start_time_ms_;
        if (total_bytes == 0 || ms == 0) return "";

        double s = static_cast<double>(ms) / 1000LL;
        double rate = (static_cast<double>(total_bytes) / s) / (1024*1024);
        return android::base::StringPrintf(" %.1f MB/s (%" PRId64 " bytes in %.3fs)",
                                           rate, total_bytes, s);
    }

    void Print(const std::string& s) {
        // TODO: we actually don't want ELIDE; we want "ELIDE if smart, FULL if dumb".
        line_printer_.Print(s, LinePrinter::ELIDE);
    }

    void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
        std::string s = "adb: error: ";

        va_list ap;
        va_start(ap, fmt);
        android::base::StringAppendV(&s, fmt, ap);
        va_end(ap);

        line_printer_.Print(s, LinePrinter::FULL);
    }

    uint64_t total_bytes;

    // TODO: add a char[max] buffer here, to replace syncsendbuf...
@@ -191,19 +197,18 @@ class SyncConnection {
    size_t max;

  private:
    uint64_t start_time_;
    uint64_t start_time_ms_;

    LinePrinter line_printer_;

    void SendQuit() {
        SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
    }

    void ShowTransferRate() {
        uint64_t t = NOW() - start_time_;
        if (total_bytes == 0 || t == 0) return;

        fprintf(stderr, "%lld KB/s (%" PRId64 " bytes in %lld.%03llds)\n",
                ((total_bytes * 1000000LL) / t) / 1024LL,
                total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
    static uint64_t CurrentTimeMs() {
        struct timeval tv;
        gettimeofday(&tv, 0); // (Not clock_gettime because of Mac/Windows.)
        return static_cast<uint64_t>(tv.tv_sec) * 1000 + tv.tv_usec / 1000;
    }
};

@@ -249,29 +254,26 @@ static bool sync_stat(SyncConnection& sc, const char* path,
    return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
}

static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const char* path,
                          unsigned mtime, bool show_progress) {
static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode,
                          const char* lpath, const char* rpath,
                          unsigned mtime) {
    if (!sc.SendRequest(ID_SEND, path_and_mode)) {
        fprintf(stderr, "adb: failed to send ID_SEND message '%s': %s\n",
                path_and_mode, strerror(errno));
        sc.Error("failed to send ID_SEND message '%s': %s", path_and_mode, strerror(errno));
        return false;
    }

    unsigned long long size = 0;
    if (show_progress) {
        // Determine local file size.
    struct stat st;
        if (stat(path, &st) == -1) {
            fprintf(stderr, "adb: cannot stat '%s': %s\n", path, strerror(errno));
    if (stat(lpath, &st) == -1) {
        sc.Error("cannot stat '%s': %s", lpath, strerror(errno));
        return false;
    }

        size = st.st_size;
    }
    uint64_t total_size = st.st_size;
    uint64_t bytes_copied = 0;

    int lfd = adb_open(path, O_RDONLY);
    int lfd = adb_open(lpath, O_RDONLY);
    if (lfd < 0) {
        fprintf(stderr, "adb: cannot open '%s': %s\n", path, strerror(errno));
        sc.Error("cannot open '%s': %s", lpath, strerror(errno));
        return false;
    }

@@ -281,7 +283,7 @@ static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const c
        int ret = adb_read(lfd, sbuf.data, sc.max);
        if (ret <= 0) {
            if (ret < 0) {
                fprintf(stderr, "adb: cannot read '%s': %s\n", path, strerror(errno));
                sc.Error("cannot read '%s': %s", lpath, strerror(errno));
                adb_close(lfd);
                return false;
            }
@@ -295,9 +297,10 @@ static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const c
        }
        sc.total_bytes += ret;

        if (show_progress) {
            print_transfer_progress(sc.total_bytes, size);
        }
        bytes_copied += ret;

        int percentage = static_cast<int>(bytes_copied * 100 / total_size);
        sc.Print(android::base::StringPrintf("%s: %d%%", rpath, percentage));
    }

    adb_close(lfd);
@@ -306,8 +309,7 @@ static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const c
    msg.data.id = ID_DONE;
    msg.data.size = mtime;
    if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
        fprintf(stderr, "adb: failed to send ID_DONE message for '%s': %s\n",
                path, strerror(errno));
        sc.Error("failed to send ID_DONE message for '%s': %s", rpath, strerror(errno));
        return false;
    }

@@ -315,7 +317,7 @@ static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const c
}

static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
                      unsigned mtime, mode_t mode, bool show_progress)
                      unsigned mtime, mode_t mode)
{
    std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);

@@ -324,44 +326,48 @@ static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
        char buf[PATH_MAX];
        ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
        if (data_length == -1) {
            fprintf(stderr, "adb: readlink '%s' failed: %s\n", lpath, strerror(errno));
            sc.Error("readlink '%s' failed: %s", lpath, strerror(errno));
            return false;
        }
        buf[data_length++] = '\0';

        if (!sc.SendSmallFile(path_and_mode.c_str(), buf, data_length, mtime)) return false;
        if (!sc.SendSmallFile(path_and_mode.c_str(), rpath, buf, data_length, mtime)) return false;
        return sc.CopyDone(lpath, rpath);
#endif
    }

    if (!S_ISREG(mode)) {
        fprintf(stderr, "adb: local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
        sc.Error("local file '%s' has unsupported mode: 0o%o", lpath, mode);
        return false;
    }

    struct stat st;
    if (stat(lpath, &st) == -1) {
        fprintf(stderr, "adb: failed to stat local file '%s': %s\n", lpath, strerror(errno));
        sc.Error("failed to stat local file '%s': %s", lpath, strerror(errno));
        return false;
    }
    if (st.st_size < SYNC_DATA_MAX) {
        std::string data;
        if (!android::base::ReadFileToString(lpath, &data)) {
            fprintf(stderr, "adb: failed to read all of '%s': %s\n", lpath, strerror(errno));
            sc.Error("failed to read all of '%s': %s", lpath, strerror(errno));
            return false;
        }
        if (!sc.SendSmallFile(path_and_mode.c_str(), rpath, data.data(), data.size(), mtime)) {
            return false;
        }
        if (!sc.SendSmallFile(path_and_mode.c_str(), data.data(), data.size(), mtime)) return false;
    } else {
        if (!SendLargeFile(sc, path_and_mode.c_str(), lpath, mtime, show_progress)) return false;
        if (!SendLargeFile(sc, path_and_mode.c_str(), lpath, rpath, mtime)) {
            return false;
        }
    }
    return sc.CopyDone(lpath, rpath);
}

static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath) {
    sc.Print(rpath);

    unsigned size = 0;
    if (show_progress) {
    if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
    }

    if (!sc.SendRequest(ID_RECV, rpath)) return false;

@@ -369,10 +375,11 @@ static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
    mkdirs(lpath);
    int lfd = adb_creat(lpath, 0644);
    if (lfd < 0) {
        fprintf(stderr, "adb: cannot create '%s': %s\n", lpath, strerror(errno));
        sc.Error("cannot create '%s': %s", lpath, strerror(errno));
        return false;
    }

    uint64_t bytes_copied = 0;
    while (true) {
        syncmsg msg;
        if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
@@ -391,7 +398,7 @@ static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
        }

        if (msg.data.size > sc.max) {
            fprintf(stderr, "adb: msg.data.size too large: %u (max %zu)\n", msg.data.size, sc.max);
            sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
            adb_close(lfd);
            adb_unlink(lpath);
            return false;
@@ -405,7 +412,7 @@ static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
        }

        if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
            fprintf(stderr, "adb: cannot write '%s': %s\n", lpath, strerror(errno));
            sc.Error("cannot write '%s': %s", lpath, strerror(errno));
            adb_close(lfd);
            adb_unlink(lpath);
            return false;
@@ -413,9 +420,10 @@ static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,

        sc.total_bytes += msg.data.size;

        if (show_progress) {
            print_transfer_progress(sc.total_bytes, size);
        }
        bytes_copied += msg.data.size;

        int percentage = static_cast<int>(bytes_copied * 100 / size);
        sc.Print(android::base::StringPrintf("%s: %d%%", rpath, percentage));
    }

    adb_close(lfd);
@@ -475,13 +483,14 @@ static bool IsDotOrDotDot(const char* name) {
    return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
}

static int local_build_list(copyinfo** filelist, const char* lpath, const char* rpath) {
static int local_build_list(SyncConnection& sc,
                            copyinfo** filelist, const char* lpath, const char* rpath) {
    copyinfo *dirlist = 0;
    copyinfo *ci, *next;

    std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir);
    if (!dir) {
        fprintf(stderr, "adb: cannot open '%s': %s\n", lpath, strerror(errno));
        sc.Error("cannot open '%s': %s", lpath, strerror(errno));
        return -1;
    }

@@ -491,7 +500,7 @@ static int local_build_list(copyinfo** filelist, const char* lpath, const char*

        char stat_path[PATH_MAX];
        if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) {
            fprintf(stderr, "adb: skipping long path '%s%s'\n", lpath, de->d_name);
            sc.Error("skipping long path '%s%s'", lpath, de->d_name);
            continue;
        }
        strcpy(stat_path, lpath);
@@ -506,7 +515,7 @@ static int local_build_list(copyinfo** filelist, const char* lpath, const char*
            } else {
                ci = mkcopyinfo(lpath, rpath, de->d_name, 0);
                if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
                    fprintf(stderr, "adb: skipping special file '%s'\n", ci->src);
                    sc.Error("skipping special file '%s'", ci->src);
                    free(ci);
                } else {
                    ci->time = st.st_mtime;
@@ -517,7 +526,7 @@ static int local_build_list(copyinfo** filelist, const char* lpath, const char*
                }
            }
        } else {
            fprintf(stderr, "adb: cannot lstat '%s': %s\n",stat_path , strerror(errno));
            sc.Error("cannot lstat '%s': %s",stat_path , strerror(errno));
        }
    }

@@ -525,7 +534,7 @@ static int local_build_list(copyinfo** filelist, const char* lpath, const char*
    dir.reset();
    for (ci = dirlist; ci != 0; ci = next) {
        next = ci->next;
        local_build_list(filelist, ci->src, ci->dst);
        local_build_list(sc, filelist, ci->src, ci->dst);
        free(ci);
    }

@@ -555,7 +564,7 @@ static bool copy_local_dir_remote(SyncConnection& sc, const char* lpath, const c
        rpath = tmp;
    }

    if (local_build_list(&filelist, lpath, rpath)) {
    if (local_build_list(sc, &filelist, lpath, rpath)) {
        return false;
    }

@@ -578,10 +587,13 @@ static bool copy_local_dir_remote(SyncConnection& sc, const char* lpath, const c
    for (ci = filelist; ci != 0; ci = next) {
        next = ci->next;
        if (ci->flag == 0) {
            fprintf(stderr, "%spush: %s -> %s\n", list_only ? "would " : "", ci->src, ci->dst);
            if (!list_only && !sync_send(sc, ci->src, ci->dst, ci->time, ci->mode, false)) {
            if (list_only) {
                fprintf(stderr, "would push: %s -> %s\n", ci->src, ci->dst);
            } else {
                if (!sync_send(sc, ci->src, ci->dst, ci->time, ci->mode)) {
                  return false;
                }
            }
            pushed++;
        } else {
            skipped++;
@@ -589,20 +601,21 @@ static bool copy_local_dir_remote(SyncConnection& sc, const char* lpath, const c
        free(ci);
    }

    fprintf(stderr, "%d file%s pushed. %d file%s skipped.\n",
    sc.Print(android::base::StringPrintf("%s: %d file%s pushed. %d file%s skipped.%s\n",
                                         rpath,
                                         pushed, (pushed == 1) ? "" : "s",
            skipped, (skipped == 1) ? "" : "s");

                                         skipped, (skipped == 1) ? "" : "s",
                                         sc.TransferRate().c_str()));
    return true;
}

bool do_sync_push(const char* lpath, const char* rpath, bool show_progress) {
bool do_sync_push(const char* lpath, const char* rpath) {
    SyncConnection sc;
    if (!sc.IsValid()) return false;

    struct stat st;
    if (stat(lpath, &st)) {
        fprintf(stderr, "adb: cannot stat '%s': %s\n", lpath, strerror(errno));
        sc.Error("cannot stat '%s': %s", lpath, strerror(errno));
        return false;
    }

@@ -619,11 +632,13 @@ bool do_sync_push(const char* lpath, const char* rpath, bool show_progress) {
        path_holder = android::base::StringPrintf("%s/%s", rpath, adb_basename(lpath).c_str());
        rpath = path_holder.c_str();
    }
    return sync_send(sc, lpath, rpath, st.st_mtime, st.st_mode, show_progress);
    bool result = sync_send(sc, lpath, rpath, st.st_mtime, st.st_mode);
    sc.Print("\n");
    return result;
}


struct sync_ls_build_list_cb_args {
    SyncConnection* sc;
    copyinfo** filelist;
    copyinfo** dirlist;
    const char* rpath;
@@ -633,7 +648,7 @@ struct sync_ls_build_list_cb_args {
static void sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
                                  const char* name, void* cookie)
{
    sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;
    sync_ls_build_list_cb_args* args = static_cast<sync_ls_build_list_cb_args*>(cookie);
    copyinfo *ci;

    if (S_ISDIR(mode)) {
@@ -655,22 +670,23 @@ static void sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
        ci->next = *filelist;
        *filelist = ci;
    } else {
        fprintf(stderr, "adb: skipping special file '%s'\n", name);
        args->sc->Print(android::base::StringPrintf("skipping special file '%s'\n", name));
    }
}

static bool remote_build_list(SyncConnection& sc, copyinfo **filelist,
                              const char *rpath, const char *lpath) {
    copyinfo *dirlist = NULL;
    sync_ls_build_list_cb_args args;
    copyinfo* dirlist = nullptr;

    sync_ls_build_list_cb_args args;
    args.sc = &sc;
    args.filelist = filelist;
    args.dirlist = &dirlist;
    args.rpath = rpath;
    args.lpath = lpath;

    // Put the files/dirs in rpath on the lists.
    if (!sync_ls(sc, rpath, sync_ls_build_list_cb, (void *)&args)) {
    if (!sync_ls(sc, rpath, sync_ls_build_list_cb, &args)) {
        return false;
    }

@@ -710,7 +726,7 @@ static bool copy_remote_dir_local(SyncConnection& sc, const char* rpath, const c
    if (lpath_clean.back() != '/') lpath_clean.push_back('/');

    // Recursively build the list of files to copy.
    fprintf(stderr, "pull: building file list...\n");
    sc.Print("pull: building file list...");
    copyinfo* filelist = nullptr;
    if (!remote_build_list(sc, &filelist, rpath_clean.c_str(), lpath_clean.c_str())) return false;

@@ -720,8 +736,8 @@ static bool copy_remote_dir_local(SyncConnection& sc, const char* rpath, const c
    while (ci) {
        copyinfo* next = ci->next;
        if (ci->flag == 0) {
            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
            if (!sync_recv(sc, ci->src, ci->dst, false)) {
            sc.Print(android::base::StringPrintf("pull: %s -> %s", ci->src, ci->dst));
            if (!sync_recv(sc, ci->src, ci->dst)) {
                return false;
            }

@@ -736,20 +752,22 @@ static bool copy_remote_dir_local(SyncConnection& sc, const char* rpath, const c
        ci = next;
    }

    fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
    sc.Print(android::base::StringPrintf("%s: %d file%s pulled. %d file%s skipped.%s\n",
                                         rpath,
                                         pulled, (pulled == 1) ? "" : "s",
            skipped, (skipped == 1) ? "" : "s");
                                         skipped, (skipped == 1) ? "" : "s",
                                         sc.TransferRate().c_str()));
    return true;
}

bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs) {
bool do_sync_pull(const char* rpath, const char* lpath, int copy_attrs) {
    SyncConnection sc;
    if (!sc.IsValid()) return false;

    unsigned mode, time;
    if (!sync_stat(sc, rpath, &time, &mode, nullptr)) return false;
    if (mode == 0) {
        fprintf(stderr, "adb: remote object '%s' does not exist\n", rpath);
        sc.Error("remote object '%s' does not exist", rpath);
        return false;
    }

@@ -764,25 +782,24 @@ bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int
                lpath = path_holder.c_str();
            }
        }
        if (!sync_recv(sc, rpath, lpath, show_progress)) {
        if (!sync_recv(sc, rpath, lpath)) {
            return false;
        } else {
            if (copy_attrs && set_time_and_mode(lpath, time, mode)) {
                return false;
            }
        }
        sc.Print("\n");
        return true;
    } else if (S_ISDIR(mode)) {
        return copy_remote_dir_local(sc, rpath, lpath, copy_attrs);
    }

    fprintf(stderr, "adb: remote object '%s' not a file or directory\n", rpath);
    sc.Error("remote object '%s' not a file or directory", rpath);
    return false;
}

bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
    fprintf(stderr, "syncing %s...\n", rpath.c_str());

    SyncConnection sc;
    if (!sc.IsValid()) return false;

+2 −2
Original line number Diff line number Diff line
@@ -64,9 +64,9 @@ union syncmsg {

void file_sync_service(int fd, void* cookie);
bool do_sync_ls(const char* path);
bool do_sync_push(const char* lpath, const char* rpath, bool show_progress);
bool do_sync_push(const char* lpath, const char* rpath);
bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs);
bool do_sync_pull(const char* rpath, const char* lpath, int copy_attrs);

#define SYNC_DATA_MAX (64*1024)

Loading