SFTP Status Bar..
Wendy Palm
wendyp at cray.com
Thu Feb 7 08:31:10 EST 2002
how do you "turn it on"? is it automatic/default?
mouring wrote:
>
> This is the LAST version I plan on doing.. If I hear no feed back good
> or bad. Then I'll assume I've wasted my time on a feature that people
> whine about but don't care to try. This is against 3.0.2pX so it
> should be VERY easy for anyone to test.
>
> - Ben
>
> diff -ur openssh-3.0.2p1/misc.c openssh/misc.c
> --- openssh-3.0.2p1/misc.c Tue Jul 3 23:46:58 2001
> +++ openssh/misc.c Wed Feb 6 13:15:55 2002
> @@ -30,6 +30,7 @@
> #include "misc.h"
> #include "log.h"
> #include "xmalloc.h"
> +#include "atomicio.h"
>
> /* remove newline at end of string */
> char *
> @@ -304,6 +305,139 @@
> args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
> args->list[args->num++] = xstrdup(buf);
> args->list[args->num] = NULL;
> +}
> +
> +/* scp/sftp progression meter (from src/usr.bin/ftp/util.c) */
> +static int
> +foregroundproc(void)
> +{
> + static pid_t pgrp = -1;
> + int ctty_pgrp;
> +
> + if (pgrp == -1)
> + pgrp = getpgrp();
> +
> + return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
> + ctty_pgrp == pgrp));
> +}
> +
> +int
> +getttywidth(void)
> +{
> + struct winsize winsize;
> +
> + if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
> + return (winsize.ws_col ? winsize.ws_col : 80);
> + else
> + return (80);
> +}
> +
> +void
> +progressmeter(off_t statbytes, off_t totalbytes, char *filename)
> +{
> +#define STALLTIME 5 /* number of seconds before xfer assumed "stalled" */
> + static const char prefixes[] = " KMGTP";
> + static char *progressbar = NULL;
> + static struct timeval *start = NULL, lastupdate;
> + static off_t lastsize;
> + static size_t progressbar_size = 0;
> + struct timeval now, td, wait;
> + off_t cursize, abbrevsize;
> + double elapsed;
> + int ratio, barlength, i, remaining;
> + char buf[256];
> +
> + if (!start) {
> + start = xmalloc(sizeof(struct timeval));
> + (void) gettimeofday(start, (struct timezone *) 0);
> + lastupdate = *start;
> + lastsize = 0;
> + }
> + if (foregroundproc() == 0)
> + return;
> +
> + (void) gettimeofday(&now, (struct timezone *) 0);
> + cursize = statbytes;
> + if (totalbytes != 0) {
> + ratio = 100.0 * cursize / totalbytes;
> + ratio = MAX(ratio, 0);
> + ratio = MIN(ratio, 100);
> + } else
> + ratio = 100;
> +
> + barlength = getttywidth() - 51;
> + if (barlength > progressbar_size) {
> + progressbar_size = barlength;
> + progressbar = xrealloc(progressbar, barlength);
> + memset(progressbar, '*', barlength);
> + }
> +
> + snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ",
> + (filename?filename:""), ratio);
> + if (barlength > 0) {
> + i = barlength * ratio / 100;
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + "|%.*s%*s|", i, progressbar, barlength - i, "");
> + }
> + i = 0;
> + abbrevsize = cursize;
> + while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
> + i++;
> + abbrevsize >>= 10;
> + }
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5llu %c%c ",
> + (unsigned long long) abbrevsize, prefixes[i],
> + prefixes[i] == ' ' ? ' ' : 'B');
> +
> + timersub(&now, &lastupdate, &wait);
> + if (cursize > lastsize) {
> + lastupdate = now;
> + lastsize = cursize;
> + if (wait.tv_sec >= STALLTIME) {
> + start->tv_sec += wait.tv_sec;
> + start->tv_usec += wait.tv_usec;
> + }
> + wait.tv_sec = 0;
> + }
> + timersub(&now, start, &td);
> + elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
> +
> + if ((totalbytes != statbytes) &&
> + (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + " --:-- ETA");
> + } else if (wait.tv_sec >= STALLTIME) {
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + " - stalled -");
> + } else {
> + if (totalbytes != statbytes)
> + remaining = (int)(totalbytes / (statbytes / elapsed) -
> + elapsed);
> + else
> + remaining = elapsed;
> +
> + i = remaining / 3600;
> + if (i)
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + "%2d:", i);
> + else
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + " ");
> + i = remaining % 3600;
> + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> + "%02d:%02d%s", i / 60, i % 60,
> + (totalbytes != statbytes) ? " ETA" : " ");
> + }
> + atomicio(write, fileno(stdout), buf, strlen(buf));
> +
> + if (totalbytes == statbytes) {
> + atomicio(write, fileno(stdout), "\n", 1);
> +
> + /* Clean up for next usage */
> + xfree(start);
> + start = NULL;
> + statbytes = 0;
> + }
> }
>
> mysig_t
> Only in openssh: misc.c.orig
> diff -ur openssh-3.0.2p1/misc.h openssh/misc.h
> --- openssh-3.0.2p1/misc.h Wed Jul 4 12:25:55 2001
> +++ openssh/misc.h Wed Feb 6 13:02:33 2002
> @@ -29,7 +29,11 @@
> int num;
> int nalloc;
> };
> +
> void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));
> +void progressmeter(off_t statbytes, off_t totalbytes, char *curfile);
> +
> +#define PROGRESSTIME 1 /* alarm() interval for updating progress meter */
>
> /* wrapper for signal interface */
> typedef void (*mysig_t)(int);
> diff -ur openssh-3.0.2p1/scp.c openssh/scp.c
> --- openssh-3.0.2p1/scp.c Sun Oct 21 19:53:59 2001
> +++ openssh/scp.c Wed Feb 6 13:07:33 2002
> @@ -89,32 +89,12 @@
> char *__progname;
> #endif
>
> -/* For progressmeter() -- number of seconds before xfer considered "stalled" */
> -#define STALLTIME 5
> -/* alarm() interval for updating progress meter */
> -#define PROGRESSTIME 1
> -
> -/* Progress meter bar */
> -#define BAR \
> - "************************************************************"\
> - "************************************************************"\
> - "************************************************************"\
> - "************************************************************"
> -#define MAX_BARLENGTH (sizeof(BAR) - 1)
> -
> -/* Visual statistics about files as they are transferred. */
> -void progressmeter(int);
> -
> -/* Returns width of the terminal (for progress meter calculations). */
> -int getttywidth(void);
> +static void updateprogressmeter(int done);
> int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
>
> /* Struct for addargs */
> arglist args;
>
> -/* Time a transfer started. */
> -static struct timeval start;
> -
> /* Number of bytes of current file transferred so far. */
> volatile off_t statbytes;
>
> @@ -569,7 +549,7 @@
> }
> if (showprogress) {
> totalbytes = stb.st_size;
> - progressmeter(-1);
> + updateprogressmeter(0);
> }
> /* Keep writing after an error so that we stay sync'd up. */
> for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
> @@ -591,7 +571,7 @@
> }
> }
> if (showprogress)
> - progressmeter(1);
> + updateprogressmeter(1);
>
> if (close(fd) < 0 && !haderr)
> haderr = errno;
> @@ -835,7 +815,7 @@
>
> if (showprogress) {
> totalbytes = size;
> - progressmeter(-1);
> + updateprogressmeter(0);
> }
> statbytes = 0;
> for (count = i = 0; i < size; i += 4096) {
> @@ -871,7 +851,8 @@
> }
> }
> if (showprogress)
> - progressmeter(1);
> + updateprogressmeter(1);
> +
> if (count != 0 && wrerr == NO &&
> (j = atomicio(write, ofd, bp->buf, count)) != count) {
> wrerr = YES;
> @@ -1079,140 +1060,17 @@
> }
>
> static void
> -updateprogressmeter(int ignore)
> +updateprogressmeter(int done)
> {
> - int save_errno = errno;
> -
> - progressmeter(0);
> - mysignal(SIGALRM, updateprogressmeter);
> - alarm(PROGRESSTIME);
> - errno = save_errno;
> -}
> -
> -static int
> -foregroundproc(void)
> -{
> - static pid_t pgrp = -1;
> - int ctty_pgrp;
> -
> - if (pgrp == -1)
> - pgrp = getpgrp();
> + int save_errno = errno;
>
> -#ifdef HAVE_TCGETPGRP
> - return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 &&
> - ctty_pgrp == pgrp);
> -#else
> - return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
> - ctty_pgrp == pgrp));
> -#endif
> -}
>
> -void
> -progressmeter(int flag)
> -{
> - static const char prefixes[] = " KMGTP";
> - static struct timeval lastupdate;
> - static off_t lastsize;
> - struct timeval now, td, wait;
> - off_t cursize, abbrevsize;
> - double elapsed;
> - int ratio, barlength, i, remaining;
> - char buf[256];
> -
> - if (flag == -1) {
> - (void) gettimeofday(&start, (struct timezone *) 0);
> - lastupdate = start;
> - lastsize = 0;
> - }
> - if (foregroundproc() == 0)
> - return;
> + progressmeter(statbytes, totalbytes, curfile);
> + if (done == 0) {
> + mysignal(SIGALRM, updateprogressmeter);
> + alarm(PROGRESSTIME);
> + } else
> + alarm(0);
>
> - (void) gettimeofday(&now, (struct timezone *) 0);
> - cursize = statbytes;
> - if (totalbytes != 0) {
> - ratio = 100.0 * cursize / totalbytes;
> - ratio = MAX(ratio, 0);
> - ratio = MIN(ratio, 100);
> - } else
> - ratio = 100;
> -
> - snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);
> -
> - barlength = getttywidth() - 51;
> - barlength = (barlength <= MAX_BARLENGTH)?barlength:MAX_BARLENGTH;
> - if (barlength > 0) {
> - i = barlength * ratio / 100;
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> - "|%.*s%*s|", i, BAR, barlength - i, "");
> - }
> - i = 0;
> - abbrevsize = cursize;
> - while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
> - i++;
> - abbrevsize >>= 10;
> - }
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5lu %c%c ",
> - (unsigned long) abbrevsize, prefixes[i],
> - prefixes[i] == ' ' ? ' ' : 'B');
> -
> - timersub(&now, &lastupdate, &wait);
> - if (cursize > lastsize) {
> - lastupdate = now;
> - lastsize = cursize;
> - if (wait.tv_sec >= STALLTIME) {
> - start.tv_sec += wait.tv_sec;
> - start.tv_usec += wait.tv_usec;
> - }
> - wait.tv_sec = 0;
> - }
> - timersub(&now, &start, &td);
> - elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
> -
> - if (flag != 1 &&
> - (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> - " --:-- ETA");
> - } else if (wait.tv_sec >= STALLTIME) {
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> - " - stalled -");
> - } else {
> - if (flag != 1)
> - remaining = (int)(totalbytes / (statbytes / elapsed) -
> - elapsed);
> - else
> - remaining = elapsed;
> -
> - i = remaining / 3600;
> - if (i)
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> - "%2d:", i);
> - else
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> - " ");
> - i = remaining % 3600;
> - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> - "%02d:%02d%s", i / 60, i % 60,
> - (flag != 1) ? " ETA" : " ");
> - }
> - atomicio(write, fileno(stdout), buf, strlen(buf));
> -
> - if (flag == -1) {
> - mysignal(SIGALRM, updateprogressmeter);
> - alarm(PROGRESSTIME);
> - } else if (flag == 1) {
> - alarm(0);
> - atomicio(write, fileno(stdout), "\n", 1);
> - statbytes = 0;
> - }
> -}
> -
> -int
> -getttywidth(void)
> -{
> - struct winsize winsize;
> -
> - if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
> - return (winsize.ws_col ? winsize.ws_col : 80);
> - else
> - return (80);
> + errno = save_errno;
> }
> diff -ur openssh-3.0.2p1/sftp-client.c openssh/sftp-client.c
> --- openssh-3.0.2p1/sftp-client.c Wed Jul 18 10:45:45 2001
> +++ openssh/sftp-client.c Wed Feb 6 13:02:34 2002
> @@ -49,6 +49,11 @@
> /* Message ID */
> static u_int msg_id = 1;
>
> +/* Progress Meter items */
> +off_t statbytes = 0;
> +off_t totalbytes = 0;
> +char *curfile = NULL;
> +
> static void
> send_msg(int fd, Buffer *m)
> {
> @@ -671,7 +676,7 @@
>
> int
> do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
> - int pflag)
> + int pflag, void (*progressbar)(int))
> {
> int local_fd;
> u_int expected_id, handle_len, mode, type, id;
> @@ -724,6 +729,11 @@
> return(-1);
> }
>
> + totalbytes = a->size;
> + curfile = remote_path;
> + if (progressbar)
> + (progressbar)(0);
> +
> /* Read from remote and write to local */
> offset = 0;
> for(;;) {
> @@ -785,6 +795,7 @@
>
> offset += len;
> xfree(data);
> + statbytes = offset;
> }
> status = do_close(fd_in, fd_out, handle, handle_len);
>
> @@ -807,15 +818,18 @@
> }
>
> done:
> + if (progressbar)
> + (progressbar)(1);
> close(local_fd);
> buffer_free(&msg);
> xfree(handle);
> +
> return status;
> }
>
> int
> do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
> - int pflag)
> + int pflag, void (*progressbar)(int))
> {
> int local_fd;
> u_int handle_len, id;
> @@ -865,6 +879,10 @@
> buffer_free(&msg);
> return(-1);
> }
> + totalbytes = a.size;
> + curfile = local_path;
> + if (progressbar)
> + (progressbar)(0);
>
> /* Read from local and write to remote */
> offset = 0;
> @@ -908,6 +926,7 @@
> (u_int64_t)offset);
>
> offset += len;
> + statbytes = offset;
> }
>
> if (close(local_fd) == -1) {
> @@ -925,8 +944,10 @@
> status = do_close(fd_in, fd_out, handle, handle_len);
>
> done:
> + if (progressbar)
> + (progressbar)(1);
> xfree(handle);
> buffer_free(&msg);
> +
> return status;
> }
> -
> diff -ur openssh-3.0.2p1/sftp-client.h openssh/sftp-client.h
> --- openssh-3.0.2p1/sftp-client.h Tue Jul 3 23:07:13 2001
> +++ openssh/sftp-client.h Wed Feb 6 13:02:34 2002
> @@ -88,16 +88,14 @@
> /* Return target of symlink 'path' - caller must free result */
> char *do_readlink(int, int, char *);
>
> -/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
> -
> /*
> * Download 'remote_path' to 'local_path'. Preserve permissions and times
> * if 'pflag' is set
> */
> -int do_download(int, int, char *, char *, int);
> +int do_download(int, int, char *, char *, int, void (*)(int));
>
> /*
> * Upload 'local_path' to 'remote_path'. Preserve permissions and times
> * if 'pflag' is set
> */
> -int do_upload(int, int, char *, char *, int);
> +int do_upload(int, int, char *, char *, int, void (*)(int));
> diff -ur openssh-3.0.2p1/sftp-int.c openssh/sftp-int.c
> --- openssh-3.0.2p1/sftp-int.c Wed Aug 15 18:22:57 2001
> +++ openssh/sftp-int.c Wed Feb 6 13:02:34 2002
> @@ -32,6 +32,7 @@
> #include "xmalloc.h"
> #include "log.h"
> #include "pathnames.h"
> +#include "misc.h"
>
> #include "sftp.h"
> #include "sftp-common.h"
> @@ -113,6 +114,24 @@
> };
>
> static void
> +updateprogressmeter(int done)
> +{
> + int save_errno = errno;
> + extern off_t statbytes;
> + extern off_t totalbytes;
> + extern char *curfile;
> +
> + progressmeter(statbytes, totalbytes, curfile);
> + if (done == 0) {
> + mysignal(SIGALRM, updateprogressmeter);
> + alarm(PROGRESSTIME);
> + } else
> + alarm(0);
> +
> + errno = save_errno;
> +}
> +
> +static void
> help(void)
> {
> printf("Available commands:\n");
> @@ -380,8 +399,8 @@
> err = -1;
> goto out;
> }
> - printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst);
> - err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag);
> + err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag,
> + NULL);
> goto out;
> }
>
> @@ -404,8 +423,8 @@
> } else
> abs_dst = tmp;
>
> - printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
> - if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag) == -1)
> + if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag,
> + updateprogressmeter) == -1)
> err = -1;
> xfree(abs_dst);
> abs_dst = NULL;
> @@ -462,8 +481,8 @@
> }
> abs_dst = make_absolute(abs_dst, pwd);
> }
> - printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst);
> - err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag);
> + err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag,
> + updateprogressmeter);
> goto out;
> }
>
> @@ -486,8 +505,8 @@
> } else
> abs_dst = make_absolute(tmp, pwd);
>
> - printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
> - if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag) == -1)
> + if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag,
> + updateprogressmeter) == -1)
> err = -1;
> }
>
> _______________________________________________
> openssh-unix-dev at mindrot.org mailing list
> http://www.mindrot.org/mailman/listinfo/openssh-unix-dev
--
wendy palm
Cray OS Sustaining Engineering, Cray Inc.
wendyp at cray.com, 651-605-9154
More information about the openssh-unix-dev
mailing list