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

Commit 76f2a93b authored by Mark Lindner's avatar Mark Lindner
Browse files

Added transfer progress reporting for push and pull commands.

Added a new '-p' switch to the 'push' and 'pull' commands that outputs
the file transfer progress (bytes transmitted, total bytes, and % done).
This provides useful feedback when transferring large files, and also
makes it possible for other tools to easily monitor the progress of a
forked push/pull command.

Change-Id: Iee6f42f5bd41292e5bc80fba779f526f0072e356
parent 28e41cce
Loading
Loading
Loading
Loading
+50 −12
Original line number Diff line number Diff line
@@ -107,8 +107,12 @@ void help()
        "                                 will disconnect from all connected TCP/IP devices.\n"
        "\n"
        "device commands:\n"
        "  adb push <local> <remote>    - copy file/dir to device\n"
        "  adb pull <remote> [<local>]  - copy file/dir from device\n"
        "  adb push [-p] <local> <remote>\n"
        "                               - copy file/dir to device\n"
        "                                 ('-p' to display the transfer progress)\n"
        "  adb pull [-p] <remote> [<local>]\n"
        "                               - copy file/dir from device\n"
        "                                 ('-p' to display the transfer progress)\n"
        "  adb sync [ <directory> ]     - copy host->device only if changed\n"
        "                                 (-l means list but don't copy)\n"
        "                                 (see 'adb help all')\n"
@@ -921,6 +925,28 @@ static const char *find_product_out_path(const char *hint)
    return path_buf;
}


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

    if ((narg > 0) && !strcmp(*arg, "-p")) {
        *show_progress = 1;
        ++arg;
        --narg;
    }

    if (narg > 0) {
        *path1 = *arg;
        ++arg;
        --narg;
    }

    if (narg > 0) {
        *path2 = *arg;
    }
}

int adb_commandline(int argc, char **argv)
{
    char buf[4096];
@@ -1368,18 +1394,29 @@ top:
    }

    if(!strcmp(argv[0], "push")) {
        if(argc != 3) return usage();
        return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
        int show_progress = 0;
        const char* lpath = NULL, *rpath = NULL;

        parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);

        if ((lpath != NULL) && (rpath != NULL)) {
            return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
        }

    if(!strcmp(argv[0], "pull")) {
        if (argc == 2) {
            return do_sync_pull(argv[1], ".");
        } else if (argc == 3) {
            return do_sync_pull(argv[1], argv[2]);
        } else {
        return usage();
    }

    if(!strcmp(argv[0], "pull")) {
        int show_progress = 0;
        const char* rpath = NULL, *lpath = ".";

        parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);

        if (rpath != NULL) {
            return do_sync_pull(rpath, lpath, show_progress);
        }

        return usage();
    }

    if(!strcmp(argv[0], "install")) {
@@ -1717,7 +1754,7 @@ int install_app(transport_type transport, char* serial, int argc, char** argv)
        }
    }

    err = do_sync_push(apk_file, apk_dest, verify_apk);
    err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
    if (err) {
        goto cleanup_apk;
    } else {
@@ -1725,7 +1762,8 @@ int install_app(transport_type transport, char* serial, int argc, char** argv)
    }

    if (verification_file != NULL) {
        err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
        err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
                           0 /* no show progress */);
        if (err) {
            goto cleanup_apk;
        } else {
+75 −12
Original line number Diff line number Diff line
@@ -62,6 +62,22 @@ static void END()
            total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
}

static const char* transfer_progress_format = "\rTransferring: %llu/%llu (%d%%)";

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

    fprintf(stderr, transfer_progress_format, bytes_current, bytes_total,
            (int) (bytes_current * 100 / bytes_total));

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

    fflush(stderr);
}

void sync_quit(int fd)
{
    syncmsg msg;
@@ -207,9 +223,10 @@ int sync_readmode(int fd, const char *path, unsigned *mode)
    return 0;
}

static int write_data_file(int fd, const char *path, syncsendbuf *sbuf)
static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show_progress)
{
    int lfd, err = 0;
    unsigned long long size = 0;

    lfd = adb_open(path, O_RDONLY);
    if(lfd < 0) {
@@ -217,6 +234,17 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf)
        return -1;
    }

    if (show_progress) {
        // Determine local file size.
        struct stat st;
        if (lstat(path, &st)) {
            fprintf(stderr,"cannot stat '%s': %s\n", path, strerror(errno));
            return -1;
        }

        size = st.st_size;
    }

    sbuf->id = ID_DATA;
    for(;;) {
        int ret;
@@ -238,13 +266,18 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf)
            break;
        }
        total_bytes += ret;

        if (show_progress) {
            print_transfer_progress(total_bytes, size);
        }
    }

    adb_close(lfd);
    return err;
}

static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf)
static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf,
                             int show_progress)
{
    int err = 0;
    int total = 0;
@@ -264,6 +297,10 @@ static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *s
        }
        total += count;
        total_bytes += count;

        if (show_progress) {
            print_transfer_progress(total, size);
        }
    }

    return err;
@@ -295,7 +332,7 @@ static int write_data_link(int fd, const char *path, syncsendbuf *sbuf)
#endif

static int sync_send(int fd, const char *lpath, const char *rpath,
                     unsigned mtime, mode_t mode, int verifyApk)
                     unsigned mtime, mode_t mode, int verifyApk, int show_progress)
{
    syncmsg msg;
    int len, r;
@@ -377,10 +414,10 @@ static int sync_send(int fd, const char *lpath, const char *rpath,
    }

    if (file_buffer) {
        write_data_buffer(fd, file_buffer, size, sbuf);
        write_data_buffer(fd, file_buffer, size, sbuf, show_progress);
        free(file_buffer);
    } else if (S_ISREG(mode))
        write_data_file(fd, lpath, sbuf);
        write_data_file(fd, lpath, sbuf, show_progress);
#ifdef HAVE_SYMLINKS
    else if (S_ISLNK(mode))
        write_data_link(fd, lpath, sbuf);
@@ -438,17 +475,38 @@ static int mkdirs(char *name)
    return 0;
}

int sync_recv(int fd, const char *rpath, const char *lpath)
int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress)
{
    syncmsg msg;
    int len;
    int lfd = -1;
    char *buffer = send_buffer.data;
    unsigned id;
    unsigned long long size = 0;

    len = strlen(rpath);
    if(len > 1024) return -1;

    if (show_progress) {
        // Determine remote file size.
        syncmsg stat_msg;
        stat_msg.req.id = ID_STAT;
        stat_msg.req.namelen = htoll(len);

        if (writex(fd, &stat_msg.req, sizeof(stat_msg.req)) ||
            writex(fd, rpath, len)) {
            return -1;
        }

        if (readx(fd, &stat_msg.stat, sizeof(stat_msg.stat))) {
            return -1;
        }

        if (stat_msg.stat.id != ID_STAT) return -1;

        size = ltohl(stat_msg.stat.size);
    }

    msg.req.id = ID_RECV;
    msg.req.namelen = htoll(len);
    if(writex(fd, &msg.req, sizeof(msg.req)) ||
@@ -502,6 +560,10 @@ int sync_recv(int fd, const char *rpath, const char *lpath)
        }

        total_bytes += len;

        if (show_progress) {
            print_transfer_progress(total_bytes, size);
        }
    }

    adb_close(lfd);
@@ -721,7 +783,8 @@ static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, i
        if(ci->flag == 0) {
            fprintf(stderr,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst);
            if(!listonly &&
               sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */)){
               sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */,
                         0 /* no show progress */)) {
                return 1;
            }
            pushed++;
@@ -739,7 +802,7 @@ static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, i
}


int do_sync_push(const char *lpath, const char *rpath, int verifyApk)
int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int show_progress)
{
    struct stat st;
    unsigned mode;
@@ -786,7 +849,7 @@ int do_sync_push(const char *lpath, const char *rpath, int verifyApk)
            rpath = tmp;
        }
        BEGIN();
        if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk)) {
        if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk, show_progress)) {
            return 1;
        } else {
            END();
@@ -923,7 +986,7 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
        next = ci->next;
        if (ci->flag == 0) {
            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
            if (sync_recv(fd, ci->src, ci->dst)) {
            if (sync_recv(fd, ci->src, ci->dst, 0 /* no show progress */)) {
                return 1;
            }
            pulled++;
@@ -940,7 +1003,7 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
    return 0;
}

int do_sync_pull(const char *rpath, const char *lpath)
int do_sync_pull(const char *rpath, const char *lpath, int show_progress)
{
    unsigned mode;
    struct stat st;
@@ -981,7 +1044,7 @@ int do_sync_pull(const char *rpath, const char *lpath)
            }
        }
        BEGIN();
        if(sync_recv(fd, rpath, lpath)) {
        if (sync_recv(fd, rpath, lpath, show_progress)) {
            return 1;
        } else {
            END();
+3 −3
Original line number Diff line number Diff line
@@ -78,9 +78,9 @@ typedef union {

void file_sync_service(int fd, void *cookie);
int do_sync_ls(const char *path);
int do_sync_push(const char *lpath, const char *rpath, int verifyApk);
int do_sync_push(const char *lpath, const char *rpath, int verifyApk, int show_progress);
int do_sync_sync(const char *lpath, const char *rpath, int listonly);
int do_sync_pull(const char *rpath, const char *lpath);
int do_sync_pull(const char *rpath, const char *lpath, int show_progress);

#define SYNC_DATA_MAX (64*1024)