From 4d5ed2f38cb1dce0244a05f94c8aec7f725a1f33 Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Wed, 21 Feb 2001 16:13:04 +0000 Subject: [PATCH] *** empty log message *** --- compat/include/protocols/dumprestore.h | 10 +- config.h.in | 3 + configure | 123 +++++++++++++++--- configure.in | 13 ++ dump/Makefile.in | 4 +- dump/dump.h | 6 +- dump/main.c | 33 ++++- dump/optr.c | 4 +- dump/tape.c | 167 ++++++++++++++++++------- restore/Makefile.in | 4 +- restore/main.c | 4 +- restore/restore.h | 3 +- restore/tape.c | 71 ++++++++++- 13 files changed, 367 insertions(+), 78 deletions(-) diff --git a/compat/include/protocols/dumprestore.h b/compat/include/protocols/dumprestore.h index a291908..2369120 100644 --- a/compat/include/protocols/dumprestore.h +++ b/compat/include/protocols/dumprestore.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000 * - * $Id: dumprestore.h,v 1.9 2000/12/21 11:14:53 stelian Exp $ + * $Id: dumprestore.h,v 1.10 2001/02/21 16:13:05 stelian Exp $ */ /* @@ -118,5 +118,13 @@ union u_spcl { */ #define DR_NEWHEADER 0x0001 /* new format tape header */ #define DR_NEWINODEFMT 0x0002 /* new format inodes on tape */ +#define DR_COMPRESSED 0x0080 /* dump tape is compressed */ + +/* used for compressed dump tapes */ +struct tapebuf { + int32_t clen; /* compressed length of data */ + int32_t unclen; /* uncompressed length of data */ + char buf[0]; /* the data */ +}; #endif /* !_DUMPRESTORE_H_ */ diff --git a/config.h.in b/config.h.in index c7f3afb..907e5d0 100644 --- a/config.h.in +++ b/config.h.in @@ -50,3 +50,6 @@ /* Define this to 64 if you want Large File System support */ #undef _FILE_OFFSET_BITS + +/* Define this if you have zlib compression library */ +#undef HAVE_ZLIB diff --git a/configure b/configure index 961da28..e61f8d0 100755 --- a/configure +++ b/configure @@ -1825,15 +1825,101 @@ if test "$readline_h" = no -o "$readline_lib" = no; then fi fi +ac_safe=`echo "zlib.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for zlib.h""... $ac_c" 1>&6 +echo "configure:1831: checking for zlib.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + zlib_h=yes +else + echo "$ac_t""no" 1>&6 +zlib_h=no +fi + +echo $ac_n "checking for compress2 in -lz""... $ac_c" 1>&6 +echo "configure:1864: checking for compress2 in -lz" >&5 +ac_lib_var=`echo z'_'compress2 | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lz $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + zlib_lib=yes +else + echo "$ac_t""no" 1>&6 +zlib_lib=no +fi + +if test "$zlib_h" = yes -a "$zlib_lib" = yes; then + ZLIB="-lz" + cat >> confdefs.h <<\EOF +#define HAVE_ZLIB 1 +EOF + +else + ZLIB="" +fi + + for ac_func in err errx verr verrx vwarn vwarnx warn warnx realpath lchown do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1832: checking for $ac_func" >&5 +echo "configure:1918: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1881,12 +1967,12 @@ fi done echo $ac_n "checking for glob""... $ac_c" 1>&6 -echo "configure:1885: checking for glob" >&5 +echo "configure:1971: checking for glob" >&5 if eval "test \"`echo '$''{'ac_cv_func_glob'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_glob=yes" else @@ -1931,7 +2017,7 @@ fi if test "$ac_cv_func_glob" = "yes"; then cat > conftest.$ac_ext < @@ -1959,12 +2045,12 @@ rm -f conftest* fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1963: checking for ANSI C header files" >&5 +echo "configure:2049: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1972,7 +2058,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1976: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2062: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1989,7 +2075,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2007,7 +2093,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -2028,7 +2114,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2039,7 +2125,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2043: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2129: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2063,12 +2149,12 @@ EOF fi echo $ac_n "checking for quad_t""... $ac_c" 1>&6 -echo "configure:2067: checking for quad_t" >&5 +echo "configure:2153: checking for quad_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_quad_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2096,12 +2182,12 @@ EOF fi echo $ac_n "checking for u_quad_t""... $ac_c" 1>&6 -echo "configure:2100: checking for u_quad_t" >&5 +echo "configure:2186: checking for u_quad_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_u_quad_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2308,6 +2394,7 @@ s%@MANGRP@%$MANGRP%g s%@MANMODE@%$MANMODE%g s%@DUMPDATESPATH@%$DUMPDATESPATH%g s%@CPP@%$CPP%g +s%@ZLIB@%$ZLIB%g s%@top_builddir@%$top_builddir%g CEOF diff --git a/configure.in b/configure.in index 7906e16..768a92e 100644 --- a/configure.in +++ b/configure.in @@ -294,6 +294,19 @@ if test "$readline_h" = no -o "$readline_lib" = no; then fi fi +dnl +dnl Check for zlib headers and libraries +dnl +AC_CHECK_HEADER(zlib.h, [zlib_h=yes], [zlib_h=no]) +AC_CHECK_LIB(z, compress2, [zlib_lib=yes], [zlib_lib=no]) +if test "$zlib_h" = yes -a "$zlib_lib" = yes; then + ZLIB="-lz" + AC_DEFINE(HAVE_ZLIB) +else + ZLIB="" +fi +AC_SUBST(ZLIB) + dnl dnl Check for library functions dnl diff --git a/dump/Makefile.in b/dump/Makefile.in index 26819b1..06925e9 100644 --- a/dump/Makefile.in +++ b/dump/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.4 1999/10/11 13:31:10 stelian Exp $ +# $Id: Makefile.in,v 1.5 2001/02/21 16:13:05 stelian Exp $ top_srcdir= @top_srcdir@ srcdir= @srcdir@ @@ -7,7 +7,7 @@ srcdir= @srcdir@ CFLAGS= @CCOPTS@ -pipe $(OPT) $(GINC) $(INC) $(DEFS) @DUMPDEBUG@ LDFLAGS:= $(LDFLAGS) @STATIC@ -LIBS= $(GLIBS) +LIBS= $(GLIBS) @ZLIB@ DEPLIBS= ../compat/lib/libcompat.a PROG= dump diff --git a/dump/dump.h b/dump/dump.h index e215223..c32631b 100644 --- a/dump/dump.h +++ b/dump/dump.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000 * - * $Id: dump.h,v 1.19 2000/12/21 11:14:53 stelian Exp $ + * $Id: dump.h,v 1.20 2001/02/21 16:13:05 stelian Exp $ */ /*- @@ -87,7 +87,9 @@ long asize; /* number of 0.1" units written on current tape */ int etapes; /* estimated number of tapes */ int nonodump; /* if set, do not honor UF_NODUMP user flags */ int unlimited; /* if set, write to end of medium */ - +int compressed; /* if set, dump is to be compressed */ +long long bytes_written;/* total bytes written to tape */ +long uncomprblks; /* uncompressed blocks written to tape */ int notify; /* notify operator flag */ int blockswritten; /* number of blocks written on current tape */ int tapeno; /* current tape number */ diff --git a/dump/main.c b/dump/main.c index 7745e46..eaf5457 100644 --- a/dump/main.c +++ b/dump/main.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.32 2000/12/21 11:14:54 stelian Exp $"; + "$Id: main.c,v 1.33 2001/02/21 16:13:05 stelian Exp $"; #endif /* not lint */ #include @@ -98,6 +98,9 @@ long dev_bsize = 1; /* recalculated below */ long blocksperfile; /* output blocks per file */ char *host = NULL; /* remote host (if any) */ int sizest = 0; /* return size estimate only */ +int compressed = 0; /* use zlib to compress the output */ +long long bytes_written = 0; /* total bytes written */ +long uncomprblks = 0;/* uncompressed blocks written */ #ifdef __linux__ char *__progname; @@ -159,10 +162,18 @@ main(int argc, char *argv[]) obsolete(&argc, &argv); #ifdef KERBEROS +#ifdef HAVE_ZLIB +#define optstring "0123456789aB:b:cd:e:f:F:h:kL:Mns:ST:uWwz" +#else #define optstring "0123456789aB:b:cd:e:f:F:h:kL:Mns:ST:uWw" +#endif /* HAVE_ZLIB */ +#else +#ifdef HAVE_ZLIB +#define optstring "0123456789aB:b:cd:e:f:F:h:L:Mns:ST:uWwz" #else #define optstring "0123456789aB:b:cd:e:f:F:h:L:Mns:ST:uWw" -#endif +#endif /* HAVE_ZLIB */ +#endif /* KERBEROS */ while ((ch = getopt(argc, argv, optstring)) != -1) #undef optstring switch (ch) { @@ -291,6 +302,11 @@ main(int argc, char *argv[]) case 'w': lastdump(ch); exit(X_FINOK); /* do nothing else */ +#ifdef HAVE_ZLIB + case 'z': + compressed = 1; + break; +#endif /* HAVE_ZLIB */ default: usage(); @@ -745,6 +761,13 @@ main(int argc, char *argv[]) msg("Date this dump completed: %s", ctime(&tnow)); msg("Average transfer rate: %ld KB/s\n", xferrate / tapeno); + if (compressed) { + long tapekb = bytes_written / 1024; + double rate = .0005 + (double) spcl.c_tapea / tapekb; + msg("Wrote %ldKB uncompressed, %ldKB compressed," + " compression ratio %1.3f\n", + spcl.c_tapea, tapekb, rate); + } broadcast("DUMP IS DONE!\7\7\n"); msg("DUMP IS DONE\n"); @@ -771,7 +794,11 @@ usage(void) #ifdef KERBEROS "k" #endif - "MnSu] [-B records] [-b blocksize] [-d density]\n" + "MnSu" +#ifdef HAVE_ZLIB + "z" +#endif + "] [-B records] [-b blocksize] [-d density]\n" "\t%s [-e inode#] [-f file] [-h level] [-s feet] [-T date] filesystem\n" "\t%s [-W | -w]\n", __progname, white, __progname); exit(X_STARTUP); diff --git a/dump/optr.c b/dump/optr.c index b186437..9383cf6 100644 --- a/dump/optr.c +++ b/dump/optr.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: optr.c,v 1.18 2000/12/21 11:14:54 stelian Exp $"; + "$Id: optr.c,v 1.19 2001/02/21 16:13:05 stelian Exp $"; #endif /* not lint */ #include @@ -567,7 +567,7 @@ static void print_wmsg(char arg, int dumpme, const char *dev, int level, const char *mtpt, time_t ddate) { - char *date; + char *date = NULL; if (ddate) { char *d; diff --git a/dump/tape.c b/dump/tape.c index 2db739c..ea2faa0 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.30 2001/02/16 13:38:47 stelian Exp $"; + "$Id: tape.c,v 1.31 2001/02/21 16:13:05 stelian Exp $"; #endif /* not lint */ #include @@ -88,6 +88,10 @@ int write(), read(); #include #endif +#ifdef HAVE_ZLIB +#include +#endif /* HAVE_ZLIB */ + #include "dump.h" int writesize; /* size of malloc()ed buffer for tape */ @@ -101,6 +105,7 @@ extern char *host; char *nexttape; extern pid_t rshpid; int eot_code = 1; +long long tapea_bytes = 0; /* bytes_written at start of current volume */ static ssize_t atomic_read __P((int, void *, size_t)); static ssize_t atomic_write __P((int, const void *, size_t)); @@ -125,6 +130,11 @@ struct req { }; int reqsiz; +struct slave_results { + ssize_t unclen; /* uncompressed length */ + ssize_t clen; /* compressed length */ +}; + #define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */ struct slave { int tapea; /* header number at start of this chunk */ @@ -146,7 +156,7 @@ static time_t tstart_volume; /* time of volume start */ static int tapea_volume; /* value of spcl.c_tapea at volume start */ int master; /* pid of master, for sending error signals */ -int tenths; /* length of tape used per block written */ +int tenths; /* length of tape overhead per block written */ static int caught; /* have we caught the signal to proceed? */ static int ready; /* have we reached the lock point without having */ /* received the SIGUSR2 signal from the prev slave? */ @@ -169,8 +179,11 @@ alloctape(void) * variable, 0.30" to 0.45". The gap is maximal when the tape stops. */ if (blocksperfile == 0 && !unlimited) - tenths = writesize / density + - (cartridge ? 16 : density == 625 ? 5 : 8); + tenths = (cartridge ? 16 : density == 625 ? 5 : 8); + else { + tenths = 0; + density = 1; + } /* * Allocate tape buffer contiguous with the array of instruction * packets, so flushtape() can write them together with one write(). @@ -289,14 +302,23 @@ do_stats(void) #else ctime(&tnow)); #endif - msg("Volume %d: %ld tape blocks (%.2fMB)\n", tapeno, - blocks, ((double)blocks * TP_BSIZE / 1048576)); + if (! compressed) + msg("Volume %d %ld tape blocks (%.2fMB)\n", tapeno, + blocks, ((double)blocks * TP_BSIZE / 1048576)); if (ttaken > 0) { + long volkb = (bytes_written - tapea_bytes) / 1024; + long txfrate = volkb / ttaken; msg("Volume %d took %d:%02d:%02d\n", tapeno, ttaken / 3600, (ttaken % 3600) / 60, ttaken % 60); msg("Volume %d transfer rate: %ld KB/s\n", tapeno, - blocks / ttaken); - xferrate += blocks / ttaken; + txfrate); + xferrate += txfrate; + if (compressed) { + double rate = .0005 + (double) blocks / (double) volkb; + msg("Volume %d %ldKB uncompressed, %ldKB compressed," + " compression ratio %1.3f\n", + tapeno, blocks, volkb, rate); + } } return(tnow); } @@ -359,6 +381,7 @@ flushtape(void) { int i, blks, got; long lastfirstrec; + struct slave_results returned; int siz = (char *)nextblock - (char *)slp->req; @@ -375,11 +398,15 @@ flushtape(void) /* Read results back from next slave */ if (slp->sent) { - if (atomic_read( slp->fd, (char *)&got, sizeof got) - != sizeof got) { + if (atomic_read( slp->fd, (char *)&returned, sizeof returned) + != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); } + got = returned.unclen; + bytes_written += returned.clen; + if (returned.unclen == returned.clen) + uncomprblks++; slp->sent = 0; /* Check for errors */ @@ -387,7 +414,7 @@ flushtape(void) tperror(-got); /* Check for end of tape */ - if (got < writesize) { + if (got == 0) { msg("End of tape detected\n"); /* @@ -397,8 +424,8 @@ flushtape(void) for (i = 0; i < SLAVES; i++) { if (slaves[i].sent) { if (atomic_read( slaves[i].fd, - (char *)&got, sizeof got) - != sizeof got) { + (char *)&returned, sizeof returned) + != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); } @@ -424,7 +451,7 @@ flushtape(void) slp->inode = curino; nextblock = slp->tblock; trecno = 0; - asize += tenths; + asize += tenths + returned.clen / density; blockswritten += ntrec; blocksthisvol += ntrec; if (!pipeout && !unlimited && (blocksperfile ? @@ -482,6 +509,7 @@ trewind(void) { int f; int got; + struct slave_results returned; for (f = 0; f < SLAVES; f++) { /* @@ -493,17 +521,21 @@ trewind(void) * fixme: punt for now. */ if (slaves[f].sent) { - if (atomic_read( slaves[f].fd, (char *)&got, sizeof got) - != sizeof got) { + if (atomic_read( slaves[f].fd, (char *)&returned, sizeof returned) + != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); } + got = returned.unclen; + bytes_written += returned.clen; + if (returned.unclen == returned.clen) + uncomprblks++; slaves[f].sent = 0; if (got < 0) tperror(-got); - if (got != writesize) { + if (got == 0) { msg("EOT detected in last 2 tape records!\n"); msg("Use a longer tape, decrease the size estimate\n"); quit("or use no size estimate at all.\n"); @@ -571,6 +603,7 @@ rollforward(void) register struct slave *tslp; int i, size, savedtapea, got; union u_spcl *ntb, *otb; + struct slave_results returned; #ifdef __linux__ int blks; long lastfirstrec; @@ -669,17 +702,21 @@ rollforward(void) * worked ok, otherwise the tape is much too short! */ if (slp->sent) { - if (atomic_read( slp->fd, (char *)&got, sizeof got) - != sizeof got) { + if (atomic_read( slp->fd, (char *)&returned, sizeof returned) + != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); } + got = returned.unclen; + bytes_written += returned.clen; + if (returned.clen == returned.unclen) + uncomprblks++; slp->sent = 0; if (got < 0) tperror(-got); - if (got != writesize) { + if (got == 0) { quit("EOT detected at start of the tape!\n"); } } @@ -695,7 +732,7 @@ rollforward(void) slp->firstrec = lastfirstrec + ntrec; slp->count = lastspclrec + blks + 1 - spcl.c_tapea; slp->inode = curino; - asize += tenths; + asize += tenths + returned.clen / density; blockswritten += ntrec; blocksthisvol += ntrec; #endif @@ -735,6 +772,7 @@ startnewtape(int top) parentpid = getpid(); tapea_volume = spcl.c_tapea; + tapea_bytes = bytes_written; #ifdef __linux__ (void)time4(&tstart_volume); #else @@ -867,6 +905,8 @@ restore_check_point: spcl.c_volume++; spcl.c_type = TS_TAPE; spcl.c_flags |= DR_NEWHEADER; + if (compressed) + spcl.c_flags |= DR_COMPRESSED; writeheader((ino_t)slp->inode); spcl.c_flags &=~ DR_NEWHEADER; msg("Volume %d started at: %s", tapeno, @@ -1010,18 +1050,25 @@ killall(void) } /* - * Synchronization - each process has a lockfile, and shares file - * descriptors to the following process's lockfile. When our write - * completes, we release our lock on the following process's lock- - * file, allowing the following process to lock it and proceed. We - * get the lock back for the next cycle by swapping descriptors. + * Synchronization - each process waits for a SIGUSR2 from the + * previous process before writing to the tape, and sends SIGUSR2 + * to the next process when the tape write completes. On tape errors + * a SIGUSR1 is sent to the master which then terminates all of the + * slaves. */ static void doslave(int cmd, int slave_number) { register int nread; - int nextslave, size, eot_count; + int nextslave, size, eot_count, bufsize; volatile int wrote = 0; + char *buffer; +#ifdef HAVE_ZLIB + struct tapebuf *comp_buf = NULL; + int compresult, complevel = 6, do_compress = 0; + unsigned long worklen; +#endif /* HAVE_ZLIB */ + struct slave_results returns; #ifdef __linux__ errcode_t retval; #endif @@ -1047,6 +1094,15 @@ doslave(int cmd, int slave_number) quit("master/slave protocol botched - didn't get pid of next slave.\n"); } +#ifdef HAVE_ZLIB + /* if we're doing a compressed dump, allocate the compress buffer */ + if (compressed) { + comp_buf = malloc(sizeof(struct tapebuf) + TP_BSIZE + writesize); + if (comp_buf == NULL) + quit("couldn't allocate a compress buffer.\n"); + } +#endif /* HAVE_ZLIB */ + /* * Get list of blocks to dump, read the blocks into tape buffer */ @@ -1055,10 +1111,10 @@ doslave(int cmd, int slave_number) for (trecno = 0; trecno < ntrec; trecno += p->count, p += p->count) { - if (p->dblk) { + if (p->dblk) { /* read a disk block */ bread(p->dblk, slp->tblock[trecno], p->count * TP_BSIZE); - } else { + } else { /* read record from pipe */ if (p->count != 1 || atomic_read( cmd, (char *)slp->tblock[trecno], TP_BSIZE) != TP_BSIZE) @@ -1077,16 +1133,44 @@ doslave(int cmd, int slave_number) wrote = 0; eot_count = 0; size = 0; + buffer = (char *) slp->tblock[0]; /* set write pointer */ + bufsize = writesize; /* length to write */ + returns.clen = returns.unclen = bufsize; + +#ifdef HAVE_ZLIB + /* + * If the data can't be compressed it's written with no + * prefix as writesize bytes. If it's compressible, it's + * written from struct tapebuf with an 8 byte prefix + * followed by the data. This will always be less than + * writesize. Restore, on a short read, can compare the + * length read to the compressed length in the header + * to verify that the read was good. + */ + + if (do_compress) { /* don't compress the first block */ + comp_buf->clen = comp_buf->unclen = bufsize; + worklen = TP_BSIZE + writesize; + compresult = compress2(comp_buf->buf, &worklen, + (char *)slp->tblock[0], writesize, complevel); + if (compresult == Z_OK && worklen <= writesize-32) { + /* write the compressed buffer */ + comp_buf->clen = worklen; + buffer = (char *) comp_buf; + returns.clen = bufsize = worklen + 8; + } + } + /* compress the remaining blocks */ + do_compress = compressed; +#endif /* HAVE_ZLIB */ - while (eot_count < 10 && size < writesize) { + while (eot_count < 10 && size < bufsize) { #ifdef RDUMP if (host) - wrote = rmtwrite(slp->tblock[0]+size, - writesize-size); + wrote = rmtwrite(buffer + size, bufsize - size); else #endif - wrote = write(tapefd, slp->tblock[0]+size, - writesize-size); + wrote = write(tapefd, buffer + size, bufsize - size); #ifdef WRITEDEBUG printf("slave %d wrote %d\n", slave_number, wrote); #endif @@ -1098,9 +1182,9 @@ doslave(int cmd, int slave_number) } #ifdef WRITEDEBUG - if (size != writesize) + if (size != bufsize) printf("slave %d only wrote %d out of %d bytes and gave up.\n", - slave_number, size, writesize); + slave_number, size, bufsize); #endif /* @@ -1112,23 +1196,22 @@ doslave(int cmd, int slave_number) } if (eot_count > 0) - size = 0; + returns.clen = returns.unclen = 0; /* * pass errno back to master for special handling */ if (wrote < 0) - size = -errno; + returns.unclen = -errno; /* - * pass size of write back to master + * pass size of data and size of write back to master * (for EOT handling) */ - (void) atomic_write( cmd, (char *)&size, sizeof size); + (void) atomic_write( cmd, (char *)&returns, sizeof returns); /* - * If partial write, don't want next slave to go. - * Also jolts him awake. + * Signal the next slave to go. */ (void) kill(nextslave, SIGUSR2); } diff --git a/restore/Makefile.in b/restore/Makefile.in index 323d14f..af0b593 100644 --- a/restore/Makefile.in +++ b/restore/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.5 2000/05/29 14:17:37 stelian Exp $ +# $Id: Makefile.in,v 1.6 2001/02/21 16:13:05 stelian Exp $ top_srcdir= @top_srcdir@ srcdir= @srcdir@ @@ -7,7 +7,7 @@ srcdir= @srcdir@ CFLAGS= @CCOPTS@ -pipe $(OPT) $(DEFS) $(GINC) $(INC) @RESTOREDEBUG@ LDFLAGS:= $(LDFLAGS) @STATIC@ -LIBS= $(GLIBS) -le2p @READLINE@ +LIBS= $(GLIBS) -le2p @READLINE@ @ZLIB@ DEPLIBS= ../compat/lib/libcompat.a PROG= restore diff --git a/restore/main.c b/restore/main.c index b2d8c05..1843d4b 100644 --- a/restore/main.c +++ b/restore/main.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.15 2000/12/21 11:14:54 stelian Exp $"; + "$Id: main.c,v 1.16 2001/02/21 16:13:05 stelian Exp $"; #endif /* not lint */ #include @@ -74,7 +74,7 @@ static const char rcsid[] = #include "extern.h" int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; -int hflag = 1, mflag = 1, Nflag = 0; +int hflag = 1, mflag = 1, Nflag = 0, zflag = 0; int uflag = 0; int dokerberos = 0; char command = '\0'; diff --git a/restore/restore.h b/restore/restore.h index 11d38ec..562b910 100644 --- a/restore/restore.h +++ b/restore/restore.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000 * - * $Id: restore.h,v 1.12 2000/12/21 11:14:54 stelian Exp $ + * $Id: restore.h,v 1.13 2001/02/21 16:13:05 stelian Exp $ */ /* @@ -61,6 +61,7 @@ extern int Nflag; /* do not write the disk */ extern int uflag; /* unlink symlink targets */ extern int vflag; /* print out actions taken */ extern int yflag; /* always try to recover from tape errors */ +extern int zflag; /* tape is in compressed format */ /* * Global variables */ diff --git a/restore/tape.c b/restore/tape.c index 015dc87..ae0c725 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -46,7 +46,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.23 2000/12/21 15:01:54 stelian Exp $"; + "$Id: tape.c,v 1.24 2001/02/21 16:13:05 stelian Exp $"; #endif /* not lint */ #include @@ -72,6 +72,10 @@ static const char rcsid[] = #include #include +#ifdef HAVE_ZLIB +#include +#endif /* HAVE_ZLIB */ + #ifdef __linux__ #include #endif @@ -88,6 +92,11 @@ static char magtapeprefix[MAXPATHLEN]; static int blkcnt; static int numtrec; static char *tapebuf; +static char *tbufptr = NULL; /* active tape buffer */ +#ifdef HAVE_ZLIB +static char *comprbuf; /* uncompress work buf */ +static size_t comprlen; +#endif static union u_spcl endoftapemark; static long blksread; /* blocks read since last header */ static long tpblksread = 0; /* TP_BSIZE blocks read */ @@ -115,7 +124,9 @@ static int gethead __P((struct s_spcl *)); static void readtape __P((char *)); static void setdumpnum __P((void)); static u_int swabi __P((u_int)); +#if 0 static u_long swabl __P((u_long)); +#endif static u_char *swab64 __P((u_char *, int)); static u_char *swab32 __P((u_char *, int)); static u_char *swab16 __P((u_char *, int)); @@ -199,6 +210,14 @@ newtapebuf(long size) if (tapebuf == NULL) errx(1, "Cannot allocate space for tape buffer"); tapebufsize = size; +#ifdef HAVE_ZLIB + if (comprbuf != NULL) + free(comprbuf); + comprlen = size * TP_BSIZE; + comprbuf = malloc(comprlen); + if (comprbuf == NULL) + errx(1, "Cannot allocate space for uncompress buffer"); +#endif /* HAVE_ZLIB */ } /* @@ -237,6 +256,15 @@ setup(void) errx(1, "Tape is not a dump tape"); fprintf(stderr, "Converting to new file system format.\n"); } + + if (spcl.c_flags & DR_COMPRESSED) { + fprintf(stderr, "Dump tape is compressed.\n"); +#ifdef HAVE_ZLIB + zflag = 1; +#else + errx(1,"This restore version doesn't support decompression"); +#endif /* HAVE_ZLIB */ + } if (pipein) { endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; endoftapemark.s_spcl.c_type = TS_END; @@ -1218,13 +1246,19 @@ readtape(char *buf) { ssize_t rd, newvol, i; int cnt, seek_failed; +#ifdef HAVE_ZLIB + int cresult; + struct tapebuf* tpb; + unsigned long worklen; +#endif if (blkcnt < numtrec) { - memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); blksread++; tpblksread++; return; } + tbufptr = tapebuf; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; if (numtrec == 0) @@ -1238,6 +1272,28 @@ getmore: else #endif i = read(mt, &tapebuf[rd], cnt); + +#ifdef HAVE_ZLIB + if (i < 0) + goto readerror; + if (i == 0 && !pipein) + goto endoftape; + + if (zflag && i != ntrec * TP_BSIZE) { + tpb = (struct tapebuf *) tapebuf; + if (i != tpb->clen + sizeof(struct tapebuf)) + errx(1,"tape is not a compressed dump tape"); + worklen = comprlen; + cresult = uncompress(comprbuf, &worklen, tpb->buf, tpb->clen); + if (cresult != Z_OK) + errx(1,"tape is not a compressed dump tape"); + if (worklen != tpb->unclen) + errx(1,"decompression error, length mismatch"); + i = worklen; + tbufptr = comprbuf; + } +#endif /* HAVE_ZLIB */ + /* * Check for mid-tape short read error. * If found, skip rest of buffer and start with the next. @@ -1272,6 +1328,9 @@ getmore: /* * Handle read error. */ +#ifdef HAVE_ZLIB +readerror: +#endif if (i < 0) { fprintf(stderr, "Tape read error while "); switch (curfile.action) { @@ -1310,6 +1369,9 @@ getmore: /* * Handle end of tape. */ +#ifdef HAVE_ZLIB +endoftape: +#endif if (i == 0) { Vprintf(stdout, "End-of-tape encountered\n"); if (!pipein) { @@ -1327,7 +1389,7 @@ getmore: memmove(&tapebuf[rd], &endoftapemark, TP_BSIZE); } blkcnt = 0; - memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], TP_BSIZE); + memmove(buf, &tbufptr[(blkcnt++ * TP_BSIZE)], TP_BSIZE); blksread++; tpblksread++; } @@ -1354,6 +1416,7 @@ findtapeblksize(void) (long)i, TP_BSIZE); ntrec = i / TP_BSIZE; numtrec = ntrec; + tbufptr = tapebuf; Vprintf(stdout, "Tape block size is %ld\n", ntrec); } @@ -1791,9 +1854,11 @@ swabi(u_int x) return (x); } +#if 0 static u_long swabl(u_long x) { swabst((u_char *)"l", (u_char *)&x); return (x); } +#endif -- 2.39.2