diff -Naur mbuffer-20010515/CHANGES mbuffer-20010518/CHANGES --- mbuffer-20010515/CHANGES Tue May 15 12:56:38 2001 +++ mbuffer-20010518/CHANGES Fri May 18 10:19:16 2001 @@ -1,10 +1,16 @@ +20010518: +- Bugfix: multi volume output now should work + (bugreport by Dan Hollis) +- docu update +- added some extra checks after running lint... + 20010515: - Docu update concerning usage of multi volume support - multi volume options consistency checking added 20010509: - summary is now also displayed upon break and terminate -- bugfix: summary overflow +- Bugfix: summary overflow - experimental feature: input of multiple volumes 20010507: @@ -18,7 +24,7 @@ - Bugfix: fixed sleep, which limited the performace to 1MB/s (credits go to Padraig Brady ) - Bugfix: fixed incorrect display of total datatransfer for >2GB -- cosmetic: on sighup print newline on stderr +- Cosmetic: on sighup print newline on stderr - added manpage 20010208: diff -Naur mbuffer-20010515/Makefile.in mbuffer-20010518/Makefile.in --- mbuffer-20010515/Makefile.in Mon May 14 08:23:47 2001 +++ mbuffer-20010518/Makefile.in Fri May 18 09:54:11 2001 @@ -24,7 +24,7 @@ distclean: clean $(RM) -f $(TARGET) config.h config.cache config.log \ - config.status *~ Makefile out + config.status *~ Makefile out mbuffer.1 install: $(INSTALL) $(TARGET) $(bindir) diff -Naur mbuffer-20010515/configure mbuffer-20010518/configure --- mbuffer-20010515/configure Tue May 15 12:58:20 2001 +++ mbuffer-20010518/configure Fri May 18 09:53:05 2001 @@ -643,7 +643,7 @@ PACKAGE=mbuffer -VERSION=20010515 +VERSION=20010518 cat >> confdefs.h <> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then diff -Naur mbuffer-20010515/configure.in mbuffer-20010518/configure.in --- mbuffer-20010515/configure.in Tue May 15 12:56:26 2001 +++ mbuffer-20010518/configure.in Fri May 18 09:53:02 2001 @@ -9,7 +9,7 @@ PACKAGE=mbuffer -VERSION=20010515 +VERSION=20010518 AC_DEFINE_UNQUOTED(VERSION,"${VERSION}") AC_SUBST(VERSION) @@ -71,4 +71,4 @@ AC_SUBST(EXPERIMENTAL) -AC_OUTPUT(Makefile) +AC_OUTPUT(Makefile mbuffer.1) diff -Naur mbuffer-20010515/mbuffer.1 mbuffer-20010518/mbuffer.1 --- mbuffer-20010515/mbuffer.1 Tue May 15 12:56:56 2001 +++ mbuffer-20010518/mbuffer.1 Thu Jan 1 01:00:00 1970 @@ -1,88 +0,0 @@ -.TH "mbuffer" "1" "20010515" "Thomas Maier-Komor" "console utility" -.SH "NAME" -mbuffer \- measuring buffer -.SH "SYNTAX" -.LP -mbuffer [\fIoptions\fP] -.SH "DESCRIPTION" -.LP -mbuffer buffers i/o operations and displays the throughput rate. It is multithreaded and offers more options than the standard buffer. -.SH "OPTIONS" -.LP -.TP -\fB\-i\fR <\fIfilename\fP> -use \fIfilename\fP as input instead of the standard input -.TP -\fB\-o\fR <\fIfilename\fP> -use \fIfilename\fP as output instead of the standard output -.TP -\fB\-b\fR <\fInum\fP> -use \fInum\fP blocks for buffer (default 256) -.TP -\fB\-s\fR <\fIsize\fP> -use blocks of \fIsize\fP bytes for buffer (default 10240) -.TP -\fB\-m\fR <\fIsize\fP> -use a total of \fIsize\fP bytes for buffer (default 2MB) -.TP -\fB\-n\fR <\fInum\fP> -\fInum\fP volumes in input device (requires use of option -i for input device specification) [currently multi volume support is EXPERIMENTAL] -.TP -\fB\-t\fR -use a memory mapped temporaray file as buffer (use with huge buffers) -.TP -\fB\-T\fR <\fIfile\fP> -as \-t but use \fIfile\fP instead -.TP -\fB\-p\fR <\fInum\fP> -start writing after the buffer has been filled to \fInum\fP% (default 0 \- start at once) -.TP -\fB\-l\fR <\fIfile\fP> -log messages to \fIfile\fP instead of standard error output -.TP -\fB\-u\fR <\fInum\fP> -pause \fInum\fP microseconds after each write \- might increase performance on some drives with very low performace (< 1 MB/sec) -.TP -\fB\-f\fR -overwrite output file if it exists already -.TP -\fB\-v\fR <\fInum\fP> -set verbose level to \fInum\fP (valid values are 0..5, 0 = none, 5 = all, even debugging informations) -.TP -\fB\-q\fR -quiet \- do not display the status on the standard error output -.TP -\fB\-\-help\fR -Output help information and exit. -.TP -\fB\-\-version\fR -Output version information and exit. -.SH "FILES" -.LP -\fI/usr/local/bin/mbuffer\fP -.br -\fI/tmp/mbuffer*\fP -.SH "EXAMPLES" -.LP -To run this program with the default options just type: -.LP -mbuffer -.LP -Using mbuffer to do a backup with tar to the default tape device. Options for this example: memory mapped temporary file with a size of 10 Megabytes, start after 80% of the buffer have been filled. -.LP -tar cf \- mydirectory | gzip | mbuffer \-t \-m 10M \-p 80 > $TAPE -.LP -Using mbuffer with 3 tapes for input and extracting the contents in the current work directory (EXPERIMENTAL): -.LP -mbuffer -n 3 -i $TAPE | gzip -dc | tar xf - -.LP -Using mbuffer to write to multiple tape volumes: -.LP -tar cf - /usr | mbuffer -o $TAPE -.SH "AUTHORS" -.LP -Thomas Maier\-Komor - -.SH "SEE ALSO" -.LP -buffer(1) diff -Naur mbuffer-20010515/mbuffer.1.in mbuffer-20010518/mbuffer.1.in --- mbuffer-20010515/mbuffer.1.in Thu Jan 1 01:00:00 1970 +++ mbuffer-20010518/mbuffer.1.in Fri May 18 09:53:49 2001 @@ -0,0 +1,90 @@ +.TH "mbuffer" "1" "@VERSION@" "Thomas Maier-Komor" "console utility" +.SH "NAME" +mbuffer \- measuring buffer +.SH "SYNTAX" +.LP +mbuffer [\fIoptions\fP] +.SH "DESCRIPTION" +.LP +mbuffer buffers i/o operations and displays the throughput rate. It is multithreaded and offers more options than the standard buffer. +.SH "OPTIONS" +.LP +.TP +\fB\-i\fR <\fIfilename\fP> +use \fIfilename\fP as input instead of the standard input (needs to be +given for multi volume support) +.TP +\fB\-o\fR <\fIfilename\fP> +use \fIfilename\fP as output instead of the standard output (needs to be +given for multi volume support) +.TP +\fB\-b\fR <\fInum\fP> +use \fInum\fP blocks for buffer (default 256) +.TP +\fB\-s\fR <\fIsize\fP> +use blocks of \fIsize\fP bytes for buffer (default 10240) +.TP +\fB\-m\fR <\fIsize\fP> +use a total of \fIsize\fP bytes for buffer (default 2MB) +.TP +\fB\-n\fR <\fInum\fP> +\fInum\fP volumes in input device (requires use of option -i for input device specification) [currently multi volume support is EXPERIMENTAL] +.TP +\fB\-t\fR +use a memory mapped temporaray file as buffer (use with huge buffers) +.TP +\fB\-T\fR <\fIfile\fP> +as \-t but use \fIfile\fP instead +.TP +\fB\-p\fR <\fInum\fP> +start writing after the buffer has been filled to \fInum\fP% (default 0 \- start at once) +.TP +\fB\-l\fR <\fIfile\fP> +log messages to \fIfile\fP instead of standard error output +.TP +\fB\-u\fR <\fInum\fP> +pause \fInum\fP microseconds after each write \- might increase performance on some drives with very low performace (< 1 MB/sec) +.TP +\fB\-f\fR +overwrite output file if it exists already +.TP +\fB\-v\fR <\fInum\fP> +set verbose level to \fInum\fP (valid values are 0..5, 0 = none, 5 = all, even debugging informations) +.TP +\fB\-q\fR +quiet \- do not display the status on the standard error output +.TP +\fB\-\-help\fR +Output help information and exit. +.TP +\fB\-\-version\fR +Output version information and exit. +.SH "FILES" +.LP +\fI/usr/local/bin/mbuffer\fP +.br +\fI/tmp/mbuffer*\fP +.SH "EXAMPLES" +.LP +To run this program with the default options just type: +.LP +mbuffer +.LP +Using mbuffer to do a backup with tar to the default tape device. Options for this example: memory mapped temporary file with a size of 10 Megabytes, start after 80% of the buffer have been filled. +.LP +tar cf \- mydirectory | gzip | mbuffer \-t \-m 10M \-p 80 > $TAPE +.LP +Using mbuffer with 3 tapes for input and extracting the contents in the current work directory (EXPERIMENTAL): +.LP +mbuffer -n 3 -i $TAPE | gzip -dc | tar xf - +.LP +Using mbuffer to write to multiple tape volumes: +.LP +tar cf - /usr | mbuffer -o $TAPE +.SH "AUTHORS" +.LP +Thomas Maier\-Komor + +.SH "SEE ALSO" +.LP +buffer(1) diff -Naur mbuffer-20010515/mbuffer.c mbuffer-20010518/mbuffer.c --- mbuffer-20010515/mbuffer.c Mon May 14 10:28:31 2001 +++ mbuffer-20010518/mbuffer.c Fri May 18 09:43:42 2001 @@ -20,8 +20,8 @@ Numout = 0, Pause = 0, Memmap = 0, Status = 1, Outsize = 0; float Start = 0; char *Tmpfile = 0, **Buffer; -const char *Infile = 0; -int Blocksize = 10240, Numblocks = 256; +const char *Infile = 0, *Outfile = 0; +int Blocksize = 10240, Nooverwrite = O_EXCL, Numblocks = 256; #ifdef EXPERIMENTAL int Multivolume = 0; #endif @@ -136,7 +136,7 @@ ftime(&Starttime); last.time = Starttime.time; last.millitm = Starttime.millitm; - usleep(1000); // needed on alpha (stderr fails with fpe on nan) + usleep(1000); /* needed on alpha (stderr fails with fpe on nan) */ sem_getvalue(&Buf2Dev,&rest); while (!(Finish & (rest == 0))) { fill = (float)rest / (float)Numblocks * 100; @@ -174,7 +174,7 @@ } #ifdef EXPERIMENTAL -void requestVolume() +void requestInputVolume() { close(In); fprintf(Terminal,"\ninsert next volume..."); @@ -204,7 +204,7 @@ err = read(In,Buffer[at] + num,Blocksize - num); #ifdef EXPERIMENTAL if ((!err) && (Terminal) && (Multivolume)) { - requestVolume(); + requestInputVolume(); } else #endif if (-1 == err) { @@ -231,16 +231,38 @@ infomsg("inputThread: exiting..."); } +#ifdef EXPERIMENTAL +void requestOutputVolume() +{ + if (!Outfile) { + errormsg("End of volume, but not end of input:\n" + "Output file must be given (option -o) for multi volume support!\n"); + Finish = 1; + pthread_exit((void *) -1); + } + close(Out); + fprintf(Terminal,"\nvolume full - insert new media and press return whe ready...\n"); + tcflush(fileno(Terminal),TCIFLUSH); + fgetc(Terminal); + fprintf(Terminal,"\nOK - continuing...\n"); + if (-1 == (Out = open(Outfile,Nooverwrite|O_CREAT|O_WRONLY|O_TRUNC|O_SYNC,0666))) { + errormsg("error reopening output file: %s\n",strerror(errno)); + Finish = 1; + pthread_exit((void *) -1); + } +} +#endif + void outputThread() { int at = 0, err, fill, num, rest; if (Start) { infomsg("outputThread: waiting for buffer...\n"); - while (((float) fill / (float) Numblocks) < Start) { + do { usleep(100000); sem_getvalue(&Buf2Dev,&fill); - } + } while (((float) fill / (float) Numblocks) < Start); } fill = -1; infomsg("\noutputThread: starting...\n"); @@ -265,13 +287,7 @@ err = write(Out,Buffer[at++] + num, Outsize > rest ? Outsize : rest ); #ifdef EXPERIMENTAL if ((-1 == err) && (Terminal) && ((errno == ENOMEM) || (errno == ENOSPC))) { - fsync(Out); - fprintf(Terminal,"\nvolume full - insert new media and press return whe ready...\n"); - tcflush(fileno(Terminal),TCIFLUSH); - fgetc(Terminal); - fprintf(Terminal,"\nOK - continuing...\n"); - if (-1 == lseek(Out,0,SEEK_SET)) - errormsg("error seeking to pos 0: %s\n",strerror(errno)); + requestOutputVolume(); continue; } else if (-1 == err) { #else @@ -300,33 +316,11 @@ } } -int getNumber(const char *str) -{ - int i; - char c; - - switch (sscanf(str,"%i%c",&i,&c)) { - case 0: - return -1; // error - case 1: - return i; - default: - } - switch (c) { - case 'k': - case 'K': - return i << 10; - case 'M': - return i << 20; - } - return -1; -} - void version() { fprintf(stderr, "mbuffer version "VERSION"\n"\ - "Copyright 2001 - T. Maier-Komor\n" + "Copyright 2001 - T. Maier-Komor\n"\ "License: GPL2 - see file COPYING\n"); exit(0); } @@ -400,8 +394,7 @@ int main(int argc, char **argv) { - int c, nooverwrite = O_EXCL, totalmem = 0; - const char *outFile = 0; + int c, totalmem = 0; int optMset = 0, optSset = 0, optBset = 0; #ifdef HAVE_ST_BLKSIZE struct stat st; @@ -438,8 +431,8 @@ Infile = argv[c]; debugmsg("Infile set to %s\n",Infile); } else if (!argcheck("-o",argv,&c)) { - outFile = argv[c]; - debugmsg("outFile set to %s\n",outFile); + Outfile = argv[c]; + debugmsg("Outfile set to %s\n",Outfile); } else if (!argcheck("-T",argv,&c)) { Tmpfile = argv[c]; Memmap = 1; @@ -457,7 +450,7 @@ debugmsg("mm set to 1\n"); #endif } else if (!strcmp("-f",argv[c])) { - nooverwrite = 0; + Nooverwrite = 0; debugmsg("overwrite set to 0\n"); } else if (!strcmp("-q",argv[c])) { debugmsg("disabling display of status\n"); @@ -511,8 +504,10 @@ if (-1 == Tmp) fatal("could not create temporary file (%s): %s\n",tmpfile,strerror(errno)); /* resize the file. Needed - at least under linux, who knows why? */ - lseek(Tmp,Numblocks*Blocksize-sizeof(int),SEEK_SET); - write(Tmp,&c,sizeof(int)); + if (-1 == lseek(Tmp,Numblocks*Blocksize-sizeof(int),SEEK_SET)) + fatal("could not resize temporary file: %s\n",strerror(errno)); + if (-1 == write(Tmp,&c,sizeof(int))) + fatal("could not resize temporary file: %s\n",strerror(errno)); Buffer[0] = mmap(0,Blocksize*Numblocks,PROT_READ|PROT_WRITE,MAP_PRIVATE,Tmp,0); if (MAP_FAILED == Buffer[0]) fatal("could not map buffer-file to memory: %s\n",strerror(errno)); @@ -539,8 +534,8 @@ fatal("could not open input file: %s\n",strerror(errno)); } else In = fileno(stdin); - if (outFile) { - if (-1 == (Out = open(outFile,nooverwrite|O_CREAT|O_WRONLY|O_TRUNC,0666))) + if (Outfile) { + if (-1 == (Out = open(Outfile,Nooverwrite|O_CREAT|O_WRONLY|O_TRUNC|O_SYNC,0666))) fatal("could not open output file: %s\n",strerror(errno)); } else Out = fileno(stdout); @@ -572,8 +567,10 @@ } debugmsg("registering signals...\n"); - signal(SIGINT,sigHandler); - signal(SIGTERM,sigHandler); + if (SIG_ERR == signal(SIGINT,sigHandler)) + warningmsg("error registering new SIGINT handler: %s\n",strerror(errno)); + if (SIG_ERR == signal(SIGTERM,sigHandler)) + warningmsg("error registering new SIGINT handler: %s\n",strerror(errno)); debugmsg("starting threads...\n"); pthread_create(&Reader,0,(void *(*)(void *))&inputThread,0);