From 35b24fb7fabcf6df3b37aebf70c228d5b0688d32 Mon Sep 17 00:00:00 2001 From: Stelian Pop Date: Tue, 10 Apr 2001 12:46:53 +0000 Subject: [PATCH] QFA support. --- CHANGES | 11 ++- THANKS | 3 +- config.h.in | 6 ++ configure | 192 ++++++++++++++++++++++++++----------------- configure.in | 26 ++++++ dump/dump.8.in | 11 ++- dump/dump.h | 11 ++- dump/main.c | 47 +++++++++-- dump/tape.c | 57 ++++++++++++- restore/extern.h | 10 ++- restore/main.c | 75 +++++++++++++++-- restore/restore.8.in | 13 ++- restore/restore.c | 76 ++++++++++++++++- restore/restore.h | 12 ++- restore/tape.c | 81 +++++++++++++++++- restore/utilities.c | 75 ++++++++++++++++- 16 files changed, 603 insertions(+), 103 deletions(-) diff --git a/CHANGES b/CHANGES index 942238c..01d6b67 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,4 @@ -$Id: CHANGES,v 1.108 2001/04/06 10:09:39 stelian Exp $ +$Id: CHANGES,v 1.109 2001/04/10 12:46:53 stelian Exp $ Changes between versions 0.4b21 and 0.4b22 (released ????????????????) ====================================================================== @@ -33,6 +33,15 @@ Changes between versions 0.4b21 and 0.4b22 (released ????????????????) 6. Made --prefix option work in configure. All the install path are now based on the configure parameters. +7. Added the Quick File Access mode in dump/restore, contributed + by Uwe Gohlke . In this mode, dump stores in + a file tape position for each inode, and this file is used by + restore (if called with parameter Q and the filename) + to directly position the tape at the file restore is currently + working on. This saves hours when restoring single files from + large backups, saves the tapes and the drive's head. Use + --enable-qfa option of configure to compile in the QFA support. + Changes between versions 0.4b20 and 0.4b21 (released January 13, 2001) ====================================================================== diff --git a/THANKS b/THANKS index 368b771..02c17e7 100644 --- a/THANKS +++ b/THANKS @@ -1,4 +1,4 @@ -$Id: THANKS,v 1.43 2001/02/22 10:57:39 stelian Exp $ +$Id: THANKS,v 1.44 2001/04/10 12:46:53 stelian Exp $ Dump and restore were written by the people of the CSRG at the University of California, Berkeley. @@ -36,6 +36,7 @@ Bernhard Erdmann bernhard.erdmann@gmx.de Jason Fearon jasonf@netrider.org.au Jeremy Fitzhardinge jeremy@goop.org Eirik Fuller eirik@netcom.com +Uwe Gohlke uwe@ugsoft.de Andreas Hasenack andreas@conectiva.com.br Christian Haul haul@informatik.tu-darmstadt.de Jean-Paul van der Jagt jeanpaul@dutepp0.et.tudelft.nl diff --git a/config.h.in b/config.h.in index c08eced..311292a 100644 --- a/config.h.in +++ b/config.h.in @@ -59,3 +59,9 @@ /* Define this if you have zlib compression library */ #undef HAVE_ZLIB + +/* Define this if you want Quick File Access support */ +#undef USE_QFA + +/* Define this if you want to include Quick File Access debugging code */ +#undef DEBUG_QFA diff --git a/configure b/configure index 7b7fc23..b4ce3b2 100755 --- a/configure +++ b/configure @@ -25,6 +25,10 @@ ac_help="$ac_help --enable-oldstylefscript enable old style F script (no arguments)" ac_help="$ac_help --enable-largefile enable Large File System support (your glibc needs to support it)" +ac_help="$ac_help + --enable-qfa enable Quick File Access support" +ac_help="$ac_help + --enable-qfadebug include Quick File Access debugging code" ac_help="$ac_help --with-cc=COMPILER select compiler to use" ac_help="$ac_help @@ -564,7 +568,7 @@ MCONFIG=./MCONFIG echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:568: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:572: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -591,7 +595,7 @@ else fi echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:595: checking whether ln -s works" >&5 +echo "configure:599: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -614,7 +618,7 @@ fi # Extract the first word of "cp", so it can be a program name with args. set dummy cp; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:618: checking for $ac_word" >&5 +echo "configure:622: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_CP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -650,7 +654,7 @@ fi # Extract the first word of "mv", so it can be a program name with args. set dummy mv; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:654: checking for $ac_word" >&5 +echo "configure:658: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_MV'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -686,7 +690,7 @@ fi # Extract the first word of "rm", so it can be a program name with args. set dummy rm; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:690: checking for $ac_word" >&5 +echo "configure:694: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -745,7 +749,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:749: checking host system type" >&5 +echo "configure:753: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -766,7 +770,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:770: checking build system type" >&5 +echo "configure:774: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -792,7 +796,7 @@ fi # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:796: checking for $ac_word" >&5 +echo "configure:800: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -824,7 +828,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:828: checking for $ac_word" >&5 +echo "configure:832: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -859,7 +863,7 @@ fi # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:863: checking for $ac_word" >&5 +echo "configure:867: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -891,7 +895,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:895: checking for $ac_word" >&5 +echo "configure:899: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -926,7 +930,7 @@ fi # Extract the first word of "${ac_tool_prefix}patch", so it can be a program name with args. set dummy ${ac_tool_prefix}patch; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:930: checking for $ac_word" >&5 +echo "configure:934: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_PATCH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -958,7 +962,7 @@ if test -n "$ac_tool_prefix"; then # Extract the first word of "patch", so it can be a program name with args. set dummy patch; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:962: checking for $ac_word" >&5 +echo "configure:966: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_PATCH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -993,7 +997,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:997: checking for $ac_word" >&5 +echo "configure:1001: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1023,7 +1027,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1027: checking for $ac_word" >&5 +echo "configure:1031: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1074,7 +1078,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1078: checking for $ac_word" >&5 +echo "configure:1082: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1106,7 +1110,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1110: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1114: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1117,12 +1121,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1121 "configure" +#line 1125 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1130: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1148,12 +1152,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1152: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1156: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1157: checking whether we are using GNU C" >&5 +echo "configure:1161: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1162,7 +1166,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1170: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1181,7 +1185,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1185: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1189: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1224,7 +1228,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:1228: checking for a BSD compatible install" >&5 +echo "configure:1232: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1409,6 +1413,40 @@ else fi +# Check whether --enable-qfa or --disable-qfa was given. +if test "${enable_qfa+set}" = set; then + enableval="$enable_qfa" + if test "$enableval" = "yes" +then + cat >> confdefs.h <<\EOF +#define USE_QFA 1 +EOF + +fi + +else + echo "Not enabling Quick File Access support" + +fi + + +# Check whether --enable-qfadebug or --disable-qfadebug was given. +if test "${enable_qfadebug+set}" = set; then + enableval="$enable_qfadebug" + if test "$enableval" = "yes" +then + cat >> confdefs.h <<\EOF +#define DEBUG_QFA 1 +EOF + +fi + +else + echo "Not including Quick File Access debugging code" + +fi + + # Check whether --with-cc or --without-cc was given. if test "${with_cc+set}" = set; then withval="$with_cc" @@ -1539,7 +1577,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1543: checking how to run the C preprocessor" >&5 +echo "configure:1581: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1554,13 +1592,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1564: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1602: \"$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 : @@ -1571,13 +1609,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1581: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1619: \"$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 : @@ -1588,13 +1626,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1598: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1636: \"$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 : @@ -1620,17 +1658,17 @@ echo "$ac_t""$CPP" 1>&6 ac_safe=`echo "ext2fs/ext2fs.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for ext2fs/ext2fs.h""... $ac_c" 1>&6 -echo "configure:1624: checking for ext2fs/ext2fs.h" >&5 +echo "configure:1662: checking for ext2fs/ext2fs.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:1634: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1672: \"$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* @@ -1653,7 +1691,7 @@ ext2fs_h=no fi echo $ac_n "checking for ext2fs_open in -lext2fs""... $ac_c" 1>&6 -echo "configure:1657: checking for ext2fs_open in -lext2fs" >&5 +echo "configure:1695: checking for ext2fs_open in -lext2fs" >&5 ac_lib_var=`echo ext2fs'_'ext2fs_open | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1661,7 +1699,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lext2fs -lcom_err $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1698,9 +1736,9 @@ if test "$ext2fs_h" = no -o "$ext2fs_lib" = no; then fi echo $ac_n "checking for ext2_ino_t type in libext2fs headers""... $ac_c" 1>&6 -echo "configure:1702: checking for ext2_ino_t type in libext2fs headers" >&5 +echo "configure:1740: checking for ext2_ino_t type in libext2fs headers" >&5 cat > conftest.$ac_ext < #include @@ -1709,7 +1747,7 @@ int main() { ext2_ino_t ino = 0; ; return 0; } EOF -if { (eval echo configure:1713: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1751: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_EXT2_INO_T 1 @@ -1724,9 +1762,9 @@ fi rm -f conftest* echo $ac_n "checking for s_journal_inum field in ext2_super_block struct""... $ac_c" 1>&6 -echo "configure:1728: checking for s_journal_inum field in ext2_super_block struct" >&5 +echo "configure:1766: checking for s_journal_inum field in ext2_super_block struct" >&5 cat > conftest.$ac_ext < #include @@ -1735,7 +1773,7 @@ int main() { struct ext2_super_block es; es.s_journal_inum = 0; ; return 0; } EOF -if { (eval echo configure:1739: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_EXT2_JOURNAL_INUM 1 @@ -1750,7 +1788,7 @@ fi rm -f conftest* echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 -echo "configure:1754: checking for tgetent in -ltermcap" >&5 +echo "configure:1792: checking for tgetent in -ltermcap" >&5 ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1758,7 +1796,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ltermcap $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1811: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1798,17 +1836,17 @@ fi ac_safe=`echo "readline/readline.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for readline/readline.h""... $ac_c" 1>&6 -echo "configure:1802: checking for readline/readline.h" >&5 +echo "configure:1840: checking for readline/readline.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:1812: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1850: \"$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* @@ -1831,7 +1869,7 @@ readline_h=no fi echo $ac_n "checking for readline in -lreadline""... $ac_c" 1>&6 -echo "configure:1835: checking for readline in -lreadline" >&5 +echo "configure:1873: checking for readline in -lreadline" >&5 ac_lib_var=`echo readline'_'readline | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1839,7 +1877,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lreadline "-ltermcap" $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1892: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1879,17 +1917,17 @@ fi ac_safe=`echo "zlib.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for zlib.h""... $ac_c" 1>&6 -echo "configure:1883: checking for zlib.h" >&5 +echo "configure:1921: 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:1893: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1931: \"$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* @@ -1912,7 +1950,7 @@ zlib_h=no fi echo $ac_n "checking for compress2 in -lz""... $ac_c" 1>&6 -echo "configure:1916: checking for compress2 in -lz" >&5 +echo "configure:1954: 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 @@ -1920,7 +1958,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lz $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1973: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1966,12 +2004,12 @@ 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:1970: checking for $ac_func" >&5 +echo "configure:2008: 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:2036: \"$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 @@ -2019,12 +2057,12 @@ fi done echo $ac_n "checking for glob""... $ac_c" 1>&6 -echo "configure:2023: checking for glob" >&5 +echo "configure:2061: 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:2089: \"$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 @@ -2068,10 +2106,10 @@ fi echo $ac_n "checking for extended glob routines""... $ac_c" 1>&6 -echo "configure:2072: checking for extended glob routines" >&5 +echo "configure:2110: checking for extended glob routines" >&5 if test "$ac_cv_func_glob" = "yes"; then cat > conftest.$ac_ext < @@ -2102,12 +2140,12 @@ rm -f conftest* fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2106: checking for ANSI C header files" >&5 +echo "configure:2144: 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 @@ -2115,7 +2153,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2119: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2157: \"$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* @@ -2132,7 +2170,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 @@ -2150,7 +2188,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 @@ -2171,7 +2209,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2182,7 +2220,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2224: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2206,12 +2244,12 @@ EOF fi echo $ac_n "checking for quad_t""... $ac_c" 1>&6 -echo "configure:2210: checking for quad_t" >&5 +echo "configure:2248: 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 @@ -2239,12 +2277,12 @@ EOF fi echo $ac_n "checking for u_quad_t""... $ac_c" 1>&6 -echo "configure:2243: checking for u_quad_t" >&5 +echo "configure:2281: 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 diff --git a/configure.in b/configure.in index 6f8e57b..b5dd89c 100644 --- a/configure.in +++ b/configure.in @@ -135,6 +135,32 @@ fi echo "Not enabling Large File System support" ) +dnl +dnl Handle --enable-qfa +dnl +AC_ARG_ENABLE([qfa], +[ --enable-qfa enable Quick File Access support], +if test "$enableval" = "yes" +then + AC_DEFINE(USE_QFA) +fi +, +echo "Not enabling Quick File Access support" +) + +dnl +dnl Handle --enable-qfadebug +dnl +AC_ARG_ENABLE([qfadebug], +[ --enable-qfadebug include Quick File Access debugging code], +if test "$enableval" = "yes" +then + AC_DEFINE(DEBUG_QFA) +fi +, +echo "Not including Quick File Access debugging code" +) + dnl dnl set $(CC) from --with-cc=value dnl diff --git a/dump/dump.8.in b/dump/dump.8.in index 52b8713..e162046 100644 --- a/dump/dump.8.in +++ b/dump/dump.8.in @@ -30,7 +30,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: dump.8.in,v 1.24 2001/03/28 12:59:48 stelian Exp $ +.\" $Id: dump.8.in,v 1.25 2001/04/10 12:46:53 stelian Exp $ .\" .Dd __DATE__ .Dt DUMP 8 @@ -49,6 +49,7 @@ .Op Fl F Ar script .Op Fl h Ar level .Op Fl L Ar label +.Op Fl Q Ar file .Op Fl s Ar feet .Op Fl T Ar date .Op Fl z Ar compression level @@ -239,6 +240,14 @@ notify all operators in the group .Dq operator by means similar to a .Xr wall 1 . +.It Fl Q Ar file +Enable the Quick File Access support. Tape positions for each +inode are stored into the file +.Ar file +which is used by restore (if called with parameter Q and the filename) +to directly position the tape at the file restore is currently working +on. This saves hours when restoring single files from large backups, +saves the tapes and the drive's head. .It Fl s Ar feet Attempt to calculate the amount of tape needed at a particular density. If this amount is exceeded, diff --git a/dump/dump.h b/dump/dump.h index 5485ec4..8235858 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.22 2001/03/20 10:02:48 stelian Exp $ + * $Id: dump.h,v 1.23 2001/04/10 12:46:53 stelian Exp $ */ /*- @@ -107,6 +107,15 @@ long dev_bsize; /* block size of underlying disk device */ int dev_bshift; /* log2(dev_bsize) */ int tp_bshift; /* log2(TP_BSIZE) */ +#ifdef USE_QFA +#define QFA_MAGIC "495115637697" +#define QFA_VERSION "1.0" +int gTapeposfd; +char *gTapeposfile; +char gTps[255]; +int GetTapePos __P((long *pos)); +#endif /* USE_QFA */ + #ifndef __P #include #endif diff --git a/dump/main.c b/dump/main.c index b032334..272d597 100644 --- a/dump/main.c +++ b/dump/main.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.41 2001/03/28 12:59:48 stelian Exp $"; + "$Id: main.c,v 1.42 2001/04/10 12:46:53 stelian Exp $"; #endif /* not lint */ #include @@ -89,6 +89,9 @@ int tapeno = 0; /* current tape number */ int density = 0; /* density in bytes/0.1" " <- this is for hilit19 */ int ntrec = NTREC; /* # tape blocks in each tape record */ int cartridge = 0; /* Assume non-cartridge tape */ +#ifdef USE_QFA +int tapepos = 0; /* assume no QFA tapeposition needed by user */ +#endif /* USA_QFA */ int dokerberos = 0; /* Use Kerberos authentication */ long dev_bsize = 1; /* recalculated below */ long blocksperfile; /* output blocks per file */ @@ -153,17 +156,24 @@ main(int argc, char *argv[]) obsolete(&argc, &argv); +#ifdef USE_QFA + gTapeposfd = -1; +#endif /* USA_QFA */ + while ((ch = getopt(argc, argv, "0123456789aB:b:cd:e:f:F:h:L:" #ifdef KERBEROS "k" #endif - "Mns:ST:uWw" + "Mn" +#ifdef USE_QFA + "Q:" +#endif + "s:ST:uWw" #ifdef HAVE_ZLIB "z::" #endif )) != -1) -#undef optstring switch (ch) { /* dump level */ case '0': case '1': case '2': case '3': case '4': @@ -262,6 +272,13 @@ main(int argc, char *argv[]) notify = 1; break; +#ifdef USE_QFA + case 'Q': /* create tapeposfile */ + gTapeposfile = optarg; + tapepos = 1; + break; +#endif /* USA_QFA */ + case 's': /* tape size, feet */ unlimited = 0; tsize = numarg("tape size", 1L, 0L) * 12 * 10; @@ -646,6 +663,21 @@ main(int argc, char *argv[]) tapesize, fetapes); } +#ifdef USE_QFA + if (tapepos) { + msg("writing QFA positions to %s\n", gTapeposfile); + if ((gTapeposfd = open(gTapeposfile, O_RDWR|O_CREAT)) < 0) + quit("can't open tapeposfile\n"); + /* print QFA-file header */ + sprintf(gTps, "%s\n%s\n%ld\n\n", QFA_MAGIC, QFA_VERSION, (unsigned long)spcl.c_date); + if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) + quit("can't write tapeposfile\n"); + sprintf(gTps, "ino\ttapeno\ttapepos\n"); + if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) + quit("can't write tapeposfile\n"); + } +#endif /* USE_QFA */ + /* * Allocate tape buffer. */ @@ -778,8 +810,12 @@ usage(void) "k" #endif "MnSu" - "] [-B records] [-b blocksize]\n" - "\t%s [-d density] [-e inode#] [-f file] [-h level] [-s feet]\n" + "] [-B records] [-b blocksize] [-d density]\n" + "\t%s [-e inode#] [-f file] [-h level] " +#ifdef USE_QFA + "[-Q file] " +#endif + "[-s feet]\n" "\t%s [-T date] " #ifdef HAVE_ZLIB "[-z zlevel] " @@ -891,6 +927,7 @@ obsolete(int *argcp, char **argvp[]) case 'F': case 'h': case 'L': + case 'Q': case 's': case 'T': if (*argv == NULL) { diff --git a/dump/tape.c b/dump/tape.c index 890c77b..8c62acb 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.40 2001/03/28 12:59:48 stelian Exp $"; + "$Id: tape.c,v 1.41 2001/04/10 12:46:53 stelian Exp $"; #endif /* not lint */ #include @@ -68,6 +68,7 @@ int write(), read(); #include #include #include +#include #ifdef __linux__ #include #include @@ -158,6 +159,9 @@ static int ready; /* have we reached the lock point without having */ /* received the SIGUSR2 signal from the prev slave? */ static sigjmp_buf jmpbuf; /* where to jump to if we are ready when the */ /* SIGUSR2 arrives from the previous slave */ +#ifdef USE_QFA +static int gtperr = 0; +#endif int alloctape(void) @@ -860,7 +864,7 @@ restore_check_point: open(tape, O_WRONLY|O_CREAT, 0666))) < 0) #else while ((tapefd = (pipeout ? fileno(stdout) : - open(tape, O_WRONLY|O_CREAT, 0666))) < 0) + open(tape, O_RDWR|O_CREAT, 0666))) < 0) #endif { msg("Cannot open output \"%s\".\n", tape); @@ -1046,6 +1050,11 @@ doslave(int cmd, int slave_number) #ifdef __linux__ errcode_t retval; #endif +#ifdef USE_QFA + long curtapepos; + union u_spcl *uspclptr; + struct s_spcl *spclptr; +#endif /* USA_QFA */ /* * Need our own seek pointer. @@ -1097,6 +1106,29 @@ doslave(int cmd, int slave_number) } } +#ifdef USE_QFA + if (gTapeposfd >= 0) { + uspclptr = (union u_spcl *)&slp->tblock[0]; + spclptr = &uspclptr->s_spcl; + if ((spclptr->c_magic == NFS_MAGIC) && + (spclptr->c_type == TS_INODE)) { + /* if an error occured previously don't + * try again */ + if (gtperr == 0) { + if ((gtperr = GetTapePos(&curtapepos)) == 0) { +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %ld\n", spclptr->c_inumber, curtapepos); +#endif + sprintf(gTps, "%ld\t%d\t%ld\n", (unsigned long)spclptr->c_inumber, tapeno, curtapepos); + if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) { + quit("error writing tapepos file.\n"); + } + } + } + } + } +#endif /* USE_QFA */ + /* Try to write the data... */ wrote = 0; eot_count = 0; @@ -1240,3 +1272,24 @@ atomic_write(int fd, const void *buf, size_t count) } while (got == -1 && errno == EINTR); return (got < 0 ? got : count - need); } + + +#ifdef USE_QFA +/* + * read the current tape position + */ +int +GetTapePos(long *pos) +{ + int err = 0; + + *pos = 0; + if (ioctl(tapefd, MTIOCPOS, pos) == -1) { + err = errno; + msg("[%ld] error: %d (getting tapepos: %ld)\n", getpid(), + err, *pos); + return err; + } + return err; +} +#endif /* USE_QFA */ diff --git a/restore/extern.h b/restore/extern.h index e63a136..c985c20 100644 --- a/restore/extern.h +++ b/restore/extern.h @@ -5,7 +5,7 @@ * Stelian Pop , 1999-2000 * Stelian Pop - Alcôve , 2000 * - * $Id: extern.h,v 1.12 2001/03/20 10:02:48 stelian Exp $ + * $Id: extern.h,v 1.13 2001/04/10 12:46:53 stelian Exp $ */ /*- @@ -125,3 +125,11 @@ int rmtseek __P((int, int)); int fsetflags __P((const char *, unsigned long)); int fgetflags __P((const char *, unsigned long *)); int setflags __P((int, unsigned long)); + +#ifdef USE_QFA +int Inode2Tapepos __P((dump_ino_t, long *, long *, int)); +int GetTapePos __P((long *)); +int GotoTapePos __P((long)); +void ReReadFromTape __P((void)); +void RequestVol __P((long)); +#endif diff --git a/restore/main.c b/restore/main.c index fd00225..8911d20 100644 --- a/restore/main.c +++ b/restore/main.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: main.c,v 1.19 2001/03/23 14:40:12 stelian Exp $"; + "$Id: main.c,v 1.20 2001/04/10 12:46:53 stelian Exp $"; #endif /* not lint */ #include @@ -115,6 +115,10 @@ main(int argc, char *argv[]) char *p, name[MAXPATHLEN]; FILE *filelist = NULL; char fname[MAXPATHLEN]; +#ifdef USE_QFA + time_t tistart, tiend, titaken; + tapeposflag = 0; +#endif /* Temp files should *not* be readable. We set permissions later. */ (void) umask(077); @@ -135,12 +139,16 @@ main(int argc, char *argv[]) for (p = tmpdir + strlen(tmpdir) - 1; p >= tmpdir && *p == '/'; p--) ; obsolete(&argc, &argv); + while ((ch = getopt(argc, argv, + "b:CcdD:f:hi" #ifdef KERBEROS -#define optlist "b:CcdD:f:hikmMNRrs:tT:uvxX:y" -#else -#define optlist "b:CcdD:f:himMNRrs:tT:uvxX:y" + "k" +#endif + "mMN" +#ifdef USE_QFA + "Q:" #endif - while ((ch = getopt(argc, argv, optlist)) != -1) + "Rrs:tT:uvxX:y")) != -1) switch(ch) { case 'b': /* Change default tape blocksize. */ @@ -198,6 +206,12 @@ main(int argc, char *argv[]) case 'N': Nflag = 1; break; +#ifdef USE_QFA + case 'Q': + gTapeposfile = optarg; + tapeposflag = 1; + break; +#endif case 's': /* Dumpnum (skip to) for multifile dump tapes. */ dumpnum = strtol(optarg, &p, 10); @@ -248,6 +262,45 @@ main(int argc, char *argv[]) *--argv = "."; } +#ifdef USE_QFA + if (tapeposflag) { + msg("reading QFA positions from %s\n", gTapeposfile); + if ((gTapeposfp = fopen(gTapeposfile, "r")) == NULL) + errx(1, "can't open file for reading -- %s", + gTapeposfile); + /* start reading header info */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; /* delete end of line */ + if (strcmp(gTps, QFA_MAGIC) != 0) + errx(1, "not requested format of -- %s", gTapeposfile); + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + if (strcmp(gTps, QFA_VERSION) != 0) + errx(1, "not requested format of -- %s", gTapeposfile); + /* read dumpdate */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + /* TODO: check dumpdate from QFA file with current dump file's + * dump date */ + /* if not equal either output warning and continue without QFA + * or abort */ + /* read empty line */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + /* read table header line */ + if (fgets(gTps, sizeof(gTps), gTapeposfp) == NULL) + errx(1, "not requested format of -- %s", gTapeposfile); + gTps[strlen(gTps) - 1] = 0; + /* end reading header info */ + /* tape position table starts here */ + gSeekstart = ftell(gTapeposfp); /* remember for later use */ +} +#endif /* USE_QFA */ + switch (command) { /* * Compare contents of tape. @@ -375,6 +428,9 @@ main(int argc, char *argv[]) * Batch extraction of tape contents. */ case 'x': +#ifdef USE_QFA + tistart = time(NULL); +#endif setup(); extractdirs(1); initsymtable((char *)0); @@ -395,6 +451,14 @@ main(int argc, char *argv[]) setdirmodes(0); if (dflag) checkrestore(); +#ifdef USE_QFA + tiend = time(NULL); + titaken = tiend - tistart; +#ifdef USE_QFA + msg("restore took %d:%02d:%02d\n", titaken / 3600, + (titaken % 3600) / 60, titaken % 60); +#endif +#endif break; } exit(0); @@ -464,6 +528,7 @@ obsolete(int *argcp, char **argvp[]) case 'b': case 'D': case 'f': + case 'Q': case 's': case 'T': case 'X': diff --git a/restore/restore.8.in b/restore/restore.8.in index 7903d7e..441fec4 100644 --- a/restore/restore.8.in +++ b/restore/restore.8.in @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: restore.8.in,v 1.12 2001/03/23 14:40:12 stelian Exp $ +.\" $Id: restore.8.in,v 1.13 2001/04/10 12:46:53 stelian Exp $ .\" .Dd __DATE__ .Dt RESTORE 8 @@ -44,6 +44,7 @@ .Op Fl b Ar blocksize .Op Fl D Ar filesystem .Op Fl f Ar file +.Op Fl Q Ar file .Op Fl s Ar fileno .Op Fl T Ar directory .Nm restore @@ -51,6 +52,7 @@ .Op Fl chkmMNuvy .Op Fl b Ar blocksize .Op Fl f Ar file +.Op Fl Q Ar file .Op Fl s Ar fileno .Op Fl T Ar directory .Nm restore @@ -58,6 +60,7 @@ .Op Fl ckMNuvy .Op Fl b Ar blocksize .Op Fl f Ar file +.Op Fl Q Ar file .Op Fl s Ar fileno .Op Fl T Ar directory .Nm restore @@ -65,6 +68,7 @@ .Op Fl ckMNuvy .Op Fl b Ar blocksize .Op Fl f Ar file +.Op Fl Q Ar file .Op Fl s Ar fileno .Op Fl T Ar directory .Nm restore @@ -72,6 +76,7 @@ .Op Fl chkMNuvy .Op Fl b Ar blocksize .Op Fl f Ar file +.Op Fl Q Ar file .Op Fl s Ar fileno .Op Fl T Ar directory .Op Fl X Ar filelist @@ -81,6 +86,7 @@ .Op Fl chkmMNuvy .Op Fl b Ar blocksize .Op Fl f Ar file +.Op Fl Q Ar file .Op Fl s Ar fileno .Op Fl T Ar directory .Op Fl X Ar filelist @@ -364,6 +370,11 @@ The flag causes .Nm to only print file names. Files are not extracted. +.It Fl Q Ar file +Use the file +.Ar file +in order to read tape position as stored using the dump Quick File +Access mode. .It Fl s Ar fileno Read from the specified .Ar fileno diff --git a/restore/restore.c b/restore/restore.c index bc38b65..8615204 100644 --- a/restore/restore.c +++ b/restore/restore.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: restore.c,v 1.14 2001/03/20 10:02:48 stelian Exp $"; + "$Id: restore.c,v 1.15 2001/04/10 12:46:53 stelian Exp $"; #endif /* not lint */ #include @@ -76,11 +76,23 @@ long listfile(char *name, dump_ino_t ino, int type) { long descend = hflag ? GOOD : FAIL; +#ifdef USE_QFA + long tnum; + long tpos; +#endif if (TSTINO(ino, dumpmap) == 0) return (descend); Vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir "); - fprintf(stdout, "%10lu\t%s\n", (unsigned long)ino, name); +#ifdef USE_QFA + if (tapeposflag) { /* add QFA positions to output */ + (void)Inode2Tapepos(ino, &tnum, &tpos, 1); + fprintf(stdout, "%10lu\t%ld\t%ld\t%s\n", (unsigned long)ino, + tnum, tpos, name); + } + else +#endif + fprintf(stdout, "%10lu\t%s\n", (unsigned long)ino, name); return (descend); } @@ -782,6 +794,10 @@ createfiles(void) register dump_ino_t first, next, last; register struct entry *ep; long curvol; +#ifdef USE_QFA + long tnum, tpos, curtpos, tmpcnt; + time_t tistart, tiend, titaken; +#endif Vprintf(stdout, "Extract requested files\n"); curfile.action = SKIP; @@ -791,6 +807,9 @@ createfiles(void) first = lowerbnd(ROOTINO); last = upperbnd(maxino - 1); for (;;) { +#ifdef USE_QFA + tmpcnt = 1; +#endif first = lowerbnd(first); last = upperbnd(last); /* @@ -814,13 +833,64 @@ createfiles(void) * or an out of order volume change is encountered */ next = lowerbnd(curfile.ino); +#ifdef USE_QFA + tistart = time(NULL); + if (tapeposflag) { + /* get tape position for inode (position directly) */ + (void)Inode2Tapepos(next, &tnum, &tpos, 1); + if (tpos == 0) + /* get tape position for last available inode + * (position before) */ + (void)Inode2Tapepos(next, &tnum, &tpos, 0); + if (tpos != 0) { + if (tnum != volno) + (void)RequestVol(tnum); + if (GetTapePos(&curtpos) == 0) { + /* curtpos +1000 ???, some drives + * might be too slow */ + if (tpos > curtpos) { +#ifdef DEBUG_QFA + msg("positioning tape %ld from %ld to %ld for inode %10lu ...\n", volno, curtpos, tpos, (unsigned long)next); +#endif + if (GotoTapePos(tpos) == 0) { +#ifdef DEBUG_QFA + if (GetTapePos(&curtpos) == 0) + msg("before resnyc at tape position %ld\n", curtpos); +#endif + (void)ReReadFromTape(); +#ifdef DEBUG_QFA + if (GetTapePos(&curtpos) == 0) + msg("after resync at tape position %ld\n", curtpos); +#endif + } + } + } + } + } +#endif /* USA_QFA */ + do { curvol = volno; - while (next > curfile.ino && volno == curvol) + while (next > curfile.ino && volno == curvol) { +#ifdef USE_QFA + ++tmpcnt; +#endif skipfile(); + } skipmaps(); skipdirs(); } while (volno == curvol + 1); +#ifdef USE_QFA + tiend = time(NULL); + titaken = tiend - tistart; +#ifdef DEBUG_QFA + if (titaken / 60 > 0) + msg("%ld reads took %d:%02d:%02d\n", + tmpcnt, titaken / 3600, + (titaken % 3600) / 60, titaken % 60); +#endif +#endif /* USE_QFA */ + /* * If volume change out of order occurred the * current state must be recalculated diff --git a/restore/restore.h b/restore/restore.h index 6c77e5a..dba1ddc 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.14 2001/03/20 10:02:48 stelian Exp $ + * $Id: restore.h,v 1.15 2001/04/10 12:46:53 stelian Exp $ */ /* @@ -161,3 +161,13 @@ typedef struct rstdirdesc RST_DIR; #define GOOD 1 #define FAIL 0 + +#ifdef USE_QFA +#define QFA_MAGIC "495115637697" +#define QFA_VERSION "1.0" +FILE *gTapeposfp; +char *gTapeposfile; +char gTps[255]; +long gSeekstart; +int tapeposflag; +#endif /* USE_QFA */ diff --git a/restore/tape.c b/restore/tape.c index 63eae65..f434143 100644 --- a/restore/tape.c +++ b/restore/tape.c @@ -46,7 +46,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.31 2001/03/27 08:09:21 stelian Exp $"; + "$Id: tape.c,v 1.32 2001/04/10 12:46:53 stelian Exp $"; #endif /* not lint */ #include @@ -82,6 +82,9 @@ static const char rcsid[] = #include "extern.h" #include "pathnames.h" +#ifdef USE_QFA +int noresyncmesg = 0; +#endif /* USE_QFA */ static long fssize = MAXBSIZE; static int mt = -1; static int pipein = 0; @@ -2095,8 +2098,11 @@ findinode(struct s_spcl *header) } } while (header->c_type == TS_ADDR); if (skipcnt > 0) - fprintf(stderr, "resync restore, skipped %ld blocks\n", - skipcnt); +#ifdef USE_QFA + if (!noresyncmesg) +#endif + fprintf(stderr, "resync restore, skipped %ld blocks\n", + skipcnt); skipcnt = 0; } @@ -2250,3 +2256,72 @@ swabl(u_long x) return (x); } #endif + +#ifdef USE_QFA +/* + * get the current position of the tape + */ +int +GetTapePos(long *pos) +{ + int err = 0; + + *pos = 0; + if (ioctl(mt, MTIOCPOS, pos) == -1) { + err = errno; + fprintf(stdout, "[%ld] error: %d (getting tapepos: %ld)\n", + (unsigned long)getpid(), err, *pos); + return err; + } + return err; +} + +typedef struct mt_pos { + short mt_op; + int mt_count; +} MTPosRec, *MTPosPtr; + +/* + * go to specified position on tape + */ +int +GotoTapePos(long pos) +{ + int err = 0; + struct mt_pos buf; + + buf.mt_op = MTSEEK; + buf.mt_count = pos; + if (ioctl(mt, MTIOCTOP, &buf) == -1) { + err = errno; + fprintf(stdout, "[%ld] error: %d (setting tapepos: %ld)\n", + (unsigned long)getpid(), err, pos); + return err; + } + return err; +} + +/* + * read next data from tape to re-sync + */ +void +ReReadFromTape(void) +{ + FLUSHTAPEBUF(); + noresyncmesg = 1; + if (gethead(&spcl) == FAIL) { +#ifdef DEBUG_QFA + fprintf(stdout, "DEBUG 1 gethead failed\n"); +#endif + } + findinode(&spcl); + noresyncmesg = 0; +} + +void +RequestVol(long tnum) +{ + FLUSHTAPEBUF(); + getvol(tnum); +} +#endif /* USE_QFA */ diff --git a/restore/utilities.c b/restore/utilities.c index 34f9f8d..e2bf2e2 100644 --- a/restore/utilities.c +++ b/restore/utilities.c @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: utilities.c,v 1.13 2001/03/20 10:02:48 stelian Exp $"; + "$Id: utilities.c,v 1.14 2001/04/10 12:46:53 stelian Exp $"; #endif /* not lint */ #include @@ -465,3 +465,76 @@ panic(fmt, va_alist) exit(1); } } + +#ifdef USE_QFA +/* + * search for ino in QFA file + * + * if exactmatch: + * if ino found return tape number and tape position + * if ino not found return tnum=0 and tpos=0 + * + * if not exactmatch: + * if ino found return tape number and tape position + * if ino not found return tape number and tape position of last smaller ino + * if no smaller inode found return tnum=0 and tpos=0 + */ +int +Inode2Tapepos(dump_ino_t ino, long *tnum, long *tpos, int exactmatch) +{ + char *p, *pp; + char numbuff[32]; + unsigned long tmpino; + long tmptnum; + long tmptpos; + + *tpos = 0; + *tnum = 0; + if (fseek(gTapeposfp, gSeekstart, SEEK_SET) == -1) + return errno; + while (fgets(gTps, sizeof(gTps), gTapeposfp) != NULL) { + gTps[strlen(gTps) - 1] = 0; /* delete end of line */ + p = gTps; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read inode */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + tmpino = atol(numbuff); + if (*p == 0) + return 1; /* may NOT happen */ + p++; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read tapenum */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + if (*p == 0) + return 1; /* may NOT happen */ + tmptnum = atol(numbuff); + p++; + bzero(numbuff, sizeof(numbuff)); + pp = numbuff; + /* read tapepos */ + while ((*p != 0) && (*p != '\t')) + *pp++ = *p++; + tmptpos = atol(numbuff); + + if (exactmatch) { + if (tmpino == ino) { + *tnum = tmptnum; + *tpos = tmptpos; + return 0; + } + } else { + if (tmpino > ino) { + return 0; + } else { + *tnum = tmptnum; + *tpos = tmptpos; + } + } + } + return 0; +} +#endif /* USE_QFA */ -- 2.39.2