[PATCH] smbclient download status

Daniel Reed n at cs.rpi.edu
Wed Apr 9 07:57:01 GMT 2003


This patch introduces common transfer status messages using fprintf() and
repetitive calls to GetTimeOfDay(). No existing messages are modified, only
new messages are displayed to stderr.

During a file transfer (either GET or PUT), at the conclusion of every
network read or write, a status message (including ETA and transfer rate)
will be displayed to the user. These messages will not be logged (they are
written using fprintf() rather than DEBUG()), and should not interfere with
automated downloads being written to stdout (smbclient ... -c 'get file -').
However, users actually viewing files using "get file -" and not passing the
output through a pager may see unfortunate artifacts.

Feel free to contact me privately if there are any concerns with this patch.
I am also on samba-technical, so I can follow any discussion here.

Thanks,
-- 
Daniel Reed <n at cs.rpi.edu>	http://s.acm.rpi.edu/~n/
naim FAQ: http://128.113.139.111/~n/naim/FAQ
-------------- next part --------------
diff -ruN samba-2.2.8a,original/source/client/client.c samba-2.2.8a/source/client/client.c
--- samba-2.2.8a,original/source/client/client.c	Fri Mar 14 16:34:47 2003
+++ samba-2.2.8a/source/client/client.c	Wed Apr  9 03:33:57 2003
@@ -101,6 +101,37 @@
 
 #define USENMB
 
+/* taken from gftp */
+static void tvsub(struct timeval *const tdiff, const struct timeval *const t1, const struct timeval *const t0)
+{
+	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+	while (tdiff->tv_usec < 0)
+		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
+}
+
+void progress(const long file_size, const long bytes, const struct timeval *const t0, const int xfer_type)
+{
+	struct timeval	td, t1;
+	float	s, bs, br;
+	long	sint, bsint, brint;
+
+	GetTimeOfDay(&t1);
+	tvsub(&td, &t1, t0);
+	s     = (float)td.tv_sec + ((float)td.tv_usec / 1000000.);
+	bs    = bytes / ((s==0) ? 1. : s);
+	br    = (float)(file_size-bytes)/bs;
+	sint  = (long)s;
+	bsint = (long)bs;
+	brint = (long)br;
+	fprintf(stderr, "\r%s: %10ld of %10ld bytes (%3.0f%%) in %3ld:%02ld"
+		" (ETA %3ld:%02ld) (%#6.02f kB/sec)",
+		xfer_type?"PUT":"GET", bytes, file_size,
+		100.*bytes/file_size, sint/60, sint-(60*(sint/60)), brint/60,
+		brint-(60*(brint/60)), bs/1024.);
+}
+/* end gftp */
+
 /****************************************************************************
 write to a local file with CR/LF->LF translation if appropriate. return the 
 number taken from the buffer. This may not equal the number written.
@@ -700,7 +731,14 @@
 		}
       
 		nread += n;
+
+		if (old_size)
+			progress(old_size, nread, &tp_start, 0);
+		else if (size)
+			progress(size, nread, &tp_start, 0);
 	}
+	if (old_size || size)
+		fprintf(stderr, "\n");
 
 	if (nread < size) {
 		DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
@@ -1020,6 +1058,7 @@
 	off_t nread=0;
 	char *buf=NULL;
 	int maxwrite=io_bufsize;
+	size_t old_size = 0;
 	
 	struct timeval tp_start;
 	GetTimeOfDay(&tp_start);
@@ -1037,6 +1076,12 @@
 		f = stdin;
 		/* size of file is not known */
 	} else {
+		struct stat statbuf;
+		int ret;
+
+		ret = stat(lname, &statbuf);
+		if ((ret == 0) && S_ISREG(statbuf.st_mode))
+			old_size = statbuf.st_size;
 		f = sys_fopen(lname,"r");
 	}
 
@@ -1074,7 +1119,12 @@
 		} 
 
 		nread += n;
+
+		if (old_size)
+			progress(old_size, nread, &tp_start, 1);
 	}
+	if (old_size)
+		fprintf(stderr, "\n");
 
 	if (!cli_close(cli, fnum)) {
 		DEBUG(0,("%s closing remote file %s\n",cli_errstr(cli),rname));


More information about the samba-technical mailing list