SFTP Status Bar..
mouring
mouring at etoh.eviladmin.org
Thu Feb 7 06:23:10 EST 2002
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;
}
More information about the openssh-unix-dev
mailing list