From: djm Date: Fri, 10 Jan 2003 10:43:24 +0000 (+0000) Subject: - fgsch@cvs.openbsd.org 2003/01/10 08:19:07 X-Git-Tag: V_3_6_P1~89 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/b65c3807cf26816238f1ddcd06979c059425e470 - fgsch@cvs.openbsd.org 2003/01/10 08:19:07 [scp.c sftp.1 sftp.c sftp-client.c sftp-int.c] sftp progress meter support. original diffs by Nils Nordman via markus@, merged to -current by me, djm@ ok. --- diff --git a/ChangeLog b/ChangeLog index 1c6ec3f7..d07d5345 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,11 @@ Allow blank lines and comments in input Ability to suppress abort on error in batchmode ("-put blah") Fixes mindrot bug #452; markus@ ok + - fgsch@cvs.openbsd.org 2003/01/10 08:19:07 + [scp.c sftp.1 sftp.c sftp-client.c sftp-int.c] + sftp progress meter support. + original diffs by Nils Nordman via + markus@, merged to -current by me, djm@ ok. 20030108 - (djm) Sync openbsd-compat/ with OpenBSD -current diff --git a/Makefile.in b/Makefile.in index 8639860e..7bdd7103 100644 --- a/Makefile.in +++ b/Makefile.in @@ -117,8 +117,8 @@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBS) -scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o - $(LD) -o $@ scp.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o + $(LD) -o $@ scp.o progressmeter.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) @@ -138,8 +138,8 @@ ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o $(LD) -o $@ sftp-server.o sftp-common.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o - $(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o progressmeter.o + $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) diff --git a/scp.c b/scp.c index 8324549d..44b5b458 100644 --- a/scp.c +++ b/scp.c @@ -75,13 +75,14 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.96 2002/12/13 15:20:52 markus Exp $"); +RCSID("$OpenBSD: scp.c,v 1.97 2003/01/10 08:19:07 fgsch Exp $"); #include "xmalloc.h" #include "atomicio.h" #include "pathnames.h" #include "log.h" #include "misc.h" +#include "progressmeter.h" #ifdef HAVE___PROGNAME extern char *__progname; @@ -89,30 +90,9 @@ extern char *__progname; char *__progname; #endif -/* For progressmeter() -- number of seconds before xfer considered "stalled" */ -#define STALLTIME 5 -/* alarm() interval for updating progress meter */ -#define PROGRESSTIME 1 - -/* Visual statistics about files as they are transferred. */ -void progressmeter(int); - -/* Returns width of the terminal (for progress meter calculations). */ -int getttywidth(void); -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; - -/* Total size of current file. */ -off_t totalbytes = 0; - /* Name of current file being transferred. */ char *curfile; @@ -505,7 +485,7 @@ source(argc, argv) struct stat stb; static BUF buffer; BUF *bp; - off_t i, amt, result; + off_t i, amt, result, statbytes; int fd, haderr, indx; char *last, *name, buf[2048]; int len; @@ -578,10 +558,8 @@ syserr: run_err("%s: %s", name, strerror(errno)); next: (void) close(fd); continue; } - if (showprogress) { - totalbytes = stb.st_size; - progressmeter(-1); - } + if (showprogress) + start_progress_meter(curfile, stb.st_size, &statbytes); /* Keep writing after an error so that we stay sync'd up. */ for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { amt = bp->cnt; @@ -602,7 +580,7 @@ next: (void) close(fd); } } if (showprogress) - progressmeter(1); + stop_progress_meter(); if (close(fd) < 0 && !haderr) haderr = errno; @@ -682,7 +660,7 @@ sink(argc, argv) BUF *bp; off_t i, j; int amt, count, exists, first, mask, mode, ofd, omode; - off_t size; + off_t size, statbytes; int setimes, targisdir, wrerrno = 0; char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; struct timeval tv[2]; @@ -844,11 +822,9 @@ bad: run_err("%s: %s", np, strerror(errno)); cp = bp->buf; wrerr = NO; - if (showprogress) { - totalbytes = size; - progressmeter(-1); - } statbytes = 0; + if (showprogress) + start_progress_meter(curfile, size, &statbytes); for (count = i = 0; i < size; i += 4096) { amt = 4096; if (i + amt > size) @@ -882,7 +858,7 @@ bad: run_err("%s: %s", np, strerror(errno)); } } if (showprogress) - progressmeter(1); + stop_progress_meter(); if (count != 0 && wrerr == NO && (j = atomicio(write, ofd, bp->buf, count)) != count) { wrerr = YES; @@ -1086,170 +1062,3 @@ lostconn(signo) else exit(1); } - -static void -updateprogressmeter(int ignore) -{ - int save_errno = errno; - - progressmeter(0); - signal(SIGALRM, updateprogressmeter); - alarm(PROGRESSTIME); - errno = save_errno; -} - -static int -foregroundproc(void) -{ - static pid_t pgrp = -1; - int ctty_pgrp; - - if (pgrp == -1) - pgrp = getpgrp(); - -#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 spaces[] = " " - " " - " " - " " - " " - " "; - static const char prefixes[] = " KMGTP"; - static struct timeval lastupdate; - static off_t lastsize; - struct timeval now, td, wait; - off_t cursize, abbrevsize, bytespersec; - double elapsed; - int ratio, remaining, i, ai, bi, nspaces; - char buf[512]; - - if (flag == -1) { - (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; - - abbrevsize = cursize; - for (ai = 0; abbrevsize >= 10000 && ai < sizeof(prefixes); ai++) - abbrevsize >>= 10; - - timersub(&now, &lastupdate, &wait); - if (cursize > lastsize) { - lastupdate = now; - lastsize = cursize; - wait.tv_sec = 0; - } - timersub(&now, &start, &td); - elapsed = td.tv_sec + (td.tv_usec / 1000000.0); - - bytespersec = 0; - if (statbytes > 0) { - bytespersec = statbytes; - if (elapsed > 0.0) - bytespersec /= elapsed; - } - for (bi = 1; bytespersec >= 1024000 && bi < sizeof(prefixes); bi++) - bytespersec >>= 10; - - nspaces = MIN(getttywidth() - 79, sizeof(spaces) - 1); - -#ifdef HAVE_LONG_LONG_INT - snprintf(buf, sizeof(buf), - "\r%-45.45s%.*s%3d%% %4lld%c%c %3lld.%01d%cB/s", - curfile, - nspaces, - spaces, - ratio, - (long long)abbrevsize, - prefixes[ai], - ai == 0 ? ' ' : 'B', - (long long)(bytespersec / 1024), - (int)((bytespersec % 1024) * 10 / 1024), - prefixes[bi] - ); -#else - snprintf(buf, sizeof(buf), - "\r%-45.45s%.*s%3d%% %4lld%c%c %3lu.%01d%cB/s", - curfile, - nspaces, - spaces, - ratio, - (u_long)abbrevsize, - prefixes[ai], - ai == 0 ? ' ' : 'B', - (u_long)(bytespersec / 1024), - (int)((bytespersec % 1024) * 10 / 1024), - prefixes[bi] - ); -#endif - - 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); -} diff --git a/sftp-client.c b/sftp-client.c index bff37073..e0d3ad56 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -28,7 +28,7 @@ /* XXX: copy between two remote sites */ #include "includes.h" -RCSID("$OpenBSD: sftp-client.c,v 1.38 2003/01/06 23:51:22 djm Exp $"); +RCSID("$OpenBSD: sftp-client.c,v 1.39 2003/01/10 08:19:07 fgsch Exp $"); #include "openbsd-compat/sys-queue.h" @@ -38,11 +38,14 @@ RCSID("$OpenBSD: sftp-client.c,v 1.38 2003/01/06 23:51:22 djm Exp $"); #include "xmalloc.h" #include "log.h" #include "atomicio.h" +#include "progressmeter.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" +extern int showprogress; + /* Minimum amount of data to read at at time */ #define MIN_READ_SIZE 512 @@ -741,6 +744,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, int read_error, write_errno; u_int64_t offset, size; u_int handle_len, mode, type, id, buflen; + off_t progress_counter; struct request { u_int id; u_int len; @@ -806,6 +810,16 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, /* Read from remote and write to local */ write_error = read_error = write_errno = num_req = offset = 0; max_req = 1; + progress_counter = 0; + + if (showprogress) { + if (size) + start_progress_meter(remote_path, size, + &progress_counter); + else + printf("Fetching %s to %s\n", remote_path, local_path); + } + while (num_req > 0 || max_req > 0) { char *data; u_int len; @@ -866,6 +880,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, write_error = 1; max_req = 0; } + progress_counter += len; xfree(data); if (len == req->len) { @@ -908,6 +923,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, } } + if (showprogress && size) + stop_progress_meter(); + /* Sanity check */ if (TAILQ_FIRST(&requests) != NULL) fatal("Transfer complete, but requests still in queue"); @@ -1018,6 +1036,11 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, /* Read from local and write to remote */ offset = 0; + if (showprogress) + start_progress_meter(local_path, sb.st_size, &offset); + else + printf("Uploading %s to %s\n", local_path, remote_path); + for (;;) { int len; @@ -1094,6 +1117,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, } offset += len; } + if (showprogress) + stop_progress_meter(); xfree(data); if (close(local_fd) == -1) { diff --git a/sftp-int.c b/sftp-int.c index f2c8fa6d..88b0530a 100644 --- a/sftp-int.c +++ b/sftp-int.c @@ -25,7 +25,7 @@ /* XXX: recursive operations */ #include "includes.h" -RCSID("$OpenBSD: sftp-int.c,v 1.51 2003/01/08 23:53:26 djm Exp $"); +RCSID("$OpenBSD: sftp-int.c,v 1.52 2003/01/10 08:19:07 fgsch Exp $"); #include "buffer.h" #include "xmalloc.h" @@ -47,6 +47,9 @@ extern size_t copy_buffer_len; /* Number of concurrent outstanding requests */ extern int num_requests; +/* This is set to 0 if the progressmeter is not desired. */ +int showprogress = 1; + /* Seperators for interactive commands */ #define WHITESPACE " \t\r\n" @@ -73,6 +76,7 @@ extern int num_requests; #define I_SHELL 20 #define I_SYMLINK 21 #define I_VERSION 22 +#define I_PROGRESS 23 struct CMD { const char *c; @@ -100,6 +104,7 @@ const struct CMD cmds[] = { { "ls", I_LS }, { "lumask", I_LUMASK }, { "mkdir", I_MKDIR }, + { "progress", I_PROGRESS }, { "put", I_PUT }, { "mput", I_PUT }, { "pwd", I_PWD }, @@ -132,6 +137,7 @@ help(void) printf("ls [path] Display remote directory listing\n"); printf("lumask umask Set local umask to 'umask'\n"); printf("mkdir path Create remote directory\n"); + printf("preogress Toggle display of progress meter\n"); printf("put local-path [remote-path] Upload file\n"); printf("pwd Display remote working directory\n"); printf("exit Quit sftp\n"); @@ -425,7 +431,6 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) err = -1; goto out; } - printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst); err = do_download(conn, g.gl_pathv[0], abs_dst, pflag); goto out; } @@ -507,7 +512,6 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag) } abs_dst = make_absolute(abs_dst, pwd); } - printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst); err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag); goto out; } @@ -810,6 +814,7 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, case I_LPWD: case I_HELP: case I_VERSION: + case I_PROGRESS: break; default: fatal("Command not implemented"); @@ -1015,6 +1020,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, case I_VERSION: printf("SFTP protocol version %u\n", sftp_proto_version(conn)); break; + case I_PROGRESS: + showprogress = !showprogress; + if (showprogress) + printf("Progress meter enabled\n"); + else + printf("Progress meter disabled\n"); + break; default: fatal("%d is not implemented", cmdnum); } diff --git a/sftp.1 b/sftp.1 index 67086bda..ecd4d317 100644 --- a/sftp.1 +++ b/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.39 2003/01/08 23:53:26 djm Exp $ +.\" $OpenBSD: sftp.1,v 1.40 2003/01/10 08:19:07 fgsch Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -228,6 +228,8 @@ Set local umask to .It Ic mkdir Ar path Create remote directory specified by .Ar path . +.It Ic progress +Toggle display of progress meter. .It Xo Ic put .Op Ar flags .Ar local-path diff --git a/sftp.c b/sftp.c index d62e9e42..e8adcba1 100644 --- a/sftp.c +++ b/sftp.c @@ -24,7 +24,7 @@ #include "includes.h" -RCSID("$OpenBSD: sftp.c,v 1.33 2003/01/08 23:53:26 djm Exp $"); +RCSID("$OpenBSD: sftp.c,v 1.34 2003/01/10 08:19:07 fgsch Exp $"); /* XXX: short-form remote directory listings (like 'ls -C') */ @@ -49,6 +49,8 @@ FILE* infile; size_t copy_buffer_len = 32768; size_t num_requests = 16; +extern int showprogress; + static void connect_to_server(char *path, char **args, int *in, int *out, pid_t *sshpid) { @@ -162,6 +164,7 @@ main(int argc, char **argv) fatal("%s (%s).", strerror(errno), optarg); } else fatal("Filename already specified."); + showprogress = 0; break; case 'P': sftp_direct = optarg;