From 75c8f56ea801b916a43e807e56bb9149b0ecf653 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 23 Oct 2002 09:16:06 +0000 Subject: [PATCH] First cut 1.27 see kes23Oct02 git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@172 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 57 ++- bacula/Makefile.in | 6 +- bacula/autoconf/config.h.in | 3 + bacula/autoconf/configure.in | 7 +- bacula/configure | 651 +++++++++++++++-------------- bacula/kernstodo | 75 ++-- bacula/src/baconfig.h | 37 +- bacula/src/cats/sql_create.c | 2 +- bacula/src/cl | 19 + bacula/src/dird/Makefile.in | 6 +- bacula/src/dird/authenticate.c | 3 +- bacula/src/dird/backup.c | 29 +- bacula/src/dird/bacula-dir.conf.in | 1 + bacula/src/dird/catreq.c | 11 +- bacula/src/dird/dird_conf.c | 6 +- bacula/src/dird/dird_conf.h | 211 +++++----- bacula/src/dird/getmsg.c | 2 +- bacula/src/dird/msgchan.c | 4 +- bacula/src/dird/ua_restore.c | 1 + bacula/src/dird/verify.c | 1 + bacula/src/filed/authenticate.c | 4 + bacula/src/filed/backup.c | 180 ++++---- bacula/src/filed/filed.h | 1 - bacula/src/filed/protos.h | 1 + bacula/src/filed/restore.c | 128 ++++-- bacula/src/filed/win32/winmain.cpp | 1 + bacula/src/findlib/Makefile.in | 6 +- bacula/src/findlib/attribs.c | 407 ++++++++++++++++++ bacula/src/findlib/create_file.c | 186 +++++++++ bacula/src/findlib/find.c | 3 + bacula/src/findlib/find.h | 64 +-- bacula/src/findlib/find_one.c | 48 +-- bacula/src/findlib/makepath.c | 396 ++++++++++++++++++ bacula/src/findlib/match.c | 4 + bacula/src/findlib/protos.h | 59 +++ bacula/src/findlib/save-cwd.c | 115 +++++ bacula/src/findlib/save-cwd.h | 18 + bacula/src/jcr.h | 1 + bacula/src/lib/Makefile.in | 10 +- bacula/src/lib/base64.c | 102 +---- bacula/src/lib/bnet.c | 21 +- bacula/src/lib/bsock.h | 20 +- bacula/src/lib/btime.c | 18 +- bacula/src/lib/btime.h | 48 ++- bacula/src/lib/cram-md5.c | 20 +- bacula/src/lib/crc32.c | 20 +- bacula/src/lib/hmac.c | 20 +- bacula/src/lib/lex.c | 18 +- bacula/src/lib/md5.h | 20 +- bacula/src/lib/parse_conf.c | 4 +- bacula/src/lib/protos.h | 25 +- bacula/src/lib/tree.c | 1 - bacula/src/lib/util.c | 43 +- bacula/src/stored/Makefile.in | 16 +- bacula/src/stored/acquire.c | 15 +- bacula/src/stored/append.c | 28 +- bacula/src/stored/askdir.c | 10 +- bacula/src/stored/authenticate.c | 4 + bacula/src/stored/bextract.c | 176 +++++--- bacula/src/stored/block.c | 46 +- bacula/src/stored/block.h | 13 +- bacula/src/stored/bls.c | 55 +-- bacula/src/stored/bscan.c | 117 ++++-- bacula/src/stored/btape.c | 323 +++++--------- bacula/src/stored/butil.c | 103 ++++- bacula/src/stored/dev.c | 58 +-- bacula/src/stored/dev.h | 2 +- bacula/src/stored/device.c | 18 +- bacula/src/stored/dircmd.c | 55 ++- bacula/src/stored/job.c | 14 +- bacula/src/stored/label.c | 60 ++- bacula/src/stored/mount.c | 4 +- bacula/src/stored/protos.h | 15 +- bacula/src/stored/read_record.c | 3 +- bacula/src/stored/record.c | 60 ++- bacula/src/stored/record.h | 101 ++--- bacula/src/stored/stored.c | 18 +- bacula/src/tools/testfind.c | 16 +- bacula/src/version.h | 6 +- 79 files changed, 3024 insertions(+), 1456 deletions(-) create mode 100644 bacula/src/cl create mode 100755 bacula/src/findlib/attribs.c create mode 100644 bacula/src/findlib/create_file.c create mode 100644 bacula/src/findlib/makepath.c create mode 100644 bacula/src/findlib/protos.h create mode 100644 bacula/src/findlib/save-cwd.c create mode 100644 bacula/src/findlib/save-cwd.h diff --git a/bacula/ChangeLog b/bacula/ChangeLog index ef7dfc497f..48b5ec82f4 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,58 @@ +2002-mm-dd Version 1.27 (22Oct02) not yet released +General: from kes23Oct02 +- I have mainly worked on getting all the details of a Restore + to work correctly (new tape format, support for Win32 + attributes, ...) +- Trademarked name Bacula. +- Implement Bacula tape format 11 (1.0 Immortal). This format + will be maintained forever. +- Accept Any Volume is yes by default. This modifies Bacula's behavior + when writing tapes. + +Changes submitted this submission: +- Corrected a bug on FreeBSD where CFLAGS would get a "yes". I was + unable to reproduce this, but a user confirmed the correction. + It was a problem with detection of largefile support, which FreeBSD + has by default. +- Added a new "license" chapter in the manual. Re-licensed a number of + library routines (bnet.c, hmac.c md5.c, cram-md5, ...) with LGPL so that they + can be used in proprietary software to access Bacula if so desired. +- Move Director's AutoChanger doc to correct location (in Storage + resource). +- Document why trademark (to protect compatibility). +- Implement and turned on Bacula tape format 11 (also BB02). This + format moves the VolSessionId and VolSessionTime from each record + header into the Block header. This is MUCH more efficient when reading + records as now whole blocks can be skipped. + Also added JobStatus in End Of Session record, and added MD5 for + FileSet, which is necessary to insure uniqueness. +- Implement a new Bacula time format for btime_t. It is Epoch time + in microseconds (i.e. base 1 Jan 1970 in microseconds). + This replaces previous floating point times. +- Added Win32 extended attributes. In doing so, I moved all attribute + handling from src/lib into src/findlib. Added new streams for + Win32 attributes and for GZIP Win32 attributes. +- Modified "Accept Any Volume" so that it really permits any volume + in the pool to be mounted. +- Removed "Mount Anonymous Volumes" from Storage daemon config. +- Implemented sparse files. You must add "sparse=yes" on the include line + for it to be enabled. +- Print "None" in backup summary rather than 0.0% if there is no compression + enabled. +- Improved error checking in daemon connection/authentication code to prevent + garbage data from harming a Bacula daemon. +- All daemon tools MUST have a config file. +- Completely strip drive specification on Win32 if a Where prefix is specified. +- Corrected DB info for writing to files. Now the File Address is stored + in File-Block variables in the catalog. +- All Storage daemon tools now use common code for acquiring/reading + Volumes. +- If a device is unmounted, report it even if the device is not open. This + will help inform users who have BLOCKED Bacula by unmounting a drive. + + +============================================================================= 2002-10-12 Version 1.26 (10Oct02) General: from kes10Oct02 - Changed Job name conventions to avoid : which is an illegal @@ -150,11 +204,12 @@ Changes submitted this submission: - Fix Volume in bsr. - Move autochanger code to new subroutine in mount.c - +============================================================================= 2002-09-05 Version 1.25a (05Sep02) Released - Fix unitialized stack variable in bextract so it will always read the currently mounted tape. +============================================================================= 2002-09-04 Version 1.25 (01Sep02) Released General: - Added .cvsignore files in each directory to cut down on the diff --git a/bacula/Makefile.in b/bacula/Makefile.in index a625f74472..eff60474a4 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -145,11 +145,7 @@ clean: @$(RMF) *~ 1 2 3 core core.* config.guess console.log console.sum -# distclean goal is for making a clean source tree, but if you have run -# configure from a different directory, then doesn't destroy all your -# hardly compiled and linked stuff. That's why there is always $(srcdir)/ -# In that case most of those commands do nothing, except cleaning *~ -# and cleaning source links. +# clean for distribution distclean: @for I in $(subdirs); do (cd $$I; $(MAKE) $@ || exit 1); done @for I in $(subdirs); do (cd $$I; $(RMF) startit stopit btraceback btraceback.gdb); done diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index ac49e75470..a10fc39d97 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -277,6 +277,8 @@ #undef HAVE_GETOPT_LONG +#undef HAVE_INET_PTON + /* The number of bytes in a char. */ #undef SIZEOF_CHAR @@ -483,3 +485,4 @@ /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES + diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index 2a86c70286..6a3f7cdcde 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -681,6 +681,7 @@ dnl A few others AC_EXEEXT dnl See if we can use 64 bit file addresses +largefile_support="no" AC_SYS_LARGEFILE @@ -1094,7 +1095,7 @@ freebsd) platforms/freebsd/bacula-sd \ platforms/freebsd/bacula-dir" hostname=`hostname -s` - ac_cv_sys_largefile_CFLAGS="yes" + largefile_support="yes" ;; hpux) DISTVER=`uname -r` @@ -1263,7 +1264,7 @@ chmod 755 src/cats/make_bdb_tables src/cats/drop_bdb_tables chmod 755 src/cats/create_bdb_database if test "x$ac_cv_sys_largefile_CFLAGS" != "xno" ; then - ac_cv_sys_largefile_CFLAGS="yes" + largefile_support="yes" fi @@ -1294,7 +1295,7 @@ Configuration on `date`: Working directory ${working_dir} SQL binaries Directory ${SQL_BINDIR} - Large file support: $ac_cv_sys_largefile_CFLAGS + Large file support: $largefile_support readline support: ${got_readline} ${PRTREADLINE_SRC} cweb support: ${got_cweb} ${CWEB_SRC} TCP Wrappers support: ${TCPW_MSG} diff --git a/bacula/configure b/bacula/configure index f909a8e4fc..74e5b4ff39 100755 --- a/bacula/configure +++ b/bacula/configure @@ -4124,8 +4124,9 @@ echo "$ac_t""${ac_cv_exeext}" 1>&6 ac_exeext=$EXEEXT +largefile_support="no" echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:4129: checking build system type" >&5 +echo "configure:4130: checking build system type" >&5 build_alias=$build case "$build_alias" in @@ -4159,7 +4160,7 @@ fi # Extract the first word of "${ac_tool_prefix}getconf", so it can be a program name with args. set dummy ${ac_tool_prefix}getconf; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:4163: checking for $ac_word" >&5 +echo "configure:4164: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_GETCONF'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4189,7 +4190,7 @@ fi echo $ac_n "checking for CFLAGS value to request large file support""... $ac_c" 1>&6 -echo "configure:4193: checking for CFLAGS value to request large file support" >&5 +echo "configure:4194: checking for CFLAGS value to request large file support" >&5 if eval "test \"`echo '$''{'ac_cv_sys_largefile_CFLAGS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4204,14 +4205,14 @@ else ac_save_CC="$CC" CC="$CC $ac_cv_sys_largefile_CFLAGS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then : else echo "configure: failed program was:" >&5 @@ -4227,7 +4228,7 @@ fi echo "$ac_t""$ac_cv_sys_largefile_CFLAGS" 1>&6 echo $ac_n "checking for LDFLAGS value to request large file support""... $ac_c" 1>&6 -echo "configure:4231: checking for LDFLAGS value to request large file support" >&5 +echo "configure:4232: checking for LDFLAGS value to request large file support" >&5 if eval "test \"`echo '$''{'ac_cv_sys_largefile_LDFLAGS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4239,7 +4240,7 @@ fi echo "$ac_t""$ac_cv_sys_largefile_LDFLAGS" 1>&6 echo $ac_n "checking for LIBS value to request large file support""... $ac_c" 1>&6 -echo "configure:4243: checking for LIBS value to request large file support" >&5 +echo "configure:4244: checking for LIBS value to request large file support" >&5 if eval "test \"`echo '$''{'ac_cv_sys_largefile_LIBS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4294,7 +4295,7 @@ echo "$ac_t""$ac_cv_sys_largefile_LIBS" 1>&6 esac ;; esac echo $ac_n "checking for _FILE_OFFSET_BITS""... $ac_c" 1>&6 -echo "configure:4298: checking for _FILE_OFFSET_BITS" >&5 +echo "configure:4299: checking for _FILE_OFFSET_BITS" >&5 if eval "test \"`echo '$''{'ac_cv_sys_file_offset_bits'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4323,7 +4324,7 @@ EOF fi echo $ac_n "checking for _LARGEFILE_SOURCE""... $ac_c" 1>&6 -echo "configure:4327: checking for _LARGEFILE_SOURCE" >&5 +echo "configure:4328: checking for _LARGEFILE_SOURCE" >&5 if eval "test \"`echo '$''{'ac_cv_sys_largefile_source'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4352,7 +4353,7 @@ EOF fi echo $ac_n "checking for _LARGE_FILES""... $ac_c" 1>&6 -echo "configure:4356: checking for _LARGE_FILES" >&5 +echo "configure:4357: checking for _LARGE_FILES" >&5 if eval "test \"`echo '$''{'ac_cv_sys_large_files'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -4389,7 +4390,7 @@ EOF # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 -echo "configure:4393: checking for X" >&5 +echo "configure:4394: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -4451,12 +4452,12 @@ if test "$ac_x_includes" = NO; then # First, try using that file with no special directory specified. cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4460: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4461: \"$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* @@ -4525,14 +4526,14 @@ if test "$ac_x_libraries" = NO; then ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4537: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. @@ -4638,17 +4639,17 @@ else case "`(uname -sr) 2>/dev/null`" in "SunOS 5"*) echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 -echo "configure:4642: checking whether -R must be followed by a space" >&5 +echo "configure:4643: checking whether -R must be followed by a space" >&5 ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_nospace=yes else @@ -4664,14 +4665,14 @@ rm -f conftest* else LIBS="$ac_xsave_LIBS -R $x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4676: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_space=yes else @@ -4703,7 +4704,7 @@ rm -f conftest* # libraries were built with DECnet support. And karl@cs.umb.edu says # the Alpha needs dnet_stub (dnet does not exist). echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 -echo "configure:4707: checking for dnet_ntoa in -ldnet" >&5 +echo "configure:4708: checking for dnet_ntoa in -ldnet" >&5 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4711,7 +4712,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4727: \"$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 @@ -4744,7 +4745,7 @@ fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 -echo "configure:4748: checking for dnet_ntoa in -ldnet_stub" >&5 +echo "configure:4749: checking for dnet_ntoa in -ldnet_stub" >&5 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4752,7 +4753,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldnet_stub $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4768: \"$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 @@ -4792,12 +4793,12 @@ fi # The nsl library prevents programs from opening the X display # on Irix 5.2, according to dickey@clark.net. echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:4796: checking for gethostbyname" >&5 +echo "configure:4797: checking for gethostbyname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+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:4825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else @@ -4841,7 +4842,7 @@ fi if test $ac_cv_func_gethostbyname = no; then echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:4845: checking for gethostbyname in -lnsl" >&5 +echo "configure:4846: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4849,7 +4850,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4865: \"$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 @@ -4890,12 +4891,12 @@ fi # -lsocket must be given before -lnsl if both are needed. # We assume that if connect needs -lnsl, so does gethostbyname. echo $ac_n "checking for connect""... $ac_c" 1>&6 -echo "configure:4894: checking for connect" >&5 +echo "configure:4895: checking for connect" >&5 if eval "test \"`echo '$''{'ac_cv_func_connect'+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:4923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_connect=yes" else @@ -4939,7 +4940,7 @@ fi if test $ac_cv_func_connect = no; then echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 -echo "configure:4943: checking for connect in -lsocket" >&5 +echo "configure:4944: checking for connect in -lsocket" >&5 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4947,7 +4948,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4963: \"$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 @@ -4982,12 +4983,12 @@ fi # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. echo $ac_n "checking for remove""... $ac_c" 1>&6 -echo "configure:4986: checking for remove" >&5 +echo "configure:4987: checking for remove" >&5 if eval "test \"`echo '$''{'ac_cv_func_remove'+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:5015: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_remove=yes" else @@ -5031,7 +5032,7 @@ fi if test $ac_cv_func_remove = no; then echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 -echo "configure:5035: checking for remove in -lposix" >&5 +echo "configure:5036: checking for remove in -lposix" >&5 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5039,7 +5040,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lposix $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5055: \"$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 @@ -5074,12 +5075,12 @@ fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. echo $ac_n "checking for shmat""... $ac_c" 1>&6 -echo "configure:5078: checking for shmat" >&5 +echo "configure:5079: checking for shmat" >&5 if eval "test \"`echo '$''{'ac_cv_func_shmat'+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:5107: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_shmat=yes" else @@ -5123,7 +5124,7 @@ fi if test $ac_cv_func_shmat = no; then echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 -echo "configure:5127: checking for shmat in -lipc" >&5 +echo "configure:5128: checking for shmat in -lipc" >&5 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5131,7 +5132,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lipc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5147: \"$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 @@ -5175,7 +5176,7 @@ fi # libraries we check for below, so use a different variable. # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 -echo "configure:5179: checking for IceConnectionNumber in -lICE" >&5 +echo "configure:5180: checking for IceConnectionNumber in -lICE" >&5 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5183,7 +5184,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5199: \"$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 @@ -5239,17 +5240,17 @@ for ac_hdr in \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5243: checking for $ac_hdr" >&5 +echo "configure:5244: checking for $ac_hdr" >&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:5253: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5254: \"$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* @@ -5276,12 +5277,12 @@ fi done echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:5280: checking for ANSI C header files" >&5 +echo "configure:5281: 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 @@ -5289,7 +5290,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5293: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5294: \"$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* @@ -5306,7 +5307,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 @@ -5324,7 +5325,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 @@ -5345,7 +5346,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -5356,7 +5357,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:5360: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5361: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -5380,19 +5381,19 @@ EOF fi echo $ac_n "checking whether sys/types.h defines makedev""... $ac_c" 1>&6 -echo "configure:5384: checking whether sys/types.h defines makedev" >&5 +echo "configure:5385: checking whether sys/types.h defines makedev" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_types_h_makedev'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { return makedev(0, 0); ; return 0; } EOF -if { (eval echo configure:5396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5397: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_sys_types_h_makedev=yes else @@ -5410,17 +5411,17 @@ echo "$ac_t""$ac_cv_header_sys_types_h_makedev" 1>&6 if test $ac_cv_header_sys_types_h_makedev = no; then ac_safe=`echo "sys/mkdev.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/mkdev.h""... $ac_c" 1>&6 -echo "configure:5414: checking for sys/mkdev.h" >&5 +echo "configure:5415: checking for sys/mkdev.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:5424: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5425: \"$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* @@ -5448,17 +5449,17 @@ fi if test $ac_cv_header_sys_mkdev_h = no; then ac_safe=`echo "sys/sysmacros.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/sysmacros.h""... $ac_c" 1>&6 -echo "configure:5452: checking for sys/sysmacros.h" >&5 +echo "configure:5453: checking for sys/sysmacros.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:5462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5463: \"$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* @@ -5490,12 +5491,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:5494: checking for $ac_hdr that defines DIR" >&5 +echo "configure:5495: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> @@ -5503,7 +5504,7 @@ int main() { DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:5507: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5508: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -5528,7 +5529,7 @@ done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:5532: checking for opendir in -ldir" >&5 +echo "configure:5533: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5536,7 +5537,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5552: \"$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 @@ -5569,7 +5570,7 @@ fi else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:5573: checking for opendir in -lx" >&5 +echo "configure:5574: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5577,7 +5578,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5593: \"$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 @@ -5611,12 +5612,12 @@ fi fi echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:5615: checking whether stat file-mode macros are broken" >&5 +echo "configure:5616: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5667,12 +5668,12 @@ EOF fi echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:5671: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo "configure:5672: checking for sys/wait.h that is POSIX.1 compatible" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5688,7 +5689,7 @@ wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:5692: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5693: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -5709,12 +5710,12 @@ EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:5713: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:5714: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5723,7 +5724,7 @@ int main() { struct tm *tp; ; return 0; } EOF -if { (eval echo configure:5727: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5728: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -5744,12 +5745,12 @@ EOF fi echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6 -echo "configure:5748: checking for st_blksize in struct stat" >&5 +echo "configure:5749: checking for st_blksize in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5757,7 +5758,7 @@ int main() { struct stat s; s.st_blksize; ; return 0; } EOF -if { (eval echo configure:5761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blksize=yes else @@ -5778,12 +5779,12 @@ EOF fi echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6 -echo "configure:5782: checking for st_blocks in struct stat" >&5 +echo "configure:5783: checking for st_blocks in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5791,7 +5792,7 @@ int main() { struct stat s; s.st_blocks; ; return 0; } EOF -if { (eval echo configure:5795: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5796: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blocks=yes else @@ -5814,12 +5815,12 @@ else fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:5818: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:5819: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5827,7 +5828,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:5831: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5832: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -5848,12 +5849,12 @@ EOF fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 -echo "configure:5852: checking for tm_zone in struct tm" >&5 +echo "configure:5853: checking for tm_zone in struct tm" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_cv_struct_tm> @@ -5861,7 +5862,7 @@ int main() { struct tm tm; tm.tm_zone; ; return 0; } EOF -if { (eval echo configure:5865: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5866: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else @@ -5881,12 +5882,12 @@ EOF else echo $ac_n "checking for tzname""... $ac_c" 1>&6 -echo "configure:5885: checking for tzname" >&5 +echo "configure:5886: checking for tzname" >&5 if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #ifndef tzname /* For SGI. */ @@ -5896,7 +5897,7 @@ int main() { atoi(*tzname); ; return 0; } EOF -if { (eval echo configure:5900: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5901: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_var_tzname=yes else @@ -5923,12 +5924,12 @@ fi # be POSIX, POSIX_C, ALL, HPUX or whatever, depending on the machine. echo $ac_n "checking for utime.h""... $ac_c" 1>&6 -echo "configure:5927: checking for utime.h" >&5 +echo "configure:5928: checking for utime.h" >&5 if eval "test \"`echo '$''{'tar_cv_header_utime_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -5937,7 +5938,7 @@ int main() { struct utimbuf foo ; return 0; } EOF -if { (eval echo configure:5941: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* tar_cv_header_utime_h=yes else @@ -5956,12 +5957,12 @@ EOF echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:5960: checking for working const" >&5 +echo "configure:5961: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6015: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -6033,17 +6034,17 @@ fi echo $ac_n "checking how to get filesystem type""... $ac_c" 1>&6 -echo "configure:6037: checking how to get filesystem type" >&5 +echo "configure:6038: checking how to get filesystem type" >&5 fstype=no # The order of these tests is important. cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6047: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6048: \"$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* @@ -6059,13 +6060,13 @@ fi rm -f conftest* if test $fstype = no; then cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6069: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6070: \"$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* @@ -6082,13 +6083,13 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6092: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6093: \"$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* @@ -6105,12 +6106,12 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6114: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6115: \"$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* @@ -6127,7 +6128,7 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < EOF @@ -6144,13 +6145,13 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:6154: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:6155: \"$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* @@ -6168,12 +6169,12 @@ fi echo "$ac_t""$fstype" 1>&6 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:6172: checking return type of signal handlers" >&5 +echo "configure:6173: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6190,7 +6191,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:6194: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6195: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -6210,13 +6211,13 @@ EOF echo $ac_n "checking for type of signal functions""... $ac_c" 1>&6 -echo "configure:6214: checking for type of signal functions" >&5 +echo "configure:6215: checking for type of signal functions" >&5 if eval "test \"`echo '$''{'bash_cv_signal_vintage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -6229,7 +6230,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* bash_cv_signal_vintage=posix else @@ -6238,7 +6239,7 @@ else rm -rf conftest* cat > conftest.$ac_ext < int main() { @@ -6248,7 +6249,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6252: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6253: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* bash_cv_signal_vintage=4.2bsd else @@ -6257,7 +6258,7 @@ else rm -rf conftest* cat > conftest.$ac_ext < @@ -6270,7 +6271,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6274: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6275: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* bash_cv_signal_vintage=svr3 else @@ -6309,12 +6310,12 @@ EOF fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 -echo "configure:6313: checking for mode_t" >&5 +echo "configure:6314: checking for mode_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6342,12 +6343,12 @@ EOF fi echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:6346: checking for uid_t in sys/types.h" >&5 +echo "configure:6347: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -6376,12 +6377,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:6380: checking for size_t" >&5 +echo "configure:6381: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6409,12 +6410,12 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:6413: checking for pid_t" >&5 +echo "configure:6414: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6442,12 +6443,12 @@ EOF fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:6446: checking for off_t" >&5 +echo "configure:6447: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6475,12 +6476,12 @@ EOF fi echo $ac_n "checking for ino_t""... $ac_c" 1>&6 -echo "configure:6479: checking for ino_t" >&5 +echo "configure:6480: checking for ino_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_ino_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6508,12 +6509,12 @@ EOF fi echo $ac_n "checking for dev_t""... $ac_c" 1>&6 -echo "configure:6512: checking for dev_t" >&5 +echo "configure:6513: checking for dev_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_dev_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6541,12 +6542,12 @@ EOF fi echo $ac_n "checking for daddr_t""... $ac_c" 1>&6 -echo "configure:6545: checking for daddr_t" >&5 +echo "configure:6546: checking for daddr_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_daddr_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6574,12 +6575,12 @@ EOF fi echo $ac_n "checking for major_t""... $ac_c" 1>&6 -echo "configure:6578: checking for major_t" >&5 +echo "configure:6579: checking for major_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_major_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6607,12 +6608,12 @@ EOF fi echo $ac_n "checking for minor_t""... $ac_c" 1>&6 -echo "configure:6611: checking for minor_t" >&5 +echo "configure:6612: checking for minor_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_minor_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6640,12 +6641,12 @@ EOF fi echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 -echo "configure:6644: checking for ssize_t" >&5 +echo "configure:6645: checking for ssize_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6673,12 +6674,12 @@ EOF fi echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6 -echo "configure:6677: checking for st_blocks in struct stat" >&5 +echo "configure:6678: checking for st_blocks in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6686,7 +6687,7 @@ int main() { struct stat s; s.st_blocks; ; return 0; } EOF -if { (eval echo configure:6690: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6691: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blocks=yes else @@ -6709,12 +6710,12 @@ else fi echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6 -echo "configure:6713: checking for st_rdev in struct stat" >&5 +echo "configure:6714: checking for st_rdev in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6722,7 +6723,7 @@ int main() { struct stat s; s.st_rdev; ; return 0; } EOF -if { (eval echo configure:6726: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6727: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_rdev=yes else @@ -6743,12 +6744,12 @@ EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:6747: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:6748: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6756,7 +6757,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:6760: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -6777,12 +6778,12 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:6781: checking for working const" >&5 +echo "configure:6782: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6836: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -6854,7 +6855,7 @@ fi echo $ac_n "checking size of char""... $ac_c" 1>&6 -echo "configure:6858: checking size of char" >&5 +echo "configure:6859: checking size of char" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_char'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6862,7 +6863,7 @@ else ac_cv_sizeof_char=1 else cat > conftest.$ac_ext < int main() @@ -6873,7 +6874,7 @@ int main() return(0); } EOF -if { (eval echo configure:6877: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6878: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_char=`cat conftestval` else @@ -6893,7 +6894,7 @@ EOF echo $ac_n "checking size of short int""... $ac_c" 1>&6 -echo "configure:6897: checking size of short int" >&5 +echo "configure:6898: checking size of short int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6901,7 +6902,7 @@ else ac_cv_sizeof_short_int=2 else cat > conftest.$ac_ext < int main() @@ -6912,7 +6913,7 @@ int main() return(0); } EOF -if { (eval echo configure:6916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_short_int=`cat conftestval` else @@ -6932,7 +6933,7 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:6936: checking size of int" >&5 +echo "configure:6937: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6940,7 +6941,7 @@ else ac_cv_sizeof_int=4 else cat > conftest.$ac_ext < int main() @@ -6951,7 +6952,7 @@ int main() return(0); } EOF -if { (eval echo configure:6955: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6956: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int=`cat conftestval` else @@ -6971,7 +6972,7 @@ EOF echo $ac_n "checking size of long int""... $ac_c" 1>&6 -echo "configure:6975: checking size of long int" >&5 +echo "configure:6976: checking size of long int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6979,7 +6980,7 @@ else ac_cv_sizeof_long_int=4 else cat > conftest.$ac_ext < int main() @@ -6990,7 +6991,7 @@ int main() return(0); } EOF -if { (eval echo configure:6994: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6995: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_int=`cat conftestval` else @@ -7010,7 +7011,7 @@ EOF echo $ac_n "checking size of long long int""... $ac_c" 1>&6 -echo "configure:7014: checking size of long long int" >&5 +echo "configure:7015: checking size of long long int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7018,7 +7019,7 @@ else ac_cv_sizeof_long_long_int=8 else cat > conftest.$ac_ext < int main() @@ -7029,7 +7030,7 @@ int main() return(0); } EOF -if { (eval echo configure:7033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7034: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_long_int=`cat conftestval` else @@ -7049,7 +7050,7 @@ EOF echo $ac_n "checking size of int *""... $ac_c" 1>&6 -echo "configure:7053: checking size of int *" >&5 +echo "configure:7054: checking size of int *" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int_p'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7057,7 +7058,7 @@ else ac_cv_sizeof_int_p=4 else cat > conftest.$ac_ext < int main() @@ -7068,7 +7069,7 @@ int main() return(0); } EOF -if { (eval echo configure:7072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7073: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int_p=`cat conftestval` else @@ -7090,20 +7091,20 @@ EOF # Check for sys/types.h types echo $ac_n "checking for u_int type""... $ac_c" 1>&6 -echo "configure:7094: checking for u_int type" >&5 +echo "configure:7095: checking for u_int type" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_int a; a = 1; ; return 0; } EOF -if { (eval echo configure:7107: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7108: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_int="yes" else @@ -7127,20 +7128,20 @@ EOF fi echo $ac_n "checking for intmax_t type""... $ac_c" 1>&6 -echo "configure:7131: checking for intmax_t type" >&5 +echo "configure:7132: checking for intmax_t type" >&5 if eval "test \"`echo '$''{'ac_cv_have_intmax_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:7144: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7145: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_intmax_t="yes" else @@ -7149,14 +7150,14 @@ else rm -rf conftest* cat > conftest.$ac_ext < int main() { intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:7160: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7161: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_intmax_t="yes" else @@ -7186,20 +7187,20 @@ fi echo $ac_n "checking for u_intmax_t type""... $ac_c" 1>&6 -echo "configure:7190: checking for u_intmax_t type" >&5 +echo "configure:7191: checking for u_intmax_t type" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_intmax_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:7203: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_intmax_t="yes" else @@ -7208,14 +7209,14 @@ else rm -rf conftest* cat > conftest.$ac_ext < int main() { u_intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:7219: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7220: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_intmax_t="yes" else @@ -7244,20 +7245,20 @@ fi echo $ac_n "checking for intXX_t types""... $ac_c" 1>&6 -echo "configure:7248: checking for intXX_t types" >&5 +echo "configure:7249: checking for intXX_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_intxx_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int8_t a; int16_t b; int32_t c; a = b = c = 1; ; return 0; } EOF -if { (eval echo configure:7261: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7262: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_intxx_t="yes" else @@ -7281,20 +7282,20 @@ EOF fi echo $ac_n "checking for int64_t type""... $ac_c" 1>&6 -echo "configure:7285: checking for int64_t type" >&5 +echo "configure:7286: checking for int64_t type" >&5 if eval "test \"`echo '$''{'ac_cv_have_int64_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int64_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:7298: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7299: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_int64_t="yes" else @@ -7318,20 +7319,20 @@ EOF fi echo $ac_n "checking for u_intXX_t types""... $ac_c" 1>&6 -echo "configure:7322: checking for u_intXX_t types" >&5 +echo "configure:7323: checking for u_intXX_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_intxx_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1; ; return 0; } EOF -if { (eval echo configure:7335: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7336: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_intxx_t="yes" else @@ -7355,20 +7356,20 @@ EOF fi echo $ac_n "checking for u_int64_t types""... $ac_c" 1>&6 -echo "configure:7359: checking for u_int64_t types" >&5 +echo "configure:7360: checking for u_int64_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_int64_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_int64_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:7372: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7373: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_int64_t="yes" else @@ -7395,9 +7396,9 @@ if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then echo $ac_n "checking for intXX_t and u_intXX_t types in sys/bitypes.h""... $ac_c" 1>&6 -echo "configure:7399: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 +echo "configure:7400: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 cat > conftest.$ac_ext < int main() { @@ -7406,7 +7407,7 @@ int main() { a = b = c = e = f = g = 1; ; return 0; } EOF -if { (eval echo configure:7410: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7411: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_U_INTXX_T 1 @@ -7433,13 +7434,13 @@ fi if test -z "$have_u_intxx_t" ; then echo $ac_n "checking for uintXX_t types""... $ac_c" 1>&6 -echo "configure:7437: checking for uintXX_t types" >&5 +echo "configure:7438: checking for uintXX_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_uintxx_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -7447,7 +7448,7 @@ int main() { uint32_t c; a = b = c = 1; ; return 0; } EOF -if { (eval echo configure:7451: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7452: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_uintxx_t="yes" else @@ -7487,12 +7488,12 @@ for ac_func in \ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7491: checking for $ac_func" >&5 +echo "configure:7492: 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:7520: \"$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 @@ -7545,12 +7546,12 @@ done for ac_func in fchdir do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7549: checking for $ac_func" >&5 +echo "configure:7550: 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:7578: \"$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 @@ -7604,12 +7605,12 @@ done for ac_func in snprintf vsnprintf gethostid getdomainname do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7608: checking for $ac_func" >&5 +echo "configure:7609: 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:7637: \"$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 @@ -7660,12 +7661,12 @@ done for ac_func in localtime_r readdir_r strerror_r gethostbyname_r do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7664: checking for $ac_func" >&5 +echo "configure:7665: 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:7693: \"$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 @@ -7715,12 +7716,12 @@ done # If resolver functions are not in libc check for -lnsl or -lresolv. echo $ac_n "checking for gethostbyname_r""... $ac_c" 1>&6 -echo "configure:7719: checking for gethostbyname_r" >&5 +echo "configure:7720: checking for gethostbyname_r" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname_r'+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:7748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname_r=yes" else @@ -7761,7 +7762,7 @@ if eval "test \"`echo '$ac_cv_func_'gethostbyname_r`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gethostbyname_r in -lnsl""... $ac_c" 1>&6 -echo "configure:7765: checking for gethostbyname_r in -lnsl" >&5 +echo "configure:7766: checking for gethostbyname_r in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname_r | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -7769,7 +7770,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7785: \"$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 @@ -7808,7 +7809,7 @@ else fi echo $ac_n "checking for gethostbyname_r in -lresolv""... $ac_c" 1>&6 -echo "configure:7812: checking for gethostbyname_r in -lresolv" >&5 +echo "configure:7813: checking for gethostbyname_r in -lresolv" >&5 ac_lib_var=`echo resolv'_'gethostbyname_r | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -7816,7 +7817,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7832: \"$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 @@ -7860,12 +7861,12 @@ fi # Find where sockets are (especially for Solaris) echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:7864: checking for socket" >&5 +echo "configure:7865: checking for socket" >&5 if eval "test \"`echo '$''{'ac_cv_func_socket'+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:7893: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_socket=yes" else @@ -7906,7 +7907,7 @@ if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for socket in -lxnet""... $ac_c" 1>&6 -echo "configure:7910: checking for socket in -lxnet" >&5 +echo "configure:7911: checking for socket in -lxnet" >&5 ac_lib_var=`echo xnet'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -7914,7 +7915,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lxnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7930: \"$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 @@ -7953,7 +7954,7 @@ else fi echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:7957: checking for socket in -lsocket" >&5 +echo "configure:7958: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -7961,7 +7962,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7977: \"$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 @@ -8000,7 +8001,7 @@ else fi echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6 -echo "configure:8004: checking for socket in -linet" >&5 +echo "configure:8005: checking for socket in -linet" >&5 ac_lib_var=`echo inet'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8008,7 +8009,7 @@ else ac_save_LIBS="$LIBS" LIBS="-linet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8024: \"$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 @@ -8052,12 +8053,12 @@ fi for ac_func in inet_pton do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8056: checking for $ac_func" >&5 +echo "configure:8057: 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:8085: \"$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 @@ -8109,12 +8110,12 @@ done echo $ac_n "checking for strftime""... $ac_c" 1>&6 -echo "configure:8113: checking for strftime" >&5 +echo "configure:8114: checking for strftime" >&5 if eval "test \"`echo '$''{'ac_cv_func_strftime'+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:8142: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strftime=yes" else @@ -8159,7 +8160,7 @@ else echo "$ac_t""no" 1>&6 # strftime is in -lintl on SCO UNIX. echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 -echo "configure:8163: checking for strftime in -lintl" >&5 +echo "configure:8164: checking for strftime in -lintl" >&5 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8167,7 +8168,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8183: \"$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 @@ -8205,12 +8206,12 @@ fi fi echo $ac_n "checking for vprintf""... $ac_c" 1>&6 -echo "configure:8209: checking for vprintf" >&5 +echo "configure:8210: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+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:8238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vprintf=yes" else @@ -8257,12 +8258,12 @@ fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 -echo "configure:8261: checking for _doprnt" >&5 +echo "configure:8262: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+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:8290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func__doprnt=yes" else @@ -8312,19 +8313,19 @@ fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:8316: checking for working alloca.h" >&5 +echo "configure:8317: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:8328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8329: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -8345,12 +8346,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:8349: checking for alloca" >&5 +echo "configure:8350: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+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:8383: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -8410,12 +8411,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:8414: checking whether alloca needs Cray hooks" >&5 +echo "configure:8415: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:8444: checking for $ac_func" >&5 +echo "configure:8445: 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:8473: \"$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 @@ -8495,7 +8496,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:8499: checking stack direction for C alloca" >&5 +echo "configure:8500: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8503,7 +8504,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -8545,7 +8546,7 @@ fi # getmntent is in -lsun on Irix 4, -lseq on Dynix/PTX, -lgen on Unixware. echo $ac_n "checking for getmntent in -lsun""... $ac_c" 1>&6 -echo "configure:8549: checking for getmntent in -lsun" >&5 +echo "configure:8550: checking for getmntent in -lsun" >&5 ac_lib_var=`echo sun'_'getmntent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8553,7 +8554,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsun $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8569: \"$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 @@ -8583,7 +8584,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for getmntent in -lseq""... $ac_c" 1>&6 -echo "configure:8587: checking for getmntent in -lseq" >&5 +echo "configure:8588: checking for getmntent in -lseq" >&5 ac_lib_var=`echo seq'_'getmntent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8591,7 +8592,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lseq $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8607: \"$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 @@ -8621,7 +8622,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for getmntent in -lgen""... $ac_c" 1>&6 -echo "configure:8625: checking for getmntent in -lgen" >&5 +echo "configure:8626: checking for getmntent in -lgen" >&5 ac_lib_var=`echo gen'_'getmntent | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8629,7 +8630,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lgen $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8645: \"$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 @@ -8665,12 +8666,12 @@ fi fi echo $ac_n "checking for getmntent""... $ac_c" 1>&6 -echo "configure:8669: checking for getmntent" >&5 +echo "configure:8670: checking for getmntent" >&5 if eval "test \"`echo '$''{'ac_cv_func_getmntent'+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:8698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_getmntent=yes" else @@ -8716,7 +8717,7 @@ else fi echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6 -echo "configure:8720: checking whether closedir returns void" >&5 +echo "configure:8721: checking whether closedir returns void" >&5 if eval "test \"`echo '$''{'ac_cv_func_closedir_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8724,13 +8725,13 @@ else ac_cv_func_closedir_void=yes else cat > conftest.$ac_ext < #include <$ac_header_dirent> int closedir(); main() { exit(closedir(opendir(".")) != 0); } EOF -if { (eval echo configure:8734: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_closedir_void=no else @@ -8753,7 +8754,7 @@ EOF fi echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:8757: checking whether setpgrp takes no argument" >&5 +echo "configure:8758: checking whether setpgrp takes no argument" >&5 if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8761,7 +8762,7 @@ else { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8786: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_setpgrp_void=no else @@ -8804,7 +8805,7 @@ EOF fi echo $ac_n "checking for working fnmatch""... $ac_c" 1>&6 -echo "configure:8808: checking for working fnmatch" >&5 +echo "configure:8809: checking for working fnmatch" >&5 if eval "test \"`echo '$''{'ac_cv_func_fnmatch_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -8815,11 +8816,11 @@ if test "$cross_compiling" = yes; then ac_cv_func_fnmatch_works=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_func_fnmatch_works=yes else @@ -8844,7 +8845,7 @@ fi echo $ac_n "checking for setlocale in -lxpg4""... $ac_c" 1>&6 -echo "configure:8848: checking for setlocale in -lxpg4" >&5 +echo "configure:8849: checking for setlocale in -lxpg4" >&5 ac_lib_var=`echo xpg4'_'setlocale | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8852,7 +8853,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lxpg4 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8868: \"$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 @@ -8886,7 +8887,7 @@ fi echo $ac_n "checking for getpwnam in -lsun""... $ac_c" 1>&6 -echo "configure:8890: checking for getpwnam in -lsun" >&5 +echo "configure:8891: checking for getpwnam in -lsun" >&5 ac_lib_var=`echo sun'_'getpwnam | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8894,7 +8895,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsun $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8910: \"$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 @@ -8937,17 +8938,17 @@ for ac_hdr in zlib.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:8941: checking for $ac_hdr" >&5 +echo "configure:8942: checking for $ac_hdr" >&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:8951: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:8952: \"$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* @@ -8974,7 +8975,7 @@ fi done echo $ac_n "checking for deflate in -lz""... $ac_c" 1>&6 -echo "configure:8978: checking for deflate in -lz" >&5 +echo "configure:8979: checking for deflate in -lz" >&5 ac_lib_var=`echo z'_'deflate | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -8982,7 +8983,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:8998: \"$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 @@ -9024,7 +9025,7 @@ fi PTHREAD_LIB="" echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6 -echo "configure:9028: checking for pthread_create in -lpthread" >&5 +echo "configure:9029: checking for pthread_create in -lpthread" >&5 ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -9032,7 +9033,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthread $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9048: \"$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 @@ -9062,7 +9063,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6 -echo "configure:9066: checking for pthread_create in -lpthreads" >&5 +echo "configure:9067: checking for pthread_create in -lpthreads" >&5 ac_lib_var=`echo pthreads'_'pthread_create | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -9070,7 +9071,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthreads $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9086: \"$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 @@ -9100,7 +9101,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6 -echo "configure:9104: checking for pthread_create in -lc_r" >&5 +echo "configure:9105: checking for pthread_create in -lc_r" >&5 ac_lib_var=`echo c_r'_'pthread_create | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -9108,7 +9109,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lc_r $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:9124: \"$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 @@ -9138,12 +9139,12 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create""... $ac_c" 1>&6 -echo "configure:9142: checking for pthread_create" >&5 +echo "configure:9143: checking for pthread_create" >&5 if eval "test \"`echo '$''{'ac_cv_func_pthread_create'+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:9171: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_pthread_create=yes" else @@ -9284,7 +9285,7 @@ freebsd) platforms/freebsd/bacula-sd \ platforms/freebsd/bacula-dir" hostname=`hostname -s` - ac_cv_sys_largefile_CFLAGS="yes" + largefile_support="yes" ;; hpux) DISTVER=`uname -r` @@ -9992,7 +9993,7 @@ chmod 755 src/cats/make_bdb_tables src/cats/drop_bdb_tables chmod 755 src/cats/create_bdb_database if test "x$ac_cv_sys_largefile_CFLAGS" != "xno" ; then - ac_cv_sys_largefile_CFLAGS="yes" + largefile_support="yes" fi @@ -10023,7 +10024,7 @@ Configuration on `date`: Working directory ${working_dir} SQL binaries Directory ${SQL_BINDIR} - Large file support: $ac_cv_sys_largefile_CFLAGS + Large file support: $largefile_support readline support: ${got_readline} ${PRTREADLINE_SRC} cweb support: ${got_cweb} ${CWEB_SRC} TCP Wrappers support: ${TCPW_MSG} diff --git a/bacula/kernstodo b/bacula/kernstodo index bf80aa79e1..93d95f18ab 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,38 +1,43 @@ Kern's ToDo List - 7 October 2002 + 23 October 2002 -Irix conversion notes: -- no uuencode -- no hostname To do: -- Document passwords. -- Document running multiple Jobs - Document that two Verifys at same time on same client do not work. - Document how to recycle a tape in 7 days even if the backup takes a long time. - Document default config file locations. -- Document better includes (does it cross file systems ?). +- Document better Include (does it cross file systems ?). - Document specifically how to add new File daemon to config files. -- Document forcing a new tape to be used. -- Document "Error in message.c:500 Mail program terminated in error. - -From Chuck: ---bindir is wrong and does not reflect prefix= in the *_sqlite_* scripts - (src/cats) ---top level configure options are not passed to the depkgs, particularly - prefix= ---Also, it might be better to split the depkgs location from the --with-sqlite - location. ---should be able to specify e.g. --with-sqlite=/opt/local and have it find - lib, bin, sbin for itself - I tried this and it didn't find sqlite.h -======= - -- Figure out why my Catalog size keeps growing. +- Figure out why my Catalog size keeps growing (Filename and Path + tables keep growing) -- fix it. + +- Label (asks for slot, return and it stops). + +- Document buffer size considerations with Sparse files -- +- Document all daemon tools MUST have a config file. +- Move block size code from block.c to init_dev(). +- Add code to fast seek to proper place on tape/file + when doing Restore. If it doesn't work, try linear + search as before. +- Add code to reject whole blocks if not wanted on restore. +- Why does btape error when pointed to a file? +- Possibly add email to Watchdog if drive is unmounted too + long and a job is waiting on the drive. + +- Add configure for gettimeofday. +- Disallow compile if long long not 64 bits. +- What to do with btime and JobTDate? +- Add FileSet MD5 to bscan. +- Finish implementation of restore "replace" options, and document. +- Strip trailing slashes from Include directory names in the FD. - Use read_record.c in SD code. -- Implement Sparce files, change ownership of files, restore - all Windows attributes, restore options, FSM for program - files. +- Allow changing ownership/group of files on restore. +- Restore options (overwrite, ...) +- Program files (i.e. execute a program to read/write files). + Pass read date of last backup, size of file last time. +- Try bare metal Windows restore +- Recovery of a bad tape. +- EOM records????????????????? - Why don't we get an error message from Win32 FD when bootstrap file cannot be created for restore command? - At line 51 of ua_input.c, why is = 0 necessary. Previously without @@ -41,8 +46,6 @@ From Chuck: - Make SD disallow writing on Volume with fewer files than in the catalog. - Put MaximumVolumeSize in Director. -- Document how to cancel a job that is waiting on a Volume. - Must "cancel" then "mount". - Document to have patience when SD first starts. - Document running a test version. - When Marking a file in Restore that is a hard link, also @@ -53,11 +56,12 @@ From Chuck: - Make BSR return next_block when it knows record is not in block, done when count is reached, and possibly other optimizations. I.e. add a state word. + + - After unmount, if restore job started, ask to mount. - Fix db_get_fileset in cats/sql_get.c for multiple records. - Fix start/end blocks for File devices - Add new code to scheduler.c and run_conf.c -- Volume Bytes shows bytes on last volume written in Job summary. - Fix catalog filename truncation in sql_get and sql_create. Use only a single filename split routine. - Add command to reset VolFiles to a larger value (don't allow @@ -563,3 +567,16 @@ Done: (see kernsdone for more) - Document bscan. - Document Restore. - Check if GZIP1 is working -- check speed. +- Document forcing a new tape to be used. +- Ensure that AcceptAnyVolume works. +- Document running multiple Jobs +- Preserve block number when EOT and writing on next tape. +- Document how to cancel a job that is waiting on a Volume. + Must "cancel" then "mount". +- Document Volume Bytes shows bytes on last volume written in Job summary. +- Restore all Windows attributes. Leave hooks for ACLs and security. + (Handle x = (HANDLE)get_osfhandle(fd); +- Test Windows restore. +- Look into MinGW +- Implement sparse files. +- Document sparse files. diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index e03d0c1ee8..627dc0fdbb 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -91,27 +91,31 @@ #define MAX_NETWORK_BUFFER_SIZE (32 * 1024) /* Stream definitions. Once defined these must NEVER - * change as they go on the storage media + * change as they go on the storage media. */ -#define STREAM_UNIX_ATTRIBUTES 1 /* Generic Unix attributes */ -#define STREAM_FILE_DATA 2 /* Standard uncompressed data */ -#define STREAM_MD5_SIGNATURE 3 /* MD5 signature for the file */ -#define STREAM_GZIP_DATA 4 /* GZip compressed file data */ +#define STREAM_UNIX_ATTRIBUTES 1 /* Generic Unix attributes */ +#define STREAM_FILE_DATA 2 /* Standard uncompressed data */ +#define STREAM_MD5_SIGNATURE 3 /* MD5 signature for the file */ +#define STREAM_GZIP_DATA 4 /* GZip compressed file data */ +#define STREAM_WIN32_ATTRIBUTES 5 /* Windows attributes (superset of Unix) */ +#define STREAM_SPARSE_DATA 6 /* Sparse data stream */ +#define STREAM_SPARSE_GZIP_DATA 7 +#define STREAM_PROGRAM_NAMES 8 /* program names for program data */ +#define STREAM_PROGRAM_DATA 9 /* Data needing program */ +/* Size of File Address stored in STREAM_SPARSE_DATA. Do NOT change! */ +#define SPARSE_FADDR_SIZE (sizeof(uint64_t)) -/* This is for dumb compilers like Solaris. Linux GCC + +/* This is for dumb compilers/libraries like Solaris. Linux GCC * does it correctly, so it might be worthwhile * to remove the isascii(c) with ifdefs on such * "smart" systems. */ -#undef ISSPACE -#undef ISALPHA -#undef ISUPPER -#undef ISDIGIT -#define ISSPACE(c) (isascii((int)(c)) && isspace((int)(c))) -#define ISALPHA(c) (isascii((int)(c)) && isalpha((int)(c))) -#define ISUPPER(c) (isascii((int)(c)) && isupper((int)(c))) -#define ISDIGIT(c) (isascii((int)(c)) && isdigit((int)(c))) +#define B_ISSPACE(c) (isascii((int)(c)) && isspace((int)(c))) +#define B_ISALPHA(c) (isascii((int)(c)) && isalpha((int)(c))) +#define B_ISUPPER(c) (isascii((int)(c)) && isupper((int)(c))) +#define B_ISDIGIT(c) (isascii((int)(c)) && isdigit((int)(c))) typedef void (HANDLER)(); @@ -127,6 +131,11 @@ typedef int (INTHANDLER)(); #define S_ISLNK(m) (((m) & S_IFM) == S_IFLNK) #endif +/* Added by KES to deal with Win32 systems */ +#ifndef S_ISWIN32 +#define S_ISWIN32 020000 +#endif + #ifndef INADDR_NONE #define INADDR_NONE ((unsigned long) -1) #endif diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 16370169a1..19b002781f 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -430,7 +430,7 @@ int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar) /* For the moment, we only handle Unix attributes. Note, we are * also getting any MD5 signature that was computed. */ - if (ar->Stream != STREAM_UNIX_ATTRIBUTES) { + if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES || ar->Stream == STREAM_WIN32_ATTRIBUTES)) { Mmsg0(&mdb->errmsg, _("Attempt to put non-attributes into catalog\n")); Jmsg(mdb->jcr, M_ERROR, 0, "%s", mdb->errmsg); return 0; diff --git a/bacula/src/cl b/bacula/src/cl new file mode 100644 index 0000000000..c5431ee6b7 --- /dev/null +++ b/bacula/src/cl @@ -0,0 +1,19 @@ +/* + Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307, USA. + + */ diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index f1fbcf3597..d12e4d958c 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -64,9 +64,9 @@ all: Makefile bacula-dir @echo "==== Make of dird is good ====" @echo " " -bacula-dir: $(SVROBJS) ../lib/libbac.a ../cats/libsql.a - $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ $(SVROBJS) \ - -lsql -lbac -lm $(LIBS) $(DLIB) $(DB_LIBS) +bacula-dir: $(SVROBJS) ../lib/libbac.a ../cats/libsql.a ../findlib/libfind.a + $(CXX) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SVROBJS) \ + -lsql -lbac -lfind -lm $(LIBS) $(DLIB) $(DB_LIBS) Makefile: $(srcdir)/Makefile.in $(topdir)/config.status cd $(topdir) \ diff --git a/bacula/src/dird/authenticate.c b/bacula/src/dird/authenticate.c index 1ce4f0a05c..81cf4538a4 100644 --- a/bacula/src/dird/authenticate.c +++ b/bacula/src/dird/authenticate.c @@ -131,7 +131,8 @@ int authenticate_user_agent(BSOCK *ua) if (sscanf(ua->msg, "Hello %127s calling\n", name) != 1) { - Emsg1(M_FATAL, 0, _("Authentication failure: %s"), ua->msg); + ua->msg[100] = 0; /* terminate string */ + Emsg1(M_ERROR, 0, _("Authentication failure: %s"), ua->msg); return 0; } diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index decff941a9..094c2b9a50 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -92,6 +92,7 @@ int do_backup(JCR *jcr) memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c)); MD5Final(signature, &md5c); bin_to_base64(fsr.MD5, (char *)signature, 16); /* encode 16 bytes */ + strcpy(jcr->fileset->MD5, fsr.MD5); } else { Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 signature not found.\n")); } @@ -301,7 +302,7 @@ static int wait_for_job_termination(JCR *jcr) static void backup_cleanup(JCR *jcr, int TermCode, char *since) { char sdt[50], edt[50]; - char ec1[30], ec2[30], ec3[30]; + char ec1[30], ec2[30], ec3[30], compress[50]; char term_code[100]; char *term_msg; int msg_type; @@ -356,18 +357,32 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since) bstrftime(edt, sizeof(edt), jcr->jr.EndTime); RunTime = jcr->jr.EndTime - jcr->jr.StartTime; if (RunTime <= 0) { - RunTime = 1; + kbps = 0; + } else { + kbps = (double)jcr->jr.JobBytes / (1000 * RunTime); } - kbps = (double)jcr->jr.JobBytes / (1000 * RunTime); if (!db_get_job_volume_names(jcr->db, jcr->jr.JobId, &jcr->VolumeName)) { - Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); + /* + * Note, if the job has erred, most likely it did not write any + * tape, so suppress this "error" message since in that case + * it is normal. Or look at it the other way, only for a + * normal exit should we complain about this error. + */ + if (TermCode == JS_Terminated) { + Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); + } jcr->VolumeName[0] = 0; /* none */ } if (jcr->ReadBytes == 0) { - compression = 0.0; + strcpy(compress, "None"); } else { compression = (double)100 - 100.0 * ((double)jcr->JobBytes / (double)jcr->ReadBytes); + if (compression < 0.5) { + strcpy(compress, "None"); + } else { + sprintf(compress, "%.1f %%", (float)compression); + } } Jmsg(jcr, msg_type, 0, _("%s\n\ @@ -381,7 +396,7 @@ End time: %s\n\ Files Written: %s\n\ Bytes Written: %s\n\ Rate: %.1f KB/s\n\ -Software Compression: %.1f %%\n\ +Software Compression: %s\n\ Volume names(s): %s\n\ Volume Session Id: %d\n\ Volume Session Time: %d\n\ @@ -398,7 +413,7 @@ Termination: %s\n\n"), edit_uint64_with_commas(jcr->jr.JobFiles, ec1), edit_uint64_with_commas(jcr->jr.JobBytes, ec2), (float)kbps, - (float)compression, + compress, jcr->VolumeName, jcr->VolSessionId, jcr->VolSessionTime, diff --git a/bacula/src/dird/bacula-dir.conf.in b/bacula/src/dird/bacula-dir.conf.in index fbed802461..2fde3b5c9b 100644 --- a/bacula/src/dird/bacula-dir.conf.in +++ b/bacula/src/dird/bacula-dir.conf.in @@ -152,4 +152,5 @@ Pool { Recycle = yes # Bacula can automatically recycle Volumes AutoPrune = yes # Prune expired volumes Volume Retention = 365d # one year + Accept Any Volume = yes # write on any volume in the pool } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 2aaae00f78..1e967cd25e 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -137,12 +137,14 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) } else { /* * Make sure this volume is suitable for this job, i.e. - * it is either Append or Recycle and Media Type matches. + * it is either Append or Recycle and Media Type matches + * and Pool allows any volume. */ if (mr.PoolId == jcr->PoolId && (strcmp(mr.VolStatus, "Append") == 0 || - strcmp(mr.VolStatus, "Recycle") == 0 || - strcmp(mr.MediaType, jcr->store->media_type) == 0)) { + strcmp(mr.VolStatus, "Recycle") == 0) && + strcmp(mr.MediaType, jcr->store->media_type) == 0 && + jcr->pool->accept_any_volume) { VolSuitable = 1; } } @@ -263,7 +265,7 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) Dmsg5(99, "UpdCat VolSessId=%d VolSessT=%d FI=%d Strm=%d data_len=%d\n", VolSessionId, VolSessionTime, FileIndex, Stream, data_len); - if (Stream == STREAM_UNIX_ATTRIBUTES) { + if (Stream == STREAM_UNIX_ATTRIBUTES || Stream == STREAM_WIN32_ATTRIBUTES) { skip_nonspaces(&p); /* skip FileIndex */ skip_spaces(&p); skip_nonspaces(&p); /* skip FileType */ @@ -284,7 +286,6 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) Dmsg2(111, "dirddb, &ar)) { Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db)); } diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 1fd62959b6..473fdada45 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -232,7 +232,7 @@ static struct res_items pool_items[] = { {"usecatalog", store_yesno, ITEM(res_pool.use_catalog), 1, ITEM_DEFAULT, 1}, {"usevolumeonce", store_yesno, ITEM(res_pool.use_volume_once), 1, 0, 0}, {"maximumvolumes", store_pint, ITEM(res_pool.max_volumes), 0, 0, 0}, - {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, 0, 0}, + {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, ITEM_DEFAULT, 1}, {"catalogfiles", store_yesno, ITEM(res_pool.catalog_files), 1, ITEM_DEFAULT, 1}, {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, {"autoprune", store_yesno, ITEM(res_pool.AutoPrune), 1, ITEM_DEFAULT, 1}, @@ -348,6 +348,7 @@ static struct s_kw ReplaceOptions[] = { #define FS_KW_VERIFY 4 #define FS_KW_ONEFS 5 #define FS_KW_RECURSE 6 +#define FS_KW_SPARSE 7 /* FileSet keywords */ static struct s_kw FS_option_kw[] = { @@ -357,6 +358,7 @@ static struct s_kw FS_option_kw[] = { {"verify", FS_KW_VERIFY}, {"onefs", FS_KW_ONEFS}, {"recurse", FS_KW_RECURSE}, + {"sparse", FS_KW_SPARSE}, {NULL, 0} }; @@ -387,6 +389,8 @@ static struct s_fs_opt FS_options[] = { {"no", FS_KW_ONEFS, "f"}, {"yes", FS_KW_RECURSE, "0"}, {"no", FS_KW_RECURSE, "h"}, + {"yes", FS_KW_SPARSE, "s"}, + {"no", FS_KW_SPARSE, "0"}, {NULL, 0, 0} }; diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 11c47bdfc3..22c38264a6 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -30,43 +30,43 @@ /* * Resource codes -- they must be sequential for indexing */ -#define R_FIRST 1001 - -#define R_DIRECTOR 1001 -#define R_CLIENT 1002 -#define R_JOB 1003 -#define R_STORAGE 1004 -#define R_CATALOG 1005 -#define R_SCHEDULE 1006 -#define R_FILESET 1007 -#define R_GROUP 1008 -#define R_POOL 1009 -#define R_MSGS 1010 -#define R_COUNTER 1011 - -#define R_LAST R_COUNTER +#define R_FIRST 1001 + +#define R_DIRECTOR 1001 +#define R_CLIENT 1002 +#define R_JOB 1003 +#define R_STORAGE 1004 +#define R_CATALOG 1005 +#define R_SCHEDULE 1006 +#define R_FILESET 1007 +#define R_GROUP 1008 +#define R_POOL 1009 +#define R_MSGS 1010 +#define R_COUNTER 1011 + +#define R_LAST R_COUNTER /* * Some resource attributes */ -#define R_NAME 1020 -#define R_ADDRESS 1021 -#define R_PASSWORD 1022 -#define R_TYPE 1023 -#define R_BACKUP 1024 +#define R_NAME 1020 +#define R_ADDRESS 1021 +#define R_PASSWORD 1022 +#define R_TYPE 1023 +#define R_BACKUP 1024 /* Used for certain KeyWord tables */ -struct s_kw { +struct s_kw { char *name; - int token; + int token; }; /* Job Level keyword structure */ struct s_jl { - char *level_name; /* level keyword */ - int level; /* level */ - int job_type; /* JobType permitting this level */ + char *level_name; /* level keyword */ + int level; /* level */ + int job_type; /* JobType permitting this level */ }; /* Job Type keyword structure */ @@ -78,22 +78,22 @@ struct s_jt { /* Definition of the contents of each Resource */ /* - * Director Resource + * Director Resource * */ struct s_res_dir { - RES hdr; - int DIRport; /* where we listen -- UA port server port */ - char *DIRaddr; /* bind address */ - char *password; /* Password for UA access */ - char *query_file; /* SQL query file */ - char *working_directory; /* WorkingDirectory */ - char *pid_directory; /* PidDirectory */ - char *subsys_directory; /* SubsysDirectory */ + RES hdr; + int DIRport; /* where we listen -- UA port server port */ + char *DIRaddr; /* bind address */ + char *password; /* Password for UA access */ + char *query_file; /* SQL query file */ + char *working_directory; /* WorkingDirectory */ + char *pid_directory; /* PidDirectory */ + char *subsys_directory; /* SubsysDirectory */ struct s_res_msgs *messages; /* Daemon message handler */ - int MaxConcurrentJobs; - btime_t FDConnectTimeout; /* timeout for connect in seconds */ - btime_t SDConnectTimeout; /* timeout in seconds */ + int MaxConcurrentJobs; + btime_t FDConnectTimeout; /* timeout for connect in seconds */ + btime_t SDConnectTimeout; /* timeout in seconds */ }; typedef struct s_res_dir DIRRES; @@ -102,12 +102,12 @@ typedef struct s_res_dir DIRRES; * */ struct s_res_client { - RES hdr; + RES hdr; - int FDport; /* Where File daemon listens */ - int AutoPrune; /* Do automatic pruning? */ - btime_t FileRetention; /* file retention period in seconds */ - btime_t JobRetention; /* job retention period in seconds */ + int FDport; /* Where File daemon listens */ + int AutoPrune; /* Do automatic pruning? */ + btime_t FileRetention; /* file retention period in seconds */ + btime_t JobRetention; /* job retention period in seconds */ char *address; char *password; struct s_res_cat *catalog; /* Catalog resource */ @@ -119,15 +119,15 @@ typedef struct s_res_client CLIENT; * */ struct s_res_store { - RES hdr; + RES hdr; - int SDport; /* port where Directors connect */ - int SDDport; /* data port for File daemon */ + int SDport; /* port where Directors connect */ + int SDDport; /* data port for File daemon */ char *address; char *password; char *media_type; char *dev_name; - int autochanger; /* set if autochanger */ + int autochanger; /* set if autochanger */ }; typedef struct s_res_store STORE; @@ -136,9 +136,9 @@ typedef struct s_res_store STORE; * */ struct s_res_cat { - RES hdr; + RES hdr; - int DBport; /* Port -- not yet implemented */ + int DBport; /* Port -- not yet implemented */ char *address; char *db_password; char *db_user; @@ -151,30 +151,30 @@ typedef struct s_res_cat CAT; * */ struct s_res_job { - RES hdr; - - int JobType; /* job type (backup, verify, restore */ - int level; /* default backup/verify level */ - int RestoreJobId; /* What -- JobId to restore */ - char *RestoreWhere; /* Where on disk to restore -- directory */ - char *RestoreBootstrap; /* Bootstrap file */ - char *RunBeforeJob; /* Run program before Job */ - char *RunAfterJob; /* Run program after Job */ - char *WriteBootstrap; /* Where to write bootstrap Job updates */ - int RestoreOptions; /* How (overwrite, ..) */ - btime_t MaxRunTime; /* max run time in seconds */ - btime_t MaxStartDelay; /* max start delay in seconds */ - int PruneJobs; /* Force pruning of Jobs */ - int PruneFiles; /* Force pruning of Files */ - int PruneVolumes; /* Force pruning of Volumes */ - int SpoolAttributes; /* Set to spool attributes in SD */ + RES hdr; + + int JobType; /* job type (backup, verify, restore */ + int level; /* default backup/verify level */ + int RestoreJobId; /* What -- JobId to restore */ + char *RestoreWhere; /* Where on disk to restore -- directory */ + char *RestoreBootstrap; /* Bootstrap file */ + char *RunBeforeJob; /* Run program before Job */ + char *RunAfterJob; /* Run program after Job */ + char *WriteBootstrap; /* Where to write bootstrap Job updates */ + int RestoreOptions; /* How (overwrite, ..) */ + btime_t MaxRunTime; /* max run time in seconds */ + btime_t MaxStartDelay; /* max start delay in seconds */ + int PruneJobs; /* Force pruning of Jobs */ + int PruneFiles; /* Force pruning of Files */ + int PruneVolumes; /* Force pruning of Volumes */ + int SpoolAttributes; /* Set to spool attributes in SD */ struct s_res_msgs *messages; /* How and where to send messages */ struct s_res_sch *schedule; /* When -- Automatic schedule */ struct s_res_client *client; /* Who to backup */ struct s_res_fs *fileset; /* What to backup -- Fileset */ struct s_res_store *storage; /* Where is device -- Storage daemon */ - struct s_res_pool *pool; /* Where is media -- Media Pool */ + struct s_res_pool *pool; /* Where is media -- Media Pool */ }; typedef struct s_res_job JOB; @@ -183,7 +183,7 @@ typedef struct s_res_job JOB; * */ struct s_res_fs { - RES hdr; + RES hdr; char **include_array; int num_includes; @@ -191,8 +191,9 @@ struct s_res_fs { char **exclude_array; int num_excludes; int exclude_size; - int have_MD5; /* set if MD5 initialized */ - struct MD5Context md5c; /* MD5 of include/exclude */ + int have_MD5; /* set if MD5 initialized */ + struct MD5Context md5c; /* MD5 of include/exclude */ + char MD5[50]; /* base 64 representation of MD5 */ }; typedef struct s_res_fs FILESET; @@ -202,7 +203,7 @@ typedef struct s_res_fs FILESET; * */ struct s_res_sch { - RES hdr; + RES hdr; struct s_run *run; }; @@ -213,7 +214,7 @@ typedef struct s_res_sch SCHED; * */ struct s_res_group { - RES hdr; + RES hdr; }; typedef struct s_res_group GROUP; @@ -221,12 +222,12 @@ typedef struct s_res_group GROUP; * Counter Resource */ struct s_res_counter { - RES hdr; + RES hdr; - int32_t MinValue; /* Minimum value */ - int32_t MaxValue; /* Maximum value */ - int Global; /* global/local */ - char *WrapCounter; /* Wrap counter name */ + int32_t MinValue; /* Minimum value */ + int32_t MaxValue; /* Maximum value */ + int Global; /* global/local */ + char *WrapCounter; /* Wrap counter name */ }; typedef struct s_res_counter COUNTER; @@ -235,19 +236,19 @@ typedef struct s_res_counter COUNTER; * */ struct s_res_pool { - RES hdr; + RES hdr; struct s_res_counter counter; /* Counter resources */ - char *pool_type; /* Pool type */ - char *label_format; /* Label format string */ - int use_catalog; /* maintain catalog for media */ - int catalog_files; /* maintain file entries in catalog */ - int use_volume_once; /* write on volume only once */ - int accept_any_volume; /* accept any volume */ - int max_volumes; /* max number of volumes */ - btime_t VolRetention; /* volume retention period in seconds */ - int AutoPrune; /* default for pool auto prune */ - int Recycle; /* default for media recycle yes/no */ + char *pool_type; /* Pool type */ + char *label_format; /* Label format string */ + int use_catalog; /* maintain catalog for media */ + int catalog_files; /* maintain file entries in catalog */ + int use_volume_once; /* write on volume only once */ + int accept_any_volume; /* accept any volume */ + int max_volumes; /* max number of volumes */ + btime_t VolRetention; /* volume retention period in seconds */ + int AutoPrune; /* default for pool auto prune */ + int Recycle; /* default for media recycle yes/no */ }; typedef struct s_res_pool POOL; @@ -256,16 +257,16 @@ typedef struct s_res_pool POOL; * resource structure definitions. */ union u_res { - struct s_res_dir res_dir; - struct s_res_client res_client; - struct s_res_store res_store; - struct s_res_cat res_cat; - struct s_res_job res_job; - struct s_res_fs res_fs; - struct s_res_sch res_sch; - struct s_res_group res_group; - struct s_res_pool res_pool; - struct s_res_msgs res_msgs; + struct s_res_dir res_dir; + struct s_res_client res_client; + struct s_res_store res_store; + struct s_res_cat res_cat; + struct s_res_job res_job; + struct s_res_fs res_fs; + struct s_res_sch res_sch; + struct s_res_group res_group; + struct s_res_pool res_pool; + struct s_res_msgs res_msgs; struct s_res_counter res_counter; RES hdr; }; @@ -275,17 +276,17 @@ typedef union u_res URES; /* Run structure contained in Schedule Resource */ struct s_run { - struct s_run *next; /* points to next run record */ - int level; /* level override */ + struct s_run *next; /* points to next run record */ + int level; /* level override */ int job_type; - POOL *pool; /* Pool override */ - STORE *storage; /* Storage override */ - MSGS *msgs; /* Messages override */ + POOL *pool; /* Pool override */ + STORE *storage; /* Storage override */ + MSGS *msgs; /* Messages override */ char *since; int level_no; - int minute; /* minute to run job */ - time_t last_run; /* last time run */ - time_t next_run; /* next time to run */ + int minute; /* minute to run job */ + time_t last_run; /* last time run */ + time_t next_run; /* next time to run */ char hour[nbytes_for_bits(24)]; /* bit set for each hour */ char mday[nbytes_for_bits(31)]; /* bit set for each day of month */ char month[nbytes_for_bits(12)]; /* bit set for each month */ diff --git a/bacula/src/dird/getmsg.c b/bacula/src/dird/getmsg.c index abf81e5d53..3370f771cb 100644 --- a/bacula/src/dird/getmsg.c +++ b/bacula/src/dird/getmsg.c @@ -112,7 +112,7 @@ int32_t bget_msg(BSOCK *bs, int rtn) /* Handle normal data */ - if (ISDIGIT(bs->msg[0])) { /* response? */ + if (B_ISDIGIT(bs->msg[0])) { /* response? */ return n; /* yes, return it */ } diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index 70176ff7fe..ff713c9d37 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -40,7 +40,7 @@ /* Commands sent to Storage daemon */ static char jobcmd[] = "JobId=%d job=%s job_name=%s client_name=%s \ -type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d\n"; +type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s\n"; static char use_device[] = "use device=%s media_type=%s pool_name=%s pool_type=%s\n"; /* Response from Storage daemon */ @@ -108,7 +108,7 @@ int start_storage_daemon_job(JCR *jcr) bnet_fsend(sd, jobcmd, jcr->JobId, jcr->Job, jcr->job->hdr.name, jcr->client->hdr.name, jcr->JobType, jcr->JobLevel, jcr->fileset->hdr.name, !jcr->pool->catalog_files, - jcr->job->SpoolAttributes); + jcr->job->SpoolAttributes, jcr->fileset->MD5); unbash_spaces(jcr->job->hdr.name); unbash_spaces(jcr->client->hdr.name); unbash_spaces(jcr->fileset->hdr.name); diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index 807efa13db..13ac6a99b9 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -32,6 +32,7 @@ #include "dird.h" #include "ua.h" #include +#include "findlib/find.h" diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 3e52b7d125..2e29fac82c 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -42,6 +42,7 @@ #include "bacula.h" #include "dird.h" +#include "findlib/find.h" /* Imported Global Variables */ extern int debug_level; diff --git a/bacula/src/filed/authenticate.c b/bacula/src/filed/authenticate.c index aed54ac44c..bd9fde945e 100644 --- a/bacula/src/filed/authenticate.c +++ b/bacula/src/filed/authenticate.c @@ -45,11 +45,15 @@ static int authenticate(int rcode, BSOCK *bs) Emsg1(M_FATAL, 0, _("I only authenticate directors, not %d\n"), rcode); return 0; } + if (bs->msglen > 200) { + bs->msglen = 200; + } dirname = get_pool_memory(PM_MESSAGE); dirname = check_pool_memory_size(dirname, bs->msglen); if (sscanf(bs->msg, "Hello Director %s calling\n", dirname) != 1) { free_pool_memory(dirname); + bs->msg[100] = 0; Emsg1(M_FATAL, 0, _("Bad Hello command from Director: %s"), bs->msg); return 0; } diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index b91a6911f9..bab03e15fc 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -94,7 +94,8 @@ int blast_data_to_storage_daemon(JCR *jcr, char *addr) static int save_file(FF_PKT *ff_pkt, void *ijcr) { char attribs[MAXSTRING]; - int fid, stat, stream, len; + char attribsEx[MAXSTRING]; + int stat, stream; struct MD5Context md5c; int gotMD5 = 0; unsigned char signature[16]; @@ -166,32 +167,31 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode) && ff_pkt->statp.st_size > 0) { - if ((fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) { + if ((ff_pkt->fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) { ff_pkt->ff_errno = errno; Jmsg(jcr, M_NOTSAVED, -1, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno)); return 1; } } else { - fid = -1; + ff_pkt->fid = -1; } Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname); encode_stat(attribs, &ff_pkt->statp); + stream = encode_attribsEx(jcr, attribsEx, ff_pkt); + Dmsg3(200, "File %s\nattribs=%s\nattribsEx=%s\n", ff_pkt->fname, attribs, attribsEx); jcr->JobFiles++; /* increment number of files sent */ - len = strlen(ff_pkt->fname); - jcr->last_fname = check_pool_memory_size(jcr->last_fname, len + 1); - jcr->last_fname[len] = 0; /* terminate properly before copy */ - strcpy(jcr->last_fname, ff_pkt->fname); + pm_strcpy(&jcr->last_fname, ff_pkt->fname); /* * Send Attributes header to Storage daemon * */ #ifndef NO_FD_SEND_TEST - if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES)) { - if (fid >= 0) { - close(fid); + if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) { + if (ff_pkt->fid >= 0) { + close(ff_pkt->fid); } return 0; } @@ -203,38 +203,41 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) * File type * Filename (full path) * Encoded attributes - * Link name (if type==FT_LNK) + * Link name (if type==FT_LNK or FT_LNKSAVED) + * Encoded extended-attributes (for Win32) + * * For a directory, link is the same as fname, but with trailing * slash. For a linked file, link is the link. */ if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) { Dmsg2(100, "Link %s to %s\n", ff_pkt->fname, ff_pkt->link); - stat = bnet_fsend(sd, "%ld %d %s%c%s%c%s%c", jcr->JobFiles, - ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0); + stat = bnet_fsend(sd, "%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles, + ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0, + attribsEx, 0); } else if (ff_pkt->type == FT_DIR) { - stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c", jcr->JobFiles, - ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0); + /* Here link is the canonical filename (i.e. with trailing slash) */ + stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, + ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0); } else { - stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c", jcr->JobFiles, - ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0); + stat = bnet_fsend(sd, "%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, + ff_pkt->type, ff_pkt->fname, 0, attribs, 0, 0, attribsEx, 0); } Dmsg2(100, ">stored: attr len=%d: %s\n", sd->msglen, sd->msg); if (!stat) { - if (fid >= 0) { - close(fid); + if (ff_pkt->fid >= 0) { + close(ff_pkt->fid); } return 0; } - /* send data termination sentinel */ - bnet_sig(sd, BNET_EOD); + bnet_sig(sd, BNET_EOD); /* indicate end of attributes data */ #endif /* * If the file has data, read it and send to the Storage daemon * */ - if (fid >= 0) { + if (ff_pkt->fid >= 0) { Dmsg1(100, "Saving data, type=%d\n", ff_pkt->type); /* @@ -242,17 +245,36 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) * */ - stream = STREAM_FILE_DATA; + if (ff_pkt->flags & FO_SPARSE) { + stream = STREAM_SPARSE_DATA; + } else { + stream = STREAM_FILE_DATA; + } #ifdef HAVE_LIBZ + uLong compress_len; + const Bytef *cbuf = NULL; + if (ff_pkt->flags & FO_GZIP) { - stream = STREAM_GZIP_DATA; + if (stream == STREAM_FILE_DATA) { + stream = STREAM_GZIP_DATA; + } else { + stream = STREAM_SPARSE_GZIP_DATA; + } + + if (ff_pkt->flags & FO_SPARSE) { + cbuf = (Bytef *)jcr->compress_buf + SPARSE_FADDR_SIZE; + compress_len = jcr->compress_buf_size - SPARSE_FADDR_SIZE; + } else { + cbuf = (Bytef *)jcr->compress_buf; + compress_len = jcr->compress_buf_size; /* set max length */ + } } #endif #ifndef NO_FD_SEND_TEST if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, stream)) { - close(fid); + close(ff_pkt->fid); return 0; } Dmsg1(100, ">stored: datahdr %s\n", sd->msg); @@ -263,24 +285,53 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) } msgsave = sd->msg; - while ((sd->msglen=read(fid, sd->msg, jcr->buf_size)) > 0) { - jcr->ReadBytes += sd->msglen; /* count bytes read */ + uint64_t fileAddr = 0; /* file address */ + char *rbuf = sd->msg; /* read buffer */ + int rsize = jcr->buf_size; /* read size */ + + /* Make space at beginning of buffer for fileAddr */ + if (ff_pkt->flags & FO_SPARSE) { + rbuf += SPARSE_FADDR_SIZE; + rsize -= SPARSE_FADDR_SIZE; + } + + /* + * Read the file data + */ + while ((sd->msglen=read(ff_pkt->fid, rbuf, rsize)) > 0) { + int sparseBlock = 0; + + /* Check for sparse blocks */ + if (ff_pkt->flags & FO_SPARSE) { + ser_declare; + if (sd->msglen == rsize && + (fileAddr+sd->msglen < (uint64_t)ff_pkt->statp.st_size)) { + sparseBlock = is_buf_zero(rbuf, rsize); + } + + ser_begin(sd->msg, SPARSE_FADDR_SIZE); + ser_uint64(fileAddr); /* store fileAddr in begin of buffer */ + } + + jcr->ReadBytes += sd->msglen; /* count bytes read */ + fileAddr += sd->msglen; + + /* Update MD5 if requested */ if (ff_pkt->flags & FO_MD5) { - MD5Update(&md5c, (unsigned char *)(sd->msg), sd->msglen); + MD5Update(&md5c, (unsigned char *)rbuf, sd->msglen); gotMD5 = 1; } + #ifdef HAVE_LIBZ - /* ***FIXME*** add compression level options */ - if (ff_pkt->flags & FO_GZIP) { - uLong compress_len; - compress_len = jcr->compress_buf_size; /* set max length */ - if (compress2((Bytef *)jcr->compress_buf, &compress_len, - (const Bytef *)sd->msg, (uLong)sd->msglen, + /* Do compression if turned on */ + if (!sparseBlock && ff_pkt->flags & FO_GZIP) { + if (compress2((Bytef *)cbuf, &compress_len, + (const Bytef *)rbuf, (uLong)sd->msglen, ff_pkt->GZIP_level) != Z_OK) { Jmsg(jcr, M_FATAL, 0, _("Compression error\n")); sd->msg = msgsave; sd->msglen = 0; - close(fid); + close(ff_pkt->fid); return 0; } Dmsg2(100, "compressed len=%d uncompressed len=%d\n", @@ -288,59 +339,37 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) sd->msg = jcr->compress_buf; /* write compressed buffer */ sd->msglen = compress_len; + } +#endif + #ifndef NO_FD_SEND_TEST + /* Send the buffer to the Storage daemon */ + if (!sparseBlock) { + if (ff_pkt->flags & FO_SPARSE) { + sd->msglen += SPARSE_FADDR_SIZE; /* include fileAddr in size */ + } if (!bnet_send(sd)) { sd->msg = msgsave; /* restore read buffer */ sd->msglen = 0; - close(fid); + close(ff_pkt->fid); return 0; } - Dmsg1(130, "Send data to FD len=%d\n", sd->msglen); -#endif - jcr->JobBytes += sd->msglen; /* count compressed bytes saved */ - sd->msg = msgsave; /* restore read buffer */ - continue; - } -#endif -#ifndef NO_FD_SEND_TEST - if (!bnet_send(sd)) { - close(fid); - return 0; } Dmsg1(130, "Send data to FD len=%d\n", sd->msglen); #endif - jcr->JobBytes += sd->msglen; /* count bytes saved */ - } /* end while */ + jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed */ + sd->msg = msgsave; /* restore read buffer */ + + } /* end while read file data */ if (sd->msglen < 0) { Jmsg(jcr, M_ERROR, 0, _("Network error. ERR=%s\n"), bnet_strerror(sd)); } - /* Send data termination poll signal to Storage daemon. - * NOTE possibly put this poll on a counter as specified - * by the user to improve efficiency (i.e. poll every - * other file, every third file, ... - */ #ifndef NO_FD_SEND_TEST -#ifndef NO_POLL_TEST - bnet_sig(sd, BNET_EOD_POLL); - Dmsg0(130, "Send EndData_Poll\n"); - /* ***FIXME**** change to use bget_msg() */ - if (bnet_recv(sd) <= 0) { - close(fid); - return 0; - } else { - if (strcmp(sd->msg, "3000 OK\n") != 0) { - Jmsg1(jcr, M_FATAL, 0, _("Job aborted by Storage daemon: %s\n"), sd->msg); - close(fid); - return 0; - } - } -#else - bnet_sig(sd, BNET_EOD); -#endif + bnet_sig(sd, BNET_EOD); /* indicate end of file data */ #endif /* NO_FD_SEND_TEST */ - close(fid); /* close file */ + close(ff_pkt->fid); /* close file */ } @@ -357,12 +386,5 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) #endif gotMD5 = 0; } -#ifdef really_needed - if (ff_pkt->type == FT_DIR) { - Jmsg(jcr, M_SAVED, -1, _(" Directory saved normally: %s\n"), ff_pkt->link); - } else { - Jmsg(jcr, M_SAVED, -1, _(" File saved normally: %s\n"), ff_pkt->fname); - } -#endif return 1; } diff --git a/bacula/src/filed/filed.h b/bacula/src/filed/filed.h index 7c9a1ae703..e16d10318d 100644 --- a/bacula/src/filed/filed.h +++ b/bacula/src/filed/filed.h @@ -26,7 +26,6 @@ */ #include "findlib/find.h" -#include "lib/save-cwd.h" #define FILE_DAEMON 1 #include "jcr.h" #include "protos.h" /* file daemon prototypes */ diff --git a/bacula/src/filed/protos.h b/bacula/src/filed/protos.h index 4e51e27f7f..5f1b7a038c 100644 --- a/bacula/src/filed/protos.h +++ b/bacula/src/filed/protos.h @@ -29,3 +29,4 @@ extern void do_restore(JCR *jcr); extern int authenticate_director(JCR *jcr); extern int authenticate_storagedaemon(JCR *jcr); extern int make_estimate(JCR *jcr); + diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 14f9c77501..43bba98fce 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -48,6 +48,7 @@ void do_restore(JCR *jcr) POOLMEM *fname; /* original file name */ POOLMEM *ofile; /* output name with possible prefix */ POOLMEM *lname; /* link name with possible prefix */ + POOLMEM *attribsEx; /* Extended attributes (Win32) */ int32_t stream; uint32_t size; uint32_t VolSessionId, VolSessionTime, file_index; @@ -56,7 +57,10 @@ void do_restore(JCR *jcr) int extract = FALSE; int ofd = -1; int type; - uint32_t total = 0; + uint32_t total = 0; /* Job total but only 32 bits for debug */ + char *wbuf; /* write buffer */ + uint32_t wsize; /* write size */ + uint64_t fileAddr = 0; /* file write address */ wherelen = strlen(jcr->where); @@ -71,6 +75,7 @@ void do_restore(JCR *jcr) fname = get_pool_memory(PM_FNAME); ofile = get_pool_memory(PM_FNAME); lname = get_pool_memory(PM_FNAME); + attribsEx = get_pool_memory(PM_FNAME); #ifdef HAVE_LIBZ uint32_t compress_buf_size = jcr->buf_size + 12 + ((jcr->buf_size+999) / 1000) + 100; @@ -78,7 +83,14 @@ void do_restore(JCR *jcr) #endif /* - * Get a record from the Storage daemon + * Get a record from the Storage daemon. We are guaranteed to + * receive records in the following order: + * 1. Stream record header + * 2. Stream data + * a. Attributes (Unix or Win32) + * or b. File data for the file + * or c. Possibly MD5 record + * 3. Repeat step 1 */ while (bnet_recv(sd) > 0 && !job_cancelled(jcr)) { /* @@ -97,15 +109,15 @@ void do_restore(JCR *jcr) if (bnet_recv(sd) < 0 && !job_cancelled(jcr)) { Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd)); } - if (size != ((uint32_t) sd->msglen)) { + if (size != (uint32_t)sd->msglen) { Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size); goto bail_out; } Dmsg1(30, "Got stream data, len=%d\n", sd->msglen); /* File Attributes stream */ - if (stream == STREAM_UNIX_ATTRIBUTES) { - char *ap, *lp, *fp; + if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) { + char *ap, *lp, *fp, *apex; Dmsg1(30, "Stream=Unix Attributes. extract=%d\n", extract); /* If extracting, it was from previous stream, so @@ -113,12 +125,11 @@ void do_restore(JCR *jcr) */ if (extract) { if (ofd < 0) { - Emsg0(M_ABORT, 0, _("Logic error output file should be open\n")); + Emsg0(M_ERROR, 0, _("Logic error output file should be open\n")); } - close(ofd); - ofd = -1; + set_attributes(jcr, fname, ofile, lname, type, stream, + &statp, attribsEx, &ofd); extract = FALSE; - set_statp(jcr, fname, ofile, lname, type, &statp); Dmsg0(30, "Stop extracting.\n"); } @@ -141,19 +152,20 @@ void do_restore(JCR *jcr) * Filename * Attributes * Link name (if file linked i.e. FT_LNK) + * Extended attributes (Win32) * */ Dmsg1(100, "Attr: %s\n", sd->msg); if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) { Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), sd->msg); - Dmsg1(000, "\nError scanning attributes. %s\n", sd->msg); + Dmsg1(100, "\nError scanning attributes. %s\n", sd->msg); goto bail_out; } Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", record_file_index, type); if (record_file_index != file_index) { Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"), file_index, record_file_index); - Dmsg0(000, "File index error\n"); + Dmsg0(100, "File index error\n"); goto bail_out; } ap = sd->msg; @@ -178,15 +190,22 @@ void do_restore(JCR *jcr) lp = ""; } + if (stream == STREAM_WIN32_ATTRIBUTES) { + apex = ap; /* start at attributes */ + while (*apex++ != 0) { /* skip attributes */ + ; + } + while (*apex++ != 0) { /* skip link name */ + ; + } + pm_strcpy(&attribsEx, apex); /* make a copy */ + } else { + *attribsEx = 0; /* no extended attributes */ + } + + Dmsg3(200, "File %s\nattrib=%s\nattribsEx=%s\n", fname, ap, attribsEx); + decode_stat(ap, &statp); - /* - * ***FIXME*** add REAL Win32 code to backup.c - * Temp kludge so that low level routines (set_statp) know - * we are dealing with a Win32 system. - */ -#ifdef HAVE_CYGWIN - statp.st_mode |= S_ISWIN32; -#endif /* * Prepend the where directory so that the * files are put where the user wants. @@ -228,37 +247,75 @@ void do_restore(JCR *jcr) Dmsg1(30, "Outfile=%s\n", ofile); print_ls_output(jcr, ofile, lname, type, &statp); - extract = create_file(jcr, fname, ofile, lname, type, &statp, &ofd); + extract = create_file(jcr, fname, ofile, lname, type, + stream, &statp, attribsEx, &ofd); Dmsg1(40, "Extract=%d\n", extract); if (extract) { jcr->JobFiles++; + fileAddr = 0; } jcr->num_files_examined++; /* Data stream */ - } else if (stream == STREAM_FILE_DATA) { + } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA) { if (extract) { - Dmsg2(30, "Write %d bytes, total before write=%d\n", sd->msglen, total); - if (write(ofd, sd->msg, sd->msglen) != sd->msglen) { + if (stream == STREAM_SPARSE_DATA) { + ser_declare; + uint64_t faddr; + char ec1[50]; + + wbuf = sd->msg + SPARSE_FADDR_SIZE; + wsize = sd->msglen - SPARSE_FADDR_SIZE; + ser_begin(sd->msg, SPARSE_FADDR_SIZE); + unser_uint64(faddr); + if (fileAddr != faddr) { + fileAddr = faddr; + if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) { + Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), + edit_uint64(fileAddr, ec1), ofile, strerror(errno)); + goto bail_out; + } + } + } else { + wbuf = sd->msg; + wsize = sd->msglen; + } + Dmsg2(30, "Write %u bytes, total before write=%u\n", wsize, total); + if ((uint32_t)write(ofd, wbuf, wsize) != wsize) { Dmsg0(0, "===Write error===\n"); - Jmsg2(jcr, M_ERROR, 0, "Write error on %s: %s\n", ofile, strerror(errno)); + Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), ofile, strerror(errno)); goto bail_out; } - total += sd->msglen; - jcr->JobBytes += sd->msglen; + total += wsize; + jcr->JobBytes += wsize; + fileAddr += wsize; } /* GZIP data stream */ - } else if (stream == STREAM_GZIP_DATA) { + } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA) { #ifdef HAVE_LIBZ if (extract) { uLong compress_len; int stat; + if (stream == STREAM_SPARSE_GZIP_DATA) { + wbuf = sd->msg + SPARSE_FADDR_SIZE; + wsize = sd->msglen - SPARSE_FADDR_SIZE; + if (fileAddr != *((uint64_t *)sd->msg)) { + fileAddr = *((uint64_t *)sd->msg); + if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) { + Jmsg2(jcr, M_ERROR, 0, "Seek error on %s: %s\n", ofile, strerror(errno)); + goto bail_out; + } + } + } else { + wbuf = sd->msg; + wsize = sd->msglen; + } compress_len = compress_buf_size; - Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, sd->msglen); + Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize); if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len, - (const Byte *)sd->msg, (uLong)sd->msglen)) != Z_OK) { + (const Byte *)wbuf, (uLong)wsize)) != Z_OK) { Jmsg(jcr, M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat); goto bail_out; } @@ -271,6 +328,7 @@ void do_restore(JCR *jcr) } total += compress_len; jcr->JobBytes += compress_len; + fileAddr += compress_len; } #else if (extract) { @@ -282,12 +340,11 @@ void do_restore(JCR *jcr) } else if (extract) { Dmsg1(30, "Found wierd stream %d\n", stream); if (ofd < 0) { - Emsg0(M_ABORT, 0, _("Logic error output file should be open\n")); + Emsg0(M_ERROR, 0, _("Logic error output file should be open\n")); } - close(ofd); - ofd = -1; + set_attributes(jcr, fname, ofile, lname, type, stream, + &statp, attribsEx, &ofd); extract = FALSE; - set_statp(jcr, fname, ofile, lname, type, &statp); } else if (stream != STREAM_MD5_SIGNATURE) { Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); } @@ -297,8 +354,8 @@ void do_restore(JCR *jcr) * archive since we just hit an end of file, so close the file. */ if (ofd >= 0) { - close(ofd); - set_statp(jcr, fname, ofile, lname, type, &statp); + set_attributes(jcr, fname, ofile, lname, type, stream, + &statp, attribsEx, &ofd); } jcr->JobStatus = JS_Terminated; goto ok_out; @@ -313,6 +370,7 @@ ok_out: free_pool_memory(fname); free_pool_memory(ofile); free_pool_memory(lname); + free_pool_memory(attribsEx); Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles, jcr->JobBytes); } diff --git a/bacula/src/filed/win32/winmain.cpp b/bacula/src/filed/win32/winmain.cpp index 938aba1d63..ddb3d1d04c 100755 --- a/bacula/src/filed/win32/winmain.cpp +++ b/bacula/src/filed/win32/winmain.cpp @@ -21,6 +21,7 @@ Copyright (2000) Kern E. Sibbald */ +#include #include #include #include "winbacula.h" diff --git a/bacula/src/findlib/Makefile.in b/bacula/src/findlib/Makefile.in index 6b84dac1a4..12fbd39543 100644 --- a/bacula/src/findlib/Makefile.in +++ b/bacula/src/findlib/Makefile.in @@ -20,8 +20,10 @@ first_rule: all dummy: # -LIBSRCS = find.c match.c find_one.c -LIBOBJS = find.o match.o find_one.o +LIBSRCS = find.c match.c find_one.c attibs.c create_file.c \ + makepath.c save-cwd.c +LIBOBJS = find.o match.o find_one.o attribs.o create_file.o \ + makepath.o save-cwd.o .SUFFIXES: .c .o .PHONY: diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c new file mode 100755 index 0000000000..ad8bedd365 --- /dev/null +++ b/bacula/src/findlib/attribs.c @@ -0,0 +1,407 @@ +/* + * Encode and decode standard Unix attributes and + * Extended attributes for Win32 and + * other non-Unix systems, or Unix systems with ACLs, ... + * + * Kern Sibbald, October MMII + * + * Version $Id$ + * + */ +/* + Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "find.h" +#include "jcr.h" + +#ifdef HAVE_CYGWIN +#include + +/* Forward referenced subroutines */ +static +int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname, + int type, int stream, struct stat *statp, + char *attribsEx, int *ofd); +void unix_name_to_win32(char *name); +extern "C" HANDLE get_osfhandle(int fd); +void win_error(void *jcr, char *prefix, char *ofile); +#endif + + +/*=============================================================*/ +/* */ +/* *** A l l S y s t e m s *** */ +/* */ +/*=============================================================*/ + + +/* Encode a stat structure into a base64 character string */ +void encode_stat(char *buf, struct stat *statp) +{ + char *p = buf; + /* + * NOTE: we should use rdev as major and minor device if + * it is a block or char device (S_ISCHR(statp->st_mode) + * or S_ISBLK(statp->st_mode)). In all other cases, + * it is not used. + * + */ + p += to_base64((int64_t)statp->st_dev, p); + *p++ = ' '; /* separate fields with a space */ + p += to_base64((int64_t)statp->st_ino, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_mode, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_nlink, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_uid, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_gid, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_rdev, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_size, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_blksize, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_blocks, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_atime, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_mtime, p); + *p++ = ' '; + p += to_base64((int64_t)statp->st_ctime, p); + *p = 0; + return; +} + + + +/* Decode a stat packet from base64 characters */ +void +decode_stat(char *buf, struct stat *statp) +{ + char *p = buf; + int64_t val; + + p += from_base64(&val, p); + statp->st_dev = val; + p++; /* skip space */ + p += from_base64(&val, p); + statp->st_ino = val; + p++; + p += from_base64(&val, p); + statp->st_mode = val; + p++; + p += from_base64(&val, p); + statp->st_nlink = val; + p++; + p += from_base64(&val, p); + statp->st_uid = val; + p++; + p += from_base64(&val, p); + statp->st_gid = val; + p++; + p += from_base64(&val, p); + statp->st_rdev = val; + p++; + p += from_base64(&val, p); + statp->st_size = val; + p++; + p += from_base64(&val, p); + statp->st_blksize = val; + p++; + p += from_base64(&val, p); + statp->st_blocks = val; + p++; + p += from_base64(&val, p); + statp->st_atime = val; + p++; + p += from_base64(&val, p); + statp->st_mtime = val; + p++; + p += from_base64(&val, p); + statp->st_ctime = val; +} + +/* + * Set file modes, permissions and times + * + * fname is the original filename + * ofile is the output filename (may be in a different directory) + * + * Returns: 1 on success + * 0 on failure + */ +int set_attributes(void *jcr, char *fname, char *ofile, char *lname, + int type, int stream, struct stat *statp, + char *attribsEx, int *ofd) +{ + struct utimbuf ut; + +#ifdef HAVE_CYGWIN + if (set_win32_attributes(jcr, fname, ofile, lname, type, stream, + statp, attribsEx, ofd)) { + return 1; + } + /* + * If Windows stuff failed, e.g. attempt to restore Unix file + * to Windows, simply fall through and we will do it the + * universal way. + */ +#endif + + if (*ofd != -1) { + close(*ofd); /* first close file */ + *ofd = -1; + } + + ut.actime = statp->st_atime; + ut.modtime = statp->st_mtime; + + /* ***FIXME**** optimize -- don't do if already correct */ + if (type == FT_LNK) { + if (lchown(ofile, statp->st_uid, statp->st_gid) < 0) { + Jmsg2(jcr, M_ERROR, 0, "Unable to set file owner %s: ERR=%s\n", + ofile, strerror(errno)); + return 0; + } + } else { + if (chown(ofile, statp->st_uid, statp->st_gid) < 0) { + Jmsg2(jcr, M_ERROR, 0, "Unable to set file owner %s: ERR=%s\n", + ofile, strerror(errno)); + return 0; + } + } + if (chmod(ofile, statp->st_mode) < 0) { + Jmsg2(jcr, M_ERROR, 0, "Unable to set file modes %s: ERR=%s\n", + ofile, strerror(errno)); + return 0; + } + + /* + * Update file times. + */ + if (utime(ofile, &ut) < 0) { + Jmsg2(jcr, M_ERROR, 0, "Unable to set file times %s: ERR=%s\n", + ofile, strerror(errno)); + return 0; + } + return 1; +} + + +/*=============================================================*/ +/* */ +/* * * * U n i x * * * * */ +/* */ +/*=============================================================*/ + +#ifndef HAVE_CYGWIN + +/* + * If you have a Unix system with extended attributes (e.g. + * ACLs for Solaris, do it here. + */ +int encode_attribsEx(void *jcr, char *attribsEx, FF_PKT *ff_pkt) +{ + *attribsEx = 0; /* no extended attributes */ + return STREAM_UNIX_ATTRIBUTES; +} + +#endif + + + +/*=============================================================*/ +/* */ +/* * * * W i n 3 2 * * * * */ +/* */ +/*=============================================================*/ + +#ifdef HAVE_CYGWIN + +int encode_attribsEx(void *jcr, char *attribsEx, FF_PKT *ff_pkt) +{ + char *p = attribsEx; + WIN32_FILE_ATTRIBUTE_DATA atts; + ULARGE_INTEGER li; + + attribsEx[0] = 0; /* no extended attributes */ + + pm_strcpy(&ff_pkt->sys_fname, ff_pkt->fname); + unix_name_to_win32(ff_pkt->sys_fname); + if (!GetFileAttributesEx(ff_pkt->sys_fname, GetFileExInfoStandard, + (LPVOID)&atts)) { + win_error(jcr, "GetFileAttributesEx:", ff_pkt->sys_fname); + return STREAM_WIN32_ATTRIBUTES; + } + + p += to_base64((uint64_t)atts.dwFileAttributes, p); + *p++ = ' '; /* separate fields with a space */ + li.LowPart = atts.ftCreationTime.dwLowDateTime; + li.HighPart = atts.ftCreationTime.dwHighDateTime; + p += to_base64((uint64_t)li.QuadPart, p); + *p++ = ' '; + li.LowPart = atts.ftLastAccessTime.dwLowDateTime; + li.HighPart = atts.ftLastAccessTime.dwHighDateTime; + p += to_base64((uint64_t)li.QuadPart, p); + *p++ = ' '; + li.LowPart = atts.ftLastWriteTime.dwLowDateTime; + li.HighPart = atts.ftLastWriteTime.dwHighDateTime; + p += to_base64((uint64_t)li.QuadPart, p); + *p++ = ' '; + p += to_base64((uint64_t)atts.nFileSizeHigh, p); + *p++ = ' '; + p += to_base64((uint64_t)atts.nFileSizeLow, p); + *p = 0; + return STREAM_WIN32_ATTRIBUTES; +} + +/* Define attributes that are legal to set with SetFileAttributes() */ +#define SET_ATTRS ( \ + FILE_ATTRIBUTE_ARCHIVE| \ + FILE_ATTRIBUTE_HIDDEN| \ + FILE_ATTRIBUTE_NORMAL| \ + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED| \ + FILE_ATTRIBUTE_OFFLINE| \ + FILE_ATTRIBUTE_READONLY| \ + FILE_ATTRIBUTE_SYSTEM| \ + FILE_ATTRIBUTE_TEMPORARY) + + +/* + * Set Extended File Attributes for Win32 + * + * fname is the original filename + * ofile is the output filename (may be in a different directory) + * + * Returns: 1 on success + * 0 on failure + */ +static +int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname, + int type, int stream, struct stat *statp, + char *attribsEx, int *ofd) +{ + char *p = attribsEx; + int64_t val; + WIN32_FILE_ATTRIBUTE_DATA atts; + ULARGE_INTEGER li; + int fid, stat; + + if (!p || !*p) { /* we should have attributes */ + Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, *ofd); + if (*ofd != -1) { + close(*ofd); + *ofd = -1; + } + return 0; + } else { + Dmsg2(100, "Attribs %s = %s\n", ofile, attribsEx); + } + + p += from_base64(&val, p); + atts.dwFileAttributes = val; + p++; /* skip space */ + p += from_base64(&val, p); + li.QuadPart = val; + atts.ftCreationTime.dwLowDateTime = li.LowPart; + atts.ftCreationTime.dwHighDateTime = li.HighPart; + p++; /* skip space */ + p += from_base64(&val, p); + li.QuadPart = val; + atts.ftLastAccessTime.dwLowDateTime = li.LowPart; + atts.ftLastAccessTime.dwHighDateTime = li.HighPart; + p++; /* skip space */ + p += from_base64(&val, p); + li.QuadPart = val; + atts.ftLastWriteTime.dwLowDateTime = li.LowPart; + atts.ftLastWriteTime.dwHighDateTime = li.HighPart; + p++; + p += from_base64(&val, p); + atts.nFileSizeHigh = val; + p++; + p += from_base64(&val, p); + atts.nFileSizeLow = val; + + /* At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */ + + if (*ofd == -1) { + Dmsg1(100, "File not open: %s\n", ofile); + fid = open(ofile, O_RDWR); /* attempt to open the file */ + if (fid >= 0) { + *ofd = fid; + } + } + + if (*ofd != -1) { + Dmsg1(100, "SetFileTime %s\n", ofile); + stat = SetFileTime(get_osfhandle(*ofd), + &atts.ftCreationTime, + &atts.ftLastAccessTime, + &atts.ftLastWriteTime); + if (stat != 1) { + win_error(jcr, "SetFileTime:", ofile); + } + close(*ofd); + *ofd = -1; + } + + /* Bash name to Windows format */ + unix_name_to_win32(ofile); + Dmsg1(100, "SetFileAtts %s\n", ofile); + stat = SetFileAttributes(ofile, atts.dwFileAttributes & SET_ATTRS); + if (stat != 1) { + win_error(jcr, "SetFileAttributes:", ofile); + } + return 1; +} + +void win_error(void *vjcr, char *prefix, char *ofile) +{ + JCR *jcr = (JCR *)vjcr; + DWORD lerror = GetLastError(); + LPTSTR msg; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER| + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + lerror, + 0, + (LPTSTR)&msg, + 0, + NULL); + Dmsg3(100, "Error in %s on file %s: ERR=%s\n", prefix, ofile, msg); + Jmsg3(jcr, M_INFO, 0, "Error in %s file %s: ERR=%s\n", prefix, ofile, msg); + LocalFree(msg); +} + +void unix_name_to_win32(char *name) +{ + char *p; + for (p=name; *p; p++) { + if (*p == '/') { + *p = '\\'; + } + } +} + +#endif /* HAVE_CYGWIN */ diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c new file mode 100644 index 0000000000..66e4921030 --- /dev/null +++ b/bacula/src/findlib/create_file.c @@ -0,0 +1,186 @@ +/* + * Create a file, and reset the modes + * + * Kern Sibbald, November MM + * + * Version $Id$ + * + */ +/* + Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "find.h" + +#ifndef S_IRWXUGO +#define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif + +#ifndef IS_CTG +#define IS_CTG(x) 0 +#define O_CTG 0 +#endif + + +/* + * Create the file, or the directory + * + * fname is the original filename + * ofile is the output filename (may be in a different directory) + * + * Returns: 1 on success + * 0 on failure + * + * Note, we create the file here, except for special files, + * we do not set the attributes because we want to first + * write the file, then when the writing is done, set the + * attributes. + * So, we return with the file descriptor open for normal + * files. + * + */ +int create_file(void *jcr, char *fname, char *ofile, char *lname, + int type, int stream, struct stat *statp, + char *attribsEx, int *ofd) +{ + int new_mode, parent_mode, mode; + uid_t uid; + gid_t gid; + int stat = 0; + int fnl, pnl; + char *f, *p, savechr; + + *ofd = -1; +/* + * new_mode = S_IRWXUGO & ~umask(0); + */ + new_mode = statp->st_mode; + Dmsg2(300, "newmode=%x file=%s\n", new_mode, ofile); + parent_mode = S_IWUSR | S_IXUSR | new_mode; + gid = statp->st_gid; + uid = statp->st_uid; + + switch (type) { + case FT_LNKSAVED: /* Hard linked, file already saved */ + Dmsg2(130, "Hard link %s => %s\n", ofile, lname); + if (link(lname, ofile) != 0) { + Jmsg3(jcr, M_ERROR, 0, "Could not hard link %s ==> %s: ERR=%s\n", + ofile, lname, strerror(errno)); + } + break; + case FT_REGE: /* empty file */ + case FT_REG: /* regular file */ + /* Separate pathname and filename */ + for (p=f=ofile; *p; p++) { + if (*p == '/') { + f = p; /* possible filename */ + } + } + if (*f == '/') { + f++; + } + + fnl = p - f; + if (fnl == 0) { + Jmsg1(jcr, M_ERROR, 0, "Zero length filename: %s\n", fname); + return 0; + } + + pnl = f - ofile - 1; + if (pnl <= 0) { + Jmsg1(jcr, M_ERROR, 0, "Zero length path: %s\n", fname); + return 0; + } + savechr = ofile[pnl]; + ofile[pnl] = 0; /* terminate path */ + + Dmsg1(50, "Make path %s\n", ofile); + /* + * If we need to make the directory, ensure that it is with + * execute bit set (i.e. parent_mode), and preserve what already + * exists. Normally, this should do nothing. + */ + stat = !make_path(jcr, ofile, parent_mode, parent_mode, uid, gid, 1, NULL); + if (stat == 0) { + Dmsg1(0, "Could not make path. %s\n", ofile); + return 0; + } + + ofile[pnl] = savechr; /* restore full name */ + Dmsg1(100, "Create file %s\n", ofile); + mode = O_WRONLY | O_CREAT | O_TRUNC; + if (IS_CTG(statp->st_mode)) { + mode |= O_CTG; /* set contiguous bit if needed */ + } + Dmsg1(50, "Create file: %s\n", ofile); + if ((*ofd = open(ofile, mode, S_IRUSR | S_IWUSR)) < 0) { + Jmsg2(jcr, M_ERROR, 0, "Could not create %s: ERR=%s\n", ofile, strerror(errno)); + return 0; + } + return 1; + case FT_LNK: + Dmsg2(130, "FT_LNK should restore: %s -> %s\n", ofile, lname); + if (symlink(lname, ofile) != 0 && errno != EEXIST) { + Jmsg3(jcr, M_ERROR, 0, "Could not symlink %s -> %s: ERR=%s\n", + ofile, lname, strerror(errno)); + } + return 0; + case FT_DIR: + Dmsg2(300, "Make dir mode=%o dir=%s\n", new_mode, ofile); + if (make_path(jcr, ofile, new_mode, parent_mode, uid, gid, 0, NULL) != 0) { + Jmsg1(jcr, M_ERROR, 0, "Could not make directory: %s\n", ofile); + } + return 0; + case FT_SPEC: + if (S_ISFIFO(statp->st_mode)) { + Dmsg1(0, "Restore fifo: %s\n", ofile); + if (mkfifo(ofile, statp->st_mode) != 0) { + Jmsg2(jcr, M_ERROR, 0, "Cannot make fifo %s: ERR=%s\n", ofile, strerror(errno)); + return 0; + } + } else { + Dmsg1(0, "Restore node: %s\n", ofile); + if (mknod(ofile, statp->st_mode, statp->st_rdev) != 0) { + Jmsg2(jcr, M_ERROR, 0, "Cannot make node %s: ERR=%s\n", ofile, strerror(errno)); + return 0; + } + } + Dmsg1(0, "FT_SPEC %s\n", ofile); + return 0; + + /* The following should not occur */ + case FT_NOACCESS: + case FT_NOFOLLOW: + case FT_NOSTAT: + case FT_DIRNOCHG: + case FT_NOCHG: + case FT_ISARCH: + case FT_NORECURSE: + case FT_NOFSCHG: + case FT_NOOPEN: + Jmsg2(jcr, M_ERROR, 0, "Original file %s not saved. Stat=%d\n", fname, type); + return 0; + default: + Jmsg2(jcr, M_ERROR, 0, "Unknown file type %d; not restored: %s\n", type, fname); + return 0; + } + + return 0; +} diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index 02b433932c..06f85ae800 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -52,6 +52,8 @@ FF_PKT *init_find_files() ff = (FF_PKT *) bmalloc(sizeof(FF_PKT)); memset(ff, 0, sizeof(FF_PKT)); + ff->sys_fname = get_pool_memory(PM_FNAME); + init_include_exclude_files(ff); /* init lists */ ff->mtime_only = 1; ff->one_file_system = 1; @@ -132,6 +134,7 @@ term_find_files(FF_PKT *ff) { term_include_exclude_files(ff); term_find_one(ff); + free_pool_memory(ff->sys_fname); free(ff); return; } diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 2c5d1a0741..50fd5d0f6e 100755 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -4,32 +4,47 @@ * Kern Sibbald MIM */ /* - Copyright (C) 2000, 2001 Kern Sibbald and John Walker + Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef __FILES_H #define __FILES_H +#ifdef HAVE_DIRENT_H +#include +#define NAMELEN(dirent) (strlen((dirent)->d_name)) +#endif +#include +#include + +#define MODE_RALL (S_IRUSR|S_IRGRP|S_IROTH) + +#define DEFAULT_NAMEBUF_LEN 150 /* default filename buffer length */ + #ifdef HAVE_FNMATCH #include #else #include "lib/fnmatch.h" #endif +#include "save-cwd.h" + /* * NOTE!!! These go on the tape, so don't change them. If @@ -51,15 +66,20 @@ #define FT_NOFSCHG 14 /* Different file system, prohibited */ #define FT_NOOPEN 15 /* Could not open directory */ -/* FileSet options */ -#define FO_MD5 0x1 /* Do MD5 checksum */ -#define FO_GZIP 0x2 /* Do Zlib compression */ - +/* Options saved in "flag" of ff packet */ +#define FO_MD5 0x01 /* Do MD5 checksum */ +#define FO_GZIP 0x02 /* Do Zlib compression */ +#define FO_NO_RECURSION 0x04 /* no recursion in directories */ +#define FO_MULTIFS 0x08 /* multiple file systems */ +#define FO_SPARSE 0x10 /* do sparse file checking */ +/* Options saved in "options" of include list */ +/* ****FIXME**** replace OPT_ flags with FO_ */ #define OPT_compute_MD5 0x01 /* compute MD5 of file's data */ #define OPT_GZIP_compression 0x02 /* use GZIP compression */ #define OPT_no_recursion 0x04 /* no recursion in directories */ #define OPT_multifs 0x08 /* multiple file systems */ +#define OPT_sparse 0x10 /* do sparse file checking */ struct s_included_file { @@ -86,8 +106,10 @@ struct s_excluded_file { typedef struct ff { char *fname; /* filename */ char *link; /* link if file linked */ + POOLMEM *sys_fname; /* system filename */ struct stat statp; /* stat packet */ int type; /* FT_ type from above */ + int fid; /* file id if opened */ int flags; /* control flags */ int ff_errno; /* errno */ int incremental; /* do incremental save */ @@ -109,20 +131,6 @@ typedef struct ff { struct f_link *linklist; /* hard linked files */ } FF_PKT; -/* From find.c */ -FF_PKT *init_find_files(); -void set_find_options(FF_PKT *ff, int incremental, time_t mtime); -int find_files(FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt); -void term_find_files(FF_PKT *ff); - -/* From match.c */ -void init_include_exclude_files(FF_PKT *ff); -void term_include_exclude_files(FF_PKT *ff); -void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname); -void add_fname_to_exclude_list(FF_PKT *ff, char *fname); -struct s_included_file *get_next_included_file( - FF_PKT *ff, struct s_included_file *inc); -int file_is_excluded(FF_PKT *ff, char *file); -int file_is_included(FF_PKT *ff, char *file); +#include "protos.h" #endif /* __FILES_H */ diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 937c3dcf28..3a62a6b766 100755 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -27,7 +27,7 @@ #include "bacula.h" #include "find.h" -#include "system.h" +/*#include "system.h" */ extern size_t name_max; /* filename max length */ @@ -71,12 +71,12 @@ struct utimbuf */ int find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt, - char *p, dev_t parent_device, int top_level) + char *fname, dev_t parent_device, int top_level) { struct utimbuf restore_times; int rtn_stat; - ff_pkt->fname = ff_pkt->link = p; + ff_pkt->fname = ff_pkt->link = fname; if (ff_pkt->compute_MD5) { ff_pkt->flags |= FO_MD5; } @@ -84,17 +84,17 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt ff_pkt->flags |= FO_GZIP; } - if (lstat(p, &ff_pkt->statp) != 0) { + if (lstat(fname, &ff_pkt->statp) != 0) { /* Cannot stat file */ ff_pkt->type = FT_NOSTAT; ff_pkt->ff_errno = errno; return handle_file(ff_pkt, pkt); } - Dmsg1(60, "File ----: %s\n", p); + Dmsg1(60, "File ----: %s\n", fname); #ifdef DEBUG if (S_ISLNK(ff_pkt->statp.st_mode)) - Dmsg1(60, "Link-------------: %s \n", p); + Dmsg1(60, "Link-------------: %s \n", fname); #endif /* Save current times of this directory in case we need to @@ -158,10 +158,10 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt } /* File not previously dumped. Chain it into our list. */ - lp = (struct f_link *)bmalloc(sizeof (struct f_link) + strlen(p)); + lp = (struct f_link *)bmalloc(sizeof (struct f_link) + strlen(fname)); lp->ino = ff_pkt->statp.st_ino; lp->dev = ff_pkt->statp.st_dev; - strcpy (lp->name, p); + strcpy (lp->name, fname); lp->next = ff_pkt->linklist; ff_pkt->linklist = lp; } @@ -175,7 +175,7 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt /* Don't bother opening empty, world readable files. Also do not open files when archive is meant for /dev/null. */ if (ff_pkt->null_output_device || (sizeleft == 0 - && MODE_R == (MODE_R & ff_pkt->statp.st_mode))) { + && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) { ff_pkt->type = FT_REGE; } else { ff_pkt->type = FT_REG; @@ -186,14 +186,14 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt int size; char *buffer = (char *)alloca(PATH_MAX + 1); - size = readlink(p, buffer, PATH_MAX + 1); + size = readlink(fname, buffer, PATH_MAX + 1); if (size < 0) { /* Could not follow link */ ff_pkt->type = FT_NOFOLLOW; ff_pkt->ff_errno = errno; return handle_file(ff_pkt, pkt); } - buffer[size] = '\0'; + buffer[size] = 0; ff_pkt->link = buffer; ff_pkt->type = FT_LNK; /* got a real link */ return handle_file(ff_pkt, pkt); @@ -202,23 +202,23 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt DIR *directory; struct dirent *entry, *result; char *namebuf; - size_t buflen; + size_t namebuf_len; size_t len; int status; dev_t our_device = ff_pkt->statp.st_dev; - if (access(p, R_OK) == -1 && geteuid() != 0) { + if (access(fname, R_OK) == -1 && geteuid() != 0) { /* Could not access() directory */ ff_pkt->type = FT_NOACCESS; ff_pkt->ff_errno = errno; return handle_file(ff_pkt, pkt); } - /* Build new prototype name. Ensure exactly one trailing slash. */ - len = strlen(p); - buflen = len + NAME_FIELD_SIZE; - namebuf = (char *)bmalloc(buflen + 2); - strncpy(namebuf, p, buflen); + /* Build a canonical directory name with a trailing slash. */ + len = strlen(fname); + namebuf_len = len + DEFAULT_NAMEBUF_LEN; + namebuf = (char *)bmalloc(namebuf_len + 2); + strncpy(namebuf, fname, namebuf_len); while (len >= 1 && namebuf[len - 1] == '/') len--; namebuf[len++] = '/'; @@ -263,7 +263,7 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt * Now process the files in this directory. */ errno = 0; - if ((directory = opendir(p)) == NULL) { + if ((directory = opendir(fname)) == NULL) { free(namebuf); ff_pkt->type = FT_NOOPEN; ff_pkt->ff_errno = errno; @@ -271,7 +271,7 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt } /* - * This could possibly run faster if we chdir to the directory + * This would possibly run faster if we chdir to the directory * before traversing it. */ rtn_stat = 1; @@ -292,9 +292,9 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt continue; } - if ((int)NAMLEN(entry) + len >= buflen) { - buflen = len + NAMLEN(entry); - namebuf = (char *)brealloc(namebuf, buflen + 2); + if ((int)NAMELEN(entry) + len >= namebuf_len) { + namebuf_len = len + NAMELEN(entry); + namebuf = (char *)brealloc(namebuf, namebuf_len + 2); } strcpy(namebuf + len, entry->d_name); if (!file_is_excluded(ff_pkt, namebuf)) { @@ -305,7 +305,7 @@ find_one_file(FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), void *pkt free(namebuf); free(entry); if (ff_pkt->atime_preserve) { - utime(p, &restore_times); + utime(fname, &restore_times); } return rtn_stat; } /* end check for directory */ diff --git a/bacula/src/findlib/makepath.c b/bacula/src/findlib/makepath.c new file mode 100644 index 0000000000..53fa1cce30 --- /dev/null +++ b/bacula/src/findlib/makepath.c @@ -0,0 +1,396 @@ +/* makepath.c -- Ensure that a directory path exists. + + Copyright (C) 1990, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by David MacKenzie and Jim Meyering. */ + +/* + * Modified by Kern Sibbald for use in Bacula, December 2000 + * + * Version $Id$ + */ + +#include "bacula.h" +#include "jcr.h" +#include "save-cwd.h" + + +#if !defined(S_ISDIR) && defined(S_IFDIR) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_IRWXUGO +# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif + + +#ifndef S_ISUID +# define S_ISUID 04000 +#endif +#ifndef S_ISGID +# define S_ISGID 02000 +#endif +#ifndef S_ISVTX +# define S_ISVTX 01000 +#endif +#ifndef S_IRUSR +# define S_IRUSR 0200 +#endif +#ifndef S_IWUSR +# define S_IWUSR 0200 +#endif +#ifndef S_IXUSR +# define S_IXUSR 0100 +#endif + +#ifndef S_IRWXU +# define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR) +#endif + +#define WX_USR (S_IWUSR | S_IXUSR) + +#define quote(path) path + +extern void strip_trailing_slashes(); + +static int +cleanup(struct saved_cwd *cwd) +{ + if (cwd->do_chdir) { + int _fail = restore_cwd(cwd, NULL, NULL); + free_cwd(cwd); + if (_fail) + return 1; + } + return 0; +} + + +/* Attempt to create directory DIR (aka DIRPATH) with the specified MODE. + If CREATED_DIR_P is non-NULL, set *CREATED_DIR_P to non-zero if this + function creates DIR and to zero otherwise. Give a diagnostic and + return non-zero if DIR cannot be created or cannot be determined to + exist already. Use DIRPATH in any diagnostic, not DIR. + Note that if DIR already exists, this function will return zero + (indicating success) and will set *CREATED_DIR_P to zero. */ + +static int +make_dir(void *jcr, const char *dir, const char *dirpath, mode_t mode, int *created_dir_p) +{ + int fail = 0; + int created_dir; + + Dmsg2(300, "make_dir mode=%o dir=%s\n", mode, dir); + created_dir = (mkdir(dir, mode) == 0); + + if (!created_dir) { + struct stat stats; + + /* The mkdir and stat calls below may appear to be reversed. + They are not. It is important to call mkdir first and then to + call stat (to distinguish the three cases) only if mkdir fails. + The alternative to this approach is to `stat' each directory, + then to call mkdir if it doesn't exist. But if some other process + were to create the directory between the stat & mkdir, the mkdir + would fail with EEXIST. */ + + if (stat(dir, &stats)) { + Jmsg(jcr, M_ERROR, 0, "Cannot create directory %s: %s\n", + dirpath, strerror(errno)); + fail = 1; + } else if (!S_ISDIR(stats.st_mode)) { + Jmsg(jcr, M_ERROR, 0, "%s exists but is not a directory\n", quote(dirpath)); + fail = 1; + } else { + /* DIR (aka DIRPATH) already exists and is a directory. */ + } + } + + if (created_dir_p) { + *created_dir_p = created_dir; + } + + return fail; +} + +/* Ensure that the directory ARGPATH exists. + Remove any trailing slashes from ARGPATH before calling this function. + + Create any leading directories that don't already exist, with + permissions PARENT_MODE. + + If the last element of ARGPATH does not exist, create it as + a new directory with permissions MODE. + + If OWNER and GROUP are non-negative, use them to set the UID and GID of + any created directories. + + If VERBOSE_FMT_STRING is nonzero, use it as a printf format + string for printing a message after successfully making a directory, + with the name of the directory that was just made as an argument. + + If PRESERVE_EXISTING is non-zero and ARGPATH is an existing directory, + then do not attempt to set its permissions and ownership. + + Return 0 if ARGPATH exists as a directory with the proper + ownership and permissions when done, otherwise 1. */ + +int +make_path( + void *jcr, + const char *argpath, + int mode, + int parent_mode, + uid_t owner, + gid_t group, + int preserve_existing, + char *verbose_fmt_string) +{ + struct stat stats; + int retval = 0; + + if (stat(argpath, &stats)) { + char *slash; + int tmp_mode; /* Initial perms for leading dirs. */ + int re_protect; /* Should leading dirs be unwritable? */ + struct ptr_list { + char *dirname_end; + struct ptr_list *next; + }; + struct ptr_list *p, *leading_dirs = NULL; + struct saved_cwd cwd; + char *basename_dir; + char *dirpath; + + /* Temporarily relax umask in case it's overly restrictive. */ + mode_t oldmask = umask (0); + + /* Make a copy of ARGPATH that we can scribble NULs on. */ + dirpath = (char *)alloca(strlen(argpath) + 1); + strcpy (dirpath, argpath); + strip_trailing_slashes(dirpath); + + /* If leading directories shouldn't be writable or executable, + or should have set[ug]id or sticky bits set and we are setting + their owners, we need to fix their permissions after making them. */ + if (((parent_mode & WX_USR) != WX_USR) + || ((owner != (uid_t) -1 || group != (gid_t) -1) + && (parent_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0)) + { + tmp_mode = S_IRWXU; + re_protect = 1; + } + else { + tmp_mode = parent_mode; + re_protect = 0; + } + + /* If we can record the current working directory, we may be able + to do the chdir optimization. */ + cwd.do_chdir = !save_cwd(&cwd); + + /* If we've saved the cwd and DIRPATH is an absolute pathname, + we must chdir to `/' in order to enable the chdir optimization. + So if chdir ("/") fails, turn off the optimization. */ + if (cwd.do_chdir && *dirpath == '/' && chdir ("/") < 0) { + cwd.do_chdir = 0; + } + + slash = dirpath; + + /* Skip over leading slashes. */ + while (*slash == '/') + slash++; + + while (1) { + int newly_created_dir; + int fail; + + /* slash points to the leftmost unprocessed component of dirpath. */ + basename_dir = slash; + + slash = strchr (slash, '/'); + if (slash == NULL) { + break; + } + + /* If we're *not* doing chdir before each mkdir, then we have to refer + to the target using the full (multi-component) directory name. */ + if (!cwd.do_chdir) { + basename_dir = dirpath; + } + + *slash = '\0'; + fail = make_dir(jcr, basename_dir, dirpath, tmp_mode, &newly_created_dir); + if (fail) { + umask(oldmask); + cleanup(&cwd); + return 1; + } + + if (newly_created_dir) { + Dmsg0(300, "newly_created_dir\n"); + if (verbose_fmt_string) { + Jmsg(jcr, M_ERROR, 0, verbose_fmt_string, quote(dirpath)); + } + + if ((owner != (uid_t) -1 || group != (gid_t) -1) + && chown (basename_dir, owner, group) +#if defined(AFS) && defined (EPERM) + && errno != EPERM +#endif + ) { + Jmsg(jcr, M_ERROR, 0, "Cannot change owner and/or group of %s: %s\n", + quote (dirpath), strerror(errno)); + umask(oldmask); + cleanup(&cwd); + return 1; + } + Dmsg0(300, "Chown done.\n"); + + if (re_protect) { + struct ptr_list *pnew = (struct ptr_list *) + alloca (sizeof (struct ptr_list)); + pnew->dirname_end = slash; + pnew->next = leading_dirs; + leading_dirs = pnew; + Dmsg0(300, "re_protect\n"); + } + } + + /* If we were able to save the initial working directory, + then we can use chdir to change into each directory before + creating an entry in that directory. This avoids making + stat and mkdir process O(n^2) file name components. */ + if (cwd.do_chdir && chdir(basename_dir) < 0) { + Jmsg(jcr, M_ERROR, 0, "Cannot chdir to directory, %s: %s\n", + quote (dirpath), strerror(errno)); + umask(oldmask); + cleanup(&cwd); + return 1; + } + + *slash++ = '/'; + + /* Avoid unnecessary calls to `stat' when given + pathnames containing multiple adjacent slashes. */ + while (*slash == '/') + slash++; + } /* end while (1) */ + + if (!cwd.do_chdir) { + basename_dir = dirpath; + } + + /* We're done making leading directories. + Create the final component of the path. */ + + Dmsg1(300, "Create final component. mode=%o\n", mode); + if (make_dir(jcr, basename_dir, dirpath, mode, NULL)) { + umask(oldmask); + cleanup(&cwd); + return 1; + } + + /* Done creating directories. Restore original umask. */ + umask (oldmask); + + if (verbose_fmt_string != NULL) { + Jmsg(jcr, M_ERROR, 0, verbose_fmt_string, dirpath); + } + + if (owner != (uid_t) -1 || group != (gid_t) -1) { + if (chown(basename_dir, owner, group) +#ifdef AFS + && errno != EPERM +#endif + ) + { + Jmsg(jcr, M_ERROR, 0, "Cannot change owner and/or group of %s: %s\n", + quote (dirpath), strerror(errno)); + retval = 1; + } + } + + /* The above chown may have turned off some permission bits in MODE. + Another reason we may have to use chmod here is that mkdir(2) is + required to honor only the file permission bits. In particular, + it need not honor the `special' bits, so if MODE includes any + special bits, set them here. */ + if (mode & ~S_IRWXUGO) { + Dmsg1(300, "Final chmod mode=%o\n", mode); + } + if ((mode & ~S_IRWXUGO) && chmod(basename_dir, mode)) { + Jmsg(jcr, M_ERROR, 0, "Cannot change permissions of %s: %s\n", + quote(dirpath), strerror(errno)); + retval = 1; + } + + if (cleanup(&cwd)) + return 1; + + /* If the mode for leading directories didn't include owner "wx" + privileges, we have to reset their protections to the correct + value. */ + for (p = leading_dirs; p != NULL; p = p->next) { + *(p->dirname_end) = '\0'; + Dmsg2(300, "Reset parent mode=%o dir=%s\n", parent_mode, dirpath); + if (chmod(dirpath, parent_mode)) { + Jmsg(jcr, M_ERROR, 0, "Cannot change permissions of %s: %s\n", + quote (dirpath), strerror(errno)); + retval = 1; + } + } + } else { + /* We get here if the entire path already exists. */ + + const char *dirpath = argpath; + + if (!S_ISDIR(stats.st_mode)) { + Jmsg(jcr, M_ERROR, 0, "%s exists but is not a directory\n", quote(dirpath)); + return 1; + } + + if (!preserve_existing) { + Dmsg0(300, "Do not preserve existing.\n"); + /* chown must precede chmod because on some systems, + chown clears the set[ug]id bits for non-superusers, + resulting in incorrect permissions. + On System V, users can give away files with chown and then not + be able to chmod them. So don't give files away. */ + + if ((owner != (uid_t) -1 || group != (gid_t) -1) + && chown(dirpath, owner, group) +#ifdef AFS + && errno != EPERM +#endif + ) + { + Jmsg(jcr, M_ERROR, 0, "Cannot change owner and/or group of %s: %s\n", + quote(dirpath), strerror(errno)); + retval = 1; + } + if (chmod(dirpath, mode)) { + Jmsg(jcr, M_ERROR, 0, "Cannot change permissions of %s: %s\n", + quote(dirpath), strerror(errno)); + retval = 1; + } + Dmsg2(300, "pathexists chmod mode=%o dir=%s\n", mode, dirpath); + } + } + return retval; +} diff --git a/bacula/src/findlib/match.c b/bacula/src/findlib/match.c index 2b01f3d100..318781ddb9 100644 --- a/bacula/src/findlib/match.c +++ b/bacula/src/findlib/match.c @@ -120,6 +120,9 @@ void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname) case 'f': inc->options |= OPT_multifs; break; + case 's': + inc->options |= OPT_sparse; + break; case 'V': /* verify options */ /* Copy Verify Options */ for (j=0; *p && *p != ':'; p++) { @@ -203,6 +206,7 @@ struct s_included_file *get_next_included_file(FF_PKT *ff, struct s_included_fil inc = ainc->next; } if (inc) { + ff->flags = inc->options; if (inc->options & OPT_compute_MD5) { ff->compute_MD5 = 1; } else { diff --git a/bacula/src/findlib/protos.h b/bacula/src/findlib/protos.h new file mode 100644 index 0000000000..69b5c2b677 --- /dev/null +++ b/bacula/src/findlib/protos.h @@ -0,0 +1,59 @@ +/* + * Prototypes for finlib directory of Bacula + * + * Version $Id$ + */ +/* + Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +/* from attribs.c */ +void encode_stat (char *buf, struct stat *statp); +void decode_stat (char *buf, struct stat *statp); +int encode_attribsEx (void *jcr, char *attribsEx, FF_PKT *ff_pkt); +int set_attributes(void *jcr, char *fname, char *ofile, char *lname, + int type, int stream, struct stat *statp, + char *attribsEx, int *ofd); + +/* from create_file.c */ +int create_file(void *jcr, char *fname, char *ofile, char *lname, + int type, int stream, struct stat *statp, + char *attribsEx, int *ofd); + +/* From find.c */ +FF_PKT *init_find_files(); +void set_find_options(FF_PKT *ff, int incremental, time_t mtime); +int find_files(FF_PKT *ff, int sub(FF_PKT *ff_pkt, void *hpkt), void *pkt); +void term_find_files(FF_PKT *ff); + +/* From match.c */ +void init_include_exclude_files(FF_PKT *ff); +void term_include_exclude_files(FF_PKT *ff); +void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname); +void add_fname_to_exclude_list(FF_PKT *ff, char *fname); +int file_is_excluded(FF_PKT *ff, char *file); +int file_is_included(FF_PKT *ff, char *file); +struct s_included_file *get_next_included_file(FF_PKT *ff, + struct s_included_file *inc); + + +/* from makepath.c */ +int make_path(void *jcr, const char *argpath, int mode, + int parent_mode, uid_t owner, gid_t group, + int preserve_existing, char *verbose_fmt_string); diff --git a/bacula/src/findlib/save-cwd.c b/bacula/src/findlib/save-cwd.c new file mode 100644 index 0000000000..89746eec86 --- /dev/null +++ b/bacula/src/findlib/save-cwd.c @@ -0,0 +1,115 @@ +/* save-cwd.c -- Save and restore current working directory. + + Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Jim Meyering . */ + +#include "bacula.h" +#include "save-cwd.h" + + + +/* Record the location of the current working directory in CWD so that + the program may change to other directories and later use restore_cwd + to return to the recorded location. This function may allocate + space using malloc (via xgetcwd) or leave a file descriptor open; + use free_cwd to perform the necessary free or close. Upon failure, + no memory is allocated, any locally opened file descriptors are + closed; return non-zero -- in that case, free_cwd need not be + called, but doing so is ok. Otherwise, return zero. */ + +int +save_cwd (struct saved_cwd *cwd) +{ + static int have_working_fchdir = 1; + + cwd->desc = -1; + cwd->name = NULL; + + if (have_working_fchdir) { +#if HAVE_FCHDIR + cwd->desc = open(".", O_RDONLY); + if (cwd->desc < 0) { + Emsg1(M_ERROR, 0, "Cannot open current directory: %s\n", strerror(errno)); + return 1; + } + +# if __sun__ || sun + /* On SunOS 4, fchdir returns EINVAL if accounting is enabled, + so we have to fall back to chdir. */ + if (fchdir (cwd->desc)) { + if (errno == EINVAL) { + close(cwd->desc); + cwd->desc = -1; + have_working_fchdir = 0; + } else { + Emsg1(M_ERROR, 0, "Current directory: %s\n", strerror(errno)); + close(cwd->desc); + cwd->desc = -1; + return 1; + } + } +# endif /* __sun__ || sun */ +#else +# define fchdir(x) (abort (), 0) + have_working_fchdir = 0; +#endif + } + + if (!have_working_fchdir) { + POOLMEM *buf = get_pool_memory(PM_FNAME); + cwd->name = (POOLMEM *)getcwd(buf, sizeof_pool_memory(buf)); + if (cwd->name == NULL) { + Emsg1(M_ERROR, 0, "Cannot get current directory: %s\n", strerror(errno)); + free_pool_memory(buf); + return 1; + } + } + return 0; +} + +/* Change to recorded location, CWD, in directory hierarchy. + If "saved working directory", NULL)) + */ + +int +restore_cwd(const struct saved_cwd *cwd, const char *dest, const char *from) +{ + int fail = 0; + if (cwd->desc >= 0) { + if (fchdir(cwd->desc)) { + Emsg4(M_ERROR, 0, "Cannot return to %s%s%s: %s\n", + (dest ? dest : "saved working directory"), + (from ? " from " : ""), + (from ? from : ""), strerror(errno)); + fail = 1; + } + } else if (chdir(cwd->name) < 0) { + Emsg2(M_ERROR, 0, "%s: %s\n", cwd->name, strerror(errno)); + fail = 1; + } + return fail; +} + +void +free_cwd(struct saved_cwd *cwd) +{ + if (cwd->desc >= 0) + close(cwd->desc); + if (cwd->name) + free_pool_memory(cwd->name); +} diff --git a/bacula/src/findlib/save-cwd.h b/bacula/src/findlib/save-cwd.h new file mode 100644 index 0000000000..0af93ece2a --- /dev/null +++ b/bacula/src/findlib/save-cwd.h @@ -0,0 +1,18 @@ + + +#ifndef SAVE_CWD_H +# define SAVE_CWD_H 1 + +struct saved_cwd + { + int do_chdir; + int desc; + char *name; + }; + +int save_cwd(struct saved_cwd *cwd); +int restore_cwd(const struct saved_cwd *cwd, const char *dest, + const char *from); +void free_cwd(struct saved_cwd *cwd); + +#endif diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 9533105b8a..dbf685cd4b 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -176,6 +176,7 @@ struct s_jcr { VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */ POOLMEM *job_name; /* base Job name (not unique) */ POOLMEM *fileset_name; /* FileSet */ + POOLMEM *fileset_md5; /* MD5 for FileSet */ POOLMEM *pool_name; /* pool to use */ POOLMEM *pool_type; /* pool type to use */ POOLMEM *media_type; /* media type */ diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 7c288c4e9d..1cf4e07363 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -33,22 +33,20 @@ dummy: LIBSRCS = alloc.c base64.c bmisc.c bnet.c bnet_server.c \ bshm.c btime.c \ - cram-md5.c crc32.c create_file.c daemon.c fnmatch.c \ + cram-md5.c crc32.c daemon.c fnmatch.c \ hmac.c idcache.c jcr.c lex.c \ - makepath.c \ md5.c message.c mem_pool.c parse_conf.c \ - queue.c rwlock.c save-cwd.c serial.c \ + queue.c rwlock.c serial.c \ signal.c smartall.c tree.c util.c watchdog.c workq.c # immortal.c filesys.c LIBOBJS = alloc.o base64.o bmisc.o bnet.o bnet_server.o \ bshm.o btime.o \ - cram-md5.o crc32.o create_file.o daemon.o fnmatch.o \ + cram-md5.o crc32.o daemon.o fnmatch.o \ hmac.o idcache.o jcr.o lex.o \ - makepath.o \ md5.o message.o mem_pool.o parse_conf.o \ - queue.o rwlock.o save-cwd.o serial.o \ + queue.o rwlock.o serial.o \ signal.o smartall.o tree.o util.o watchdog.o workq.o # immortal.o filesys.o diff --git a/bacula/src/lib/base64.c b/bacula/src/lib/base64.c index b4459f5cbf..ae8e2bfd65 100644 --- a/bacula/src/lib/base64.c +++ b/bacula/src/lib/base64.c @@ -127,95 +127,6 @@ from_base64(intmax_t *value, char *where) return i; } -/* Encode a stat structure into a base64 character string */ -void -encode_stat(char *buf, struct stat *statp) -{ - char *p = buf; - /* - * NOTE: we should use rdev as major and minor device if - * it is a block or char device (S_ISCHR(statp->st_mode) - * or S_ISBLK(statp->st_mode)). In all other cases, - * it is not used. - * - */ - p += to_base64((intmax_t)statp->st_dev, p); - *p++ = ' '; /* separate fields with a space */ - p += to_base64((intmax_t)statp->st_ino, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_mode, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_nlink, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_uid, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_gid, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_rdev, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_size, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_blksize, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_blocks, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_atime, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_mtime, p); - *p++ = ' '; - p += to_base64((intmax_t)statp->st_ctime, p); - *p++ = 0; - return; -} - - -/* Decode a stat packet from base64 characters */ -void -decode_stat(char *buf, struct stat *statp) -{ - char *p = buf; - intmax_t val; - - p += from_base64(&val, p); - statp->st_dev = val; - p++; /* skip space */ - p += from_base64(&val, p); - statp->st_ino = val; - p++; - p += from_base64(&val, p); - statp->st_mode = val; - p++; - p += from_base64(&val, p); - statp->st_nlink = val; - p++; - p += from_base64(&val, p); - statp->st_uid = val; - p++; - p += from_base64(&val, p); - statp->st_gid = val; - p++; - p += from_base64(&val, p); - statp->st_rdev = val; - p++; - p += from_base64(&val, p); - statp->st_size = val; - p++; - p += from_base64(&val, p); - statp->st_blksize = val; - p++; - p += from_base64(&val, p); - statp->st_blocks = val; - p++; - p += from_base64(&val, p); - statp->st_atime = val; - p++; - p += from_base64(&val, p); - statp->st_mtime = val; - p++; - p += from_base64(&val, p); - statp->st_ctime = val; - p++; -} /* * Encode binary data in bin of len bytes into @@ -285,7 +196,7 @@ int main(int argc, char *argv[]) #ifdef TEST_MODE static int errfunc(const char *epath, int eernoo) { - Dmsg0(-1, "in errfunc\n"); + printf("in errfunc\n"); return 1; } @@ -321,13 +232,16 @@ int main(int argc, char *argv[]) continue; } encode_stat(where, &statp); + + printf("Encoded stat=%s\n", where); + +#ifdef xxx p = where; p += to_base64((intmax_t)(statp.st_atime), p); *p++ = ' '; p += to_base64((intmax_t)t, p); printf("%s %s\n", fname, where); -#ifdef xxxx printf("%s %lld\n", "st_dev", (intmax_t)statp.st_dev); printf("%s %lld\n", "st_ino", (intmax_t)statp.st_ino); printf("%s %lld\n", "st_mode", (intmax_t)statp.st_mode); @@ -343,13 +257,11 @@ int main(int argc, char *argv[]) printf("%s %lld\n", "st_ctime", (intmax_t)statp.st_ctime); #endif - if (debug_level) printf("%s: len=%d val=%s\n", fname, strlen(where), where); decode_stat(where, &statn); -#ifdef xxx if (statp.st_dev != statn.st_dev || statp.st_ino != statn.st_ino || statp.st_mode != statn.st_mode || @@ -369,13 +281,15 @@ int main(int argc, char *argv[]) printf("%s: %s\n", fname, where); printf("NOT EQAL\n"); } -#endif } globfree(&my_glob); printf("%d files examined\n", i); + to_base64(UINT32_MAX, where); + printf("UINT32_MAX=%s\n", where); + return 0; } #endif diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 80b1a53cda..403c5f83e5 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -11,19 +11,19 @@ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ @@ -116,6 +116,7 @@ bnet_recv(BSOCK *bsock) int32_t nbytes; int32_t pktsiz; + bsock->msg[0] = 0; if (bsock->errors || bsock->terminated) { return -2; } diff --git a/bacula/src/lib/bsock.h b/bacula/src/lib/bsock.h index 54d1ed3d5c..d73782a3c3 100644 --- a/bacula/src/lib/bsock.h +++ b/bacula/src/lib/bsock.h @@ -14,19 +14,19 @@ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bacula/src/lib/btime.c b/bacula/src/lib/btime.c index 3ad074a8b1..a0325e6cc4 100644 --- a/bacula/src/lib/btime.c +++ b/bacula/src/lib/btime.c @@ -55,9 +55,25 @@ void get_current_time(struct date_time *dt) #endif } +/* + * Bacula's time (btime_t) is an unsigned 64 bit integer that contains + * the number of microseconds since Epoch Time (1 Jan 1970). + */ + btime_t get_current_btime() { - return (btime_t)time(NULL); + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) { + tv.tv_sec = (long)time(NULL); /* fall back to old method */ + tv.tv_usec = 0; + } + return ((btime_t)tv.tv_sec) * 1000000 + (btime_t)tv.tv_usec; +} + +/* Convert btime to Unix time */ +time_t btime_to_etime(btime_t bt) +{ + return (time_t)(bt/1000000); } diff --git a/bacula/src/lib/btime.h b/bacula/src/lib/btime.h index ced7cae2cc..6012b12303 100644 --- a/bacula/src/lib/btime.h +++ b/bacula/src/lib/btime.h @@ -36,46 +36,55 @@ #ifndef __btime_INCLUDED #define __btime_INCLUDED -typedef float64_t fdate_t; /* Date type */ -typedef float64_t ftime_t; /* Time type */ +/* New btime definition -- use this */ +extern btime_t get_current_btime(void); +extern time_t btime_to_etime(btime_t bt); + +extern void bstrftime(char *dt, int maxlen, uint32_t tim); + + +/* =========================================================== */ +/* old code deprecated below. Do not use. */ + +typedef float64_t fdate_t; /* Date type */ +typedef float64_t ftime_t; /* Time type */ struct date_time { - fdate_t julian_day_number; /* Julian day number */ + fdate_t julian_day_number; /* Julian day number */ ftime_t julian_day_fraction; /* Julian day fraction */ }; /* In arguments and results of the following functions, quantities are expressed as follows. - year Year in the Common Era. The canonical - date of adoption of the Gregorian calendar - (October 5, 1582 in the Julian calendar) - is assumed. + year Year in the Common Era. The canonical + date of adoption of the Gregorian calendar + (October 5, 1582 in the Julian calendar) + is assumed. - month Month index with January 0, December 11. + month Month index with January 0, December 11. - day Day number of month, 1 to 31. + day Day number of month, 1 to 31. */ -extern void bstrftime(char *dt, int maxlen, uint32_t tim); extern fdate_t date_encode(uint32_t year, uint8_t month, uint8_t day); extern ftime_t time_encode(uint8_t hour, uint8_t minute, uint8_t second, - float32_t second_fraction); + float32_t second_fraction); extern void date_time_encode(struct date_time *dt, - uint32_t year, uint8_t month, uint8_t day, - uint8_t hour, uint8_t minute, uint8_t second, - float32_t second_fraction); + uint32_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second, + float32_t second_fraction); extern void date_decode(fdate_t date, uint32_t *year, uint8_t *month, - uint8_t *day); + uint8_t *day); extern void time_decode(ftime_t time, uint8_t *hour, uint8_t *minute, - uint8_t *second, float32_t *second_fraction); + uint8_t *second, float32_t *second_fraction); extern void date_time_decode(struct date_time *dt, - uint32_t *year, uint8_t *month, uint8_t *day, - uint8_t *hour, uint8_t *minute, uint8_t *second, - float32_t *second_fraction); + uint32_t *year, uint8_t *month, uint8_t *day, + uint8_t *hour, uint8_t *minute, uint8_t *second, + float32_t *second_fraction); extern int date_time_compare(struct date_time *dt1, struct date_time *dt2); @@ -83,6 +92,5 @@ extern void tm_encode(struct date_time *dt, struct tm *tm); extern void tm_decode(struct date_time *dt, struct tm *tm); extern void get_current_time(struct date_time *dt); -extern btime_t get_current_btime(void); #endif /* __btime_INCLUDED */ diff --git a/bacula/src/lib/cram-md5.c b/bacula/src/lib/cram-md5.c index f40b35dfff..90310dbacd 100644 --- a/bacula/src/lib/cram-md5.c +++ b/bacula/src/lib/cram-md5.c @@ -10,19 +10,19 @@ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bacula/src/lib/crc32.c b/bacula/src/lib/crc32.c index 4f69f3cada..412499dc3d 100644 --- a/bacula/src/lib/crc32.c +++ b/bacula/src/lib/crc32.c @@ -9,19 +9,19 @@ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bacula/src/lib/hmac.c b/bacula/src/lib/hmac.c index 40432aa51e..8c79f98c2b 100644 --- a/bacula/src/lib/hmac.c +++ b/bacula/src/lib/hmac.c @@ -10,19 +10,19 @@ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bacula/src/lib/lex.c b/bacula/src/lib/lex.c index d1c94f26ee..6e9118d054 100644 --- a/bacula/src/lib/lex.c +++ b/bacula/src/lib/lex.c @@ -291,9 +291,9 @@ lex_get_token(LEX *lf, int expect) switch (lf->state) { case lex_none: Dmsg2(290, "Lex state lex_none ch=%d,%x\n", ch, ch); - if (ISSPACE(ch)) + if (B_ISSPACE(ch)) break; - if (ISALPHA(ch)) { + if (B_ISALPHA(ch)) { if (lf->options & LOPT_NO_IDENT) lf->state = lex_string; else @@ -301,7 +301,7 @@ lex_get_token(LEX *lf, int expect) begin_str(lf, ch); break; } - if (ISDIGIT(ch)) { + if (B_ISDIGIT(ch)) { lf->state = lex_number; begin_str(lf, ch); break; @@ -362,13 +362,13 @@ lex_get_token(LEX *lf, int expect) case lex_number: Dmsg2(290, "Lex state lex_number ch=%x %c\n", ch, ch); /* Might want to allow trailing specifications here */ - if (ISDIGIT(ch)) { + if (B_ISDIGIT(ch)) { add_str(lf, ch); break; } /* A valid number can be terminated by the following */ - if (ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') { + if (B_ISSPACE(ch) || ch == L_EOL || ch == ',' || ch == ';') { token = T_NUMBER; lf->state = lex_none; } else { @@ -382,7 +382,7 @@ lex_get_token(LEX *lf, int expect) case lex_string: Dmsg1(290, "Lex state lex_string ch=%x\n", ch); if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' || - ch == ';' || ch == ',' || ch == '#' || (ISSPACE(ch)) ) { + ch == ';' || ch == ',' || ch == '#' || (B_ISSPACE(ch)) ) { lex_unget_char(lf); token = T_UNQUOTED_STRING; lf->state = lex_none; @@ -392,10 +392,10 @@ lex_get_token(LEX *lf, int expect) break; case lex_identifier: Dmsg2(290, "Lex state lex_identifier ch=%x %c\n", ch, ch); - if (ISALPHA(ch)) { + if (B_ISALPHA(ch)) { add_str(lf, ch); break; - } else if (ISSPACE(ch)) { + } else if (B_ISSPACE(ch)) { break; } else if (ch == '\n' || ch == L_EOL || ch == '=' || ch == '}' || ch == '{' || ch == ';' || ch == ',' || ch == '"' || ch == '#') { @@ -436,7 +436,7 @@ lex_get_token(LEX *lf, int expect) add_str(lf, ch); break; case lex_include: /* scanning a filename */ - if (ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' || + if (B_ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' || ch == ';' || ch == ',' || ch == '"' || ch == '#') { lf->state = lex_none; lf = lex_open_file(lf, lf->str, NULL); diff --git a/bacula/src/lib/md5.h b/bacula/src/lib/md5.h index 53faa028b6..a927064be5 100644 --- a/bacula/src/lib/md5.h +++ b/bacula/src/lib/md5.h @@ -8,19 +8,19 @@ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index a0453f647a..1a78def5a7 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -488,8 +488,8 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass) /* Look for modifier */ ch = lc->str[lc->str_len - 1]; i = 0; - if (ISALPHA(ch)) { - if (ISUPPER(ch)) { + if (B_ISALPHA(ch)) { + if (B_ISUPPER(ch)) { ch = tolower(ch); } while (mod[++i] != 0) { diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 390b207829..4ec45a0cfe 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -27,8 +27,6 @@ void base64_init (void); int to_base64 (intmax_t value, char *where); int from_base64 (intmax_t *value, char *where); -void encode_stat (char *buf, struct stat *statp); -void decode_stat (char *buf, struct stat *statp); int bin_to_base64 (char *buf, char *bin, int len); /* bmisc.c */ @@ -44,9 +42,6 @@ int bvsnprintf (char *str, size_t size, const char *format, v int pool_sprintf (char *pool_buf, char *fmt, ...); void create_pid_file (char *dir, char *progname, int port); int delete_pid_file (char *dir, char *progname, int port); -#ifndef HAVE_STRERROR_R -int strerror_r (int errnum, char *buf, size_t bufsiz); -#endif /* bnet.c */ @@ -75,13 +70,6 @@ int cram_md5_auth(BSOCK *bs, char *password); void hmac_md5(uint8_t* text, int text_len, uint8_t* key, int key_len, uint8_t *hmac); -/* create_file.c */ -int create_file(void *jcr, char *fname, char *ofile, char *lname, - int type, struct stat *statp, int *ofd); -int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type, - struct stat *statp); - - /* crc32.c */ uint32_t bcrc32(uint8_t *buf, int len); @@ -96,18 +84,6 @@ void lex_unget_char (LEX *lf); char * lex_tok_to_str (int token); int lex_get_token (LEX *lf, int expect); -/* makepath.c */ -int make_path( - void *jcr, - const char *argpath, - int mode, - int parent_mode, - uid_t owner, - gid_t group, - int preserve_existing, - char *verbose_fmt_string); - - /* message.c */ void my_name_is (int argc, char *argv[], char *name); void init_msg (void *jcr, MSGS *msg); @@ -151,6 +127,7 @@ char * add_commas (char *val, char *buf); char * edit_uint64 (uint64_t val, char *buf); int do_shell_expansion (char *name); int is_a_number (const char *num); +int is_buf_zero (char *buf, int len); int string_to_btime (char *str, btime_t *value); char *edit_btime (btime_t val, char *buf); void jobstatus_to_ascii (int JobStatus, char *msg, int maxlen); diff --git a/bacula/src/lib/tree.c b/bacula/src/lib/tree.c index 959529e155..407cf21111 100755 --- a/bacula/src/lib/tree.c +++ b/bacula/src/lib/tree.c @@ -27,7 +27,6 @@ #include "bacula.h" #include "findlib/find.h" -#include "findlib/system.h" #ifndef MAXPATHLEN #define MAXPATHLEN 1000 diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 4c9e03e6b3..d702a45f2f 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -35,6 +35,31 @@ * */ +/* Return true of buffer has all zero bytes */ +int is_buf_zero(char *buf, int len) +{ + uint64_t *ip = (uint64_t *)buf; + char *p; + int i, len64, done, rem; + + /* Optimize by checking uint64_t for zero */ + len64 = len >> sizeof(uint64_t); + for (i=0; i < len64; i++) { + if (ip[i] != 0) { + return 0; + } + } + done = len64 << sizeof(uint64_t); /* bytes already checked */ + p = buf + done; + rem = len - done; + for (i = 0; i < rem; i++) { + if (p[i] != 0) { + return 0; + } + } + return 1; +} + /* * Convert a string duration to btime_t (64 bit seconds) * Returns 0: if error @@ -52,8 +77,8 @@ int string_to_btime(char *str, btime_t *value) len = strlen(str); ch = str[len - 1]; i = 0; - if (ISALPHA(ch)) { - if (ISUPPER(ch)) { + if (B_ISALPHA(ch)) { + if (B_ISUPPER(ch)) { ch = tolower(ch); } while (mod[++i] != 0) { @@ -116,18 +141,18 @@ int is_a_number(const char *n) if( *n == '-' || *n == '+' ) { n++; } - while (ISDIGIT(*n)) { + while (B_ISDIGIT(*n)) { digit_seen = 1; n++; } if (digit_seen && *n == '.') { n++; - while (ISDIGIT(*n)) { n++; } + while (B_ISDIGIT(*n)) { n++; } } if (digit_seen && (*n == 'e' || *n == 'E') - && (ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && ISDIGIT(n[2])))) { + && (B_ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && B_ISDIGIT(n[2])))) { n += 2; /* skip e- or e+ or e digit */ - while (ISDIGIT(*n)) { n++; } + while (B_ISDIGIT(*n)) { n++; } } return digit_seen && *n==0; } @@ -191,7 +216,7 @@ char *add_commas(char *val, char *buf) void lcase(char *str) { while (*str) { - if (ISUPPER(*str)) + if (B_ISUPPER(*str)) *str = tolower((int)(*str)); str++; } @@ -296,10 +321,10 @@ fstrsch(char *a, char *b) /* folded case search */ return 0; /* failed */ } while (*a) { /* do it over the correct slow way */ - if (ISUPPER(c1 = *a)) { + if (B_ISUPPER(c1 = *a)) { c1 = tolower((int)c1); } - if (ISUPPER(c2 = *b)) { + if (B_ISUPPER(c2 = *b)) { c2 = tolower((int)c2); } if (c1 != c2) { diff --git a/bacula/src/stored/Makefile.in b/bacula/src/stored/Makefile.in index 0b7a996eb3..5216ca33c7 100644 --- a/bacula/src/stored/Makefile.in +++ b/bacula/src/stored/Makefile.in @@ -38,19 +38,19 @@ TAPEOBJS = btape.o block.o butil.o dev.o device.o label.o \ stored_conf.o match_bsr.o parse_bsr.o # bls -BLSOBJS = bls.o block.o device.o dev.o label.o match_bsr.o \ - acquire.o mount.o parse_bsr.o record.o butil.o \ - read_record.o +BLSOBJS = bls.o block.o butil.o device.o dev.o label.o match_bsr.o \ + acquire.o mount.o parse_bsr.o record.o \ + read_record.o stored_conf.o # bextract BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \ acquire.o mount.o match_bsr.o parse_bsr.o butil.o \ - read_record.o + read_record.o stored_conf.o # bscan SCNOBJS = bscan.o block.o device.o dev.o label.o \ acquire.o mount.o record.o match_bsr.o parse_bsr.o \ - butil.o read_record.o + butil.o read_record.o stored_conf.o # bpool is deprecated @@ -91,13 +91,13 @@ btape: $(TAPEOBJS) ../lib/libbac.a ../cats/libsql.a $(CXX) $(TTOOL_LDFLSGS) $(LDFLAGS) -L../lib -L../cats -o $@ $(TAPEOBJS) -lsql $(LIBS) $(DLIB) -lbac -lm bls: ../findlib/libfind.a $(BLSOBJS) ../lib/libbac.a - $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BLSOBJS) $(LIBS) $(DLIB) -lbac -lfind -lm + $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BLSOBJS) $(LIBS) $(DLIB) -lfind -lbac -lm bextract: ../findlib/libfind.a $(BEXTOBJS) ../lib/libbac.a - $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BEXTOBJS) $(LIBS) $(DLIB) $(FDLIBS) -lbac -lfind -lm + $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(BEXTOBJS) $(LIBS) $(DLIB) $(FDLIBS) -lfind -lbac -lm bscan: ../findlib/libfind.a $(SCNOBJS) ../cats/libsql.a - $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SCNOBJS) -lsql $(LIBS) $(DB_LIBS) $(FDLIBS) -lbac -lfind -lm + $(CXX) $(TTOOL_LDFLAGS) $(LDFLAGS) -L../lib -L../cats -L../findlib -o $@ $(SCNOBJS) -lsql $(LIBS) $(DB_LIBS) $(FDLIBS) -lfind -lbac -lm diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 2ba9addb45..95938dae0d 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -93,7 +93,7 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) default_path: tape_previously_mounted = 0; Dmsg0(200, "dir_get_volume_info\n"); - dir_get_volume_info(jcr, 0); + dir_get_volume_info(jcr, 0); /* Get info for reading */ Dmsg2(200, "calling autoload Vol=%s Slot=%d\n", jcr->VolumeName, jcr->VolCatInfo.Slot); if (autoload_device(jcr, dev, 0, NULL)) { @@ -144,16 +144,15 @@ int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) * Device already in append mode * * Check if we have the right Volume mounted - * OK if AnonVols and volume info OK - * OK if next volume matches current volume - * otherwise mount desired volume obtained from + * OK if current volume info OK + * OK if next volume matches current volume + * otherwise mount desired volume obtained from * dir_find_next_appendable_volume */ strcpy(jcr->VolumeName, dev->VolHdr.VolName); - if (((dev->capabilities & CAP_ANONVOLS) && - !dir_get_volume_info(jcr, 1)) || - (!dir_find_next_appendable_volume(jcr) || - strcmp(dev->VolHdr.VolName, jcr->VolumeName) != 0)) { /* wrong tape mounted */ + if (!dir_get_volume_info(jcr, 1) || + !(dir_find_next_appendable_volume(jcr) && + strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */ if (dev->num_writers != 0) { Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing with another Volume.\n"), dev_name(dev)); goto get_out; diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 70e97574d9..1a47a3ba4e 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -98,7 +98,21 @@ int do_append_data(JCR *jcr) memset(&rec, 0, sizeof(rec)); /* - * Get Data from File daemon, write to device + * Get Data from File daemon, write to device. To clarify what is + * going on here. We expect: + * - A stream header + * - Multiple records of data + * - EOD record + * + * The Stream header is just used to sychronize things, and + * none of the stream header is written to tape. + * The Multiple records of data, contain first the Attributes, + * then after another stream header, the file data, then + * after another stream header, the MD5 data if any. + * + * So we get the (stream header, data, EOD) three time for each + * file. 1. for the Attributes, 2. for the file data if any, + * and 3. for the MD5 if any. */ jcr->VolFirstFile = 0; time(&jcr->run_time); /* start counting time for rates */ @@ -110,6 +124,7 @@ int do_append_data(JCR *jcr) * file_index (sequential Bacula file index) * stream (arbitrary Bacula number to distinguish parts of data) * info (Info for Storage daemon -- compressed, encryped, ...) + * info is not currently used, so is read, but ignored! */ if ((n=bget_msg(ds)) < 0) { Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"), @@ -158,7 +173,7 @@ int do_append_data(JCR *jcr) rec.data = ds->msg; /* use message buffer */ Dmsg4(250, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n", - rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream), + rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex), rec.data_len); while (!write_record_to_block(block, &rec)) { @@ -179,15 +194,18 @@ int do_append_data(JCR *jcr) break; } jcr->JobBytes += rec.data_len; /* increment bytes this job */ - Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n", + Dmsg4(200, "write_record FI=%s SessId=%d Strm=%s len=%d\n", FI_to_ascii(rec.FileIndex), rec.VolSessionId, - stream_to_ascii(rec.Stream), rec.data_len); + stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len); + /* Send attributes and MD5 to Director for Catalog */ - if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE) { + if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE || + stream == STREAM_WIN32_ATTRIBUTES) { if (!jcr->no_attributes) { if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) { jcr->dir_bsock->spool = 1; } + Dmsg0(200, "Send attributes.\n"); if (!dir_update_file_attributes(jcr, &rec)) { Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"), bnet_strerror(jcr->dir_bsock)); diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 73120bf44b..00e6612084 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -254,7 +254,6 @@ int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) int wait_sec; int num_wait = 0; int dev_blocked; - char *msg; Dmsg0(130, "enter dir_ask_sysop_to_mount_next_volume\n"); ASSERT(dev->dev_blocked); @@ -278,15 +277,10 @@ int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) Dmsg0(190, "Return 1 from mount without wait.\n"); return 1; } - if (dev->capabilities & CAP_ANONVOLS) { - msg = "Suggest mounting"; - } else { - msg = "Please mount"; - } Jmsg(jcr, M_MOUNT, 0, _( -"%s Volume \"%s\" on Storage Device \"%s\" for Job %s\n" +"Please mount Volume \"%s\" on Storage Device \"%s\" for Job %s\n" "Use \"mount\" command to release Job.\n"), - msg, jcr->VolumeName, jcr->dev_name, jcr->Job); + jcr->VolumeName, jcr->dev_name, jcr->Job); Dmsg3(190, "Mount %s on %s for Job %s\n", jcr->VolumeName, jcr->dev_name, jcr->Job); } else { diff --git a/bacula/src/stored/authenticate.c b/bacula/src/stored/authenticate.c index 90926e0889..df7bb393dc 100644 --- a/bacula/src/stored/authenticate.c +++ b/bacula/src/stored/authenticate.c @@ -46,10 +46,14 @@ static int authenticate(int rcode, BSOCK *bs) Emsg1(M_FATAL, 0, _("I only authenticate Directors, not %d\n"), rcode); return 0; } + if (bs->msglen > 200) { + bs->msglen = 200; + } dirname = get_pool_memory(PM_MESSAGE); dirname = check_pool_memory_size(dirname, bs->msglen); if (sscanf(bs->msg, "Hello Director %127s calling\n", dirname) != 1) { + bs->msg[100] = 0; Emsg1(M_FATAL, 0, _("Bad Hello command from Director: %s\n"), bs->msg); return 0; } diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 5bab15516b..70f474d1ec 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -53,6 +53,7 @@ static long total = 0; static POOLMEM *fname; /* original file name */ static POOLMEM *ofile; /* output name with prefix */ static POOLMEM *lname; /* link name */ +static POOLMEM *attribsEx; /* extended attributes (Win32) */ static char *where; static int wherelen; /* prefix length */ static uint32_t num_files = 0; @@ -60,6 +61,16 @@ static struct stat statp; static uint32_t compress_buf_size = 70000; static POOLMEM *compress_buf; static int type; +static int stream; +static int prog_name_msg = 0; + +static char *wbuf; /* write buffer address */ +static uint32_t wsize; /* write size */ +static uint64_t fileAddr = 0; /* file write address */ + +#define CONFIG_FILE "bacula-sd.conf" +char *configfile; + static void usage() { @@ -67,6 +78,7 @@ static void usage() "\nVersion: " VERSION " (" DATE ")\n\n" "Usage: bextract [-d debug_level] \n" " -b specify a bootstrap file\n" +" -c specify a configuration file\n" " -dnn set debug level to nn\n" " -e exclude list\n" " -i include list\n" @@ -89,13 +101,20 @@ int main (int argc, char *argv[]) memset(ff, 0, sizeof(FF_PKT)); init_include_exclude_files(ff); - while ((ch = getopt(argc, argv, "b:d:e:i:?")) != -1) { + while ((ch = getopt(argc, argv, "b:c:d:e:i:?")) != -1) { switch (ch) { case 'b': /* bootstrap file */ bsr = parse_bsr(NULL, optarg); // dump_bsr(bsr); break; + case 'c': /* specify config file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; + case 'd': /* debug level */ debug_level = atoi(optarg); if (debug_level <= 0) @@ -144,6 +163,13 @@ int main (int argc, char *argv[]) Pmsg0(0, "Wrong number of arguments: \n"); usage(); } + + if (configfile == NULL) { + configfile = bstrdup(CONFIG_FILE); + } + + parse_config(configfile); + if (!got_inc) { /* If no include file, */ add_fname_to_include_list(ff, 0, "/"); /* include everything */ } @@ -161,7 +187,7 @@ static void do_extract(char *devname) { jcr = setup_jcr("bextract", devname, bsr); - dev = setup_to_read_device(jcr); + dev = setup_to_access_device(jcr, 1); /* acquire for read */ if (!dev) { exit(1); } @@ -179,9 +205,7 @@ static void do_extract(char *devname) fname = get_pool_memory(PM_FNAME); ofile = get_pool_memory(PM_FNAME); lname = get_pool_memory(PM_FNAME); - - - + attribsEx = get_pool_memory(PM_FNAME); compress_buf = get_memory(compress_buf_size); @@ -190,8 +214,8 @@ static void do_extract(char *devname) * archive since we just hit an end of file, so close the file. */ if (ofd >= 0) { - close(ofd); - set_statp(jcr, fname, ofile, lname, type, &statp); + set_attributes(jcr, fname, ofile, lname, type, stream, &statp, + attribsEx, &ofd); } release_device(jcr, dev); @@ -210,25 +234,27 @@ static void do_extract(char *devname) */ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) { + if (rec->FileIndex < 0) { return; /* we don't want labels */ } /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES) { - char *ap, *lp, *fp; + if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) { + char *ap, *lp, *fp, *apex; + + stream = rec->Stream; /* If extracting, it was from previous stream, so * close the output file. */ if (extract) { if (ofd < 0) { - Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n"); + Emsg0(M_ERROR, 0, "Logic error output file should be open\n"); } - close(ofd); - ofd = -1; extract = FALSE; - set_statp(jcr, fname, ofile, lname, type, &statp); + set_attributes(jcr, fname, ofile, lname, type, stream, &statp, + attribsEx, &ofd); } if (sizeof_pool_memory(fname) < rec->data_len) { @@ -250,6 +276,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) * Filename * Attributes * Link name (if file linked i.e. FT_LNK) + * Extended Attributes (Win32) * */ sscanf(rec->data, "%ld %d", &record_file_index, &type); @@ -278,6 +305,19 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) lp = ""; } + if (rec->Stream == STREAM_WIN32_ATTRIBUTES) { + apex = ap; /* start at attributes */ + while (*apex++ != 0) { /* skip attributes */ + ; + } + while (*apex++ != 0) { /* skip link name */ + ; + } + pm_strcpy(&attribsEx, apex); /* make a copy of Extended attributes */ + } else { + *attribsEx = 0; /* no extended attributes */ + } + if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) { @@ -287,84 +327,120 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) * files are put where the user wants. * * We do a little jig here to handle Win32 files with - * a drive letter. - * If where is null and we are running on a win32 client, - * change nothing. - * Otherwise, if the second character of the filename is a - * colon (:), change it into a slash (/) -- this creates - * a reasonable pathname on most systems. + * a drive letter -- we simply strip the drive: from + * every filename if a prefix is supplied. */ - if (where[0] == 0 && win32_client) { + if (where[0] == 0) { strcpy(ofile, fname); strcpy(lname, lp); } else { + char *fn; strcpy(ofile, where); - if (fname[1] == ':') { - fname[1] = '/'; - strcat(ofile, fname); - fname[1] = ':'; + if (win32_client && fname[1] == ':') { + fn = fname+2; /* skip over drive: */ } else { - strcat(ofile, fname); + fn = fname; /* take whole name */ + } + /* Ensure where is terminated with a slash */ + if (where[wherelen-1] != '/' && fn[0] != '/') { + strcat(ofile, "/"); } + strcat(ofile, fn); /* copy rest of name */ /* Fixup link name */ if (type == FT_LNK || type == FT_LNKSAVED) { if (lp[0] == '/') { /* if absolute path */ strcpy(lname, where); } - /* ***FIXME**** we shouldn't have links on Windoz */ - if (lp[1] == ':') { - lp[1] = '/'; - strcat(lname, lp); - lp[1] = ':'; + if (win32_client && lp[1] == ':') { + strcat(lname, lp+2); /* copy rest of name */ } else { - strcat(lname, lp); + strcat(lname, lp); /* On Unix systems we take everything */ } } } - /* Pmsg1(000, "Restoring: %s\n", ofile); */ + /* Pmsg1(000, "Restoring: %s\n", ofile); */ - extract = create_file(jcr, fname, ofile, lname, type, &statp, &ofd); + extract = create_file(jcr, fname, ofile, lname, type, stream, + &statp, attribsEx, &ofd); num_files++; if (extract) { print_ls_output(ofile, lname, type, &statp); + fileAddr = 0; } } /* Data stream and extracting */ - } else if (rec->Stream == STREAM_FILE_DATA) { + } else if (rec->Stream == STREAM_FILE_DATA || rec->Stream == STREAM_SPARSE_DATA) { if (extract) { - total += rec->data_len; - Dmsg2(8, "Write %ld bytes, total=%ld\n", rec->data_len, total); - if ((uint32_t)write(ofd, rec->data, rec->data_len) != rec->data_len) { - Emsg1(M_ERROR_TERM, 0, "Write error: %s\n", strerror(errno)); + if (rec->Stream == STREAM_SPARSE_DATA) { + ser_declare; + uint64_t faddr; + wbuf = rec->data + SPARSE_FADDR_SIZE; + wsize = rec->data_len - SPARSE_FADDR_SIZE; + ser_begin(rec->data, SPARSE_FADDR_SIZE); + unser_uint64(faddr); + if (fileAddr != faddr) { + fileAddr = faddr; + if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) { + Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno)); + } + } + } else { + wbuf = rec->data; + wsize = rec->data_len; + } + total += wsize; + Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total); + if ((uint32_t)write(ofd, wbuf, wsize) != wsize) { + Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno)); } + fileAddr += wsize; } } else if (rec->Stream == STREAM_GZIP_DATA) { #ifdef HAVE_LIBZ if (extract) { uLongf compress_len; - + int stat; + + if (rec->Stream == STREAM_SPARSE_GZIP_DATA) { + ser_declare; + uint64_t faddr; + wbuf = rec->data + SPARSE_FADDR_SIZE; + wsize = rec->data_len - SPARSE_FADDR_SIZE; + ser_begin(rec->data, SPARSE_FADDR_SIZE); + unser_uint64(faddr); + if (fileAddr != faddr) { + fileAddr = faddr; + if (lseek(ofd, (off_t)fileAddr, SEEK_SET) < 0) { + Emsg2(M_ERROR, 0, _("Seek error on %s: %s\n"), ofile, strerror(errno)); + } + } + } else { + wbuf = rec->data; + wsize = rec->data_len; + } compress_len = compress_buf_size; - if (uncompress((Bytef *)compress_buf, &compress_len, - (const Bytef *)rec->data, (uLong)rec->data_len) != Z_OK) { - Emsg0(M_ERROR_TERM, 0, _("Uncompression error.\n")); + if ((stat=uncompress((Bytef *)compress_buf, &compress_len, + (const Bytef *)wbuf, (uLong)wsize) != Z_OK)) { + Emsg1(M_ERROR_TERM, 0, _("Uncompression error. ERR=%d\n"), stat); } Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total); if ((uLongf)write(ofd, compress_buf, (size_t)compress_len) != compress_len) { Pmsg0(0, "===Write error===\n"); - Emsg2(M_ERROR_TERM, 0, "Write error on %s: %s\n", ofile, strerror(errno)); + Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), ofile, strerror(errno)); } total += compress_len; + fileAddr += compress_len; Dmsg2(100, "Compress len=%d uncompressed=%d\n", rec->data_len, compress_len); } #else if (extract) { - Emsg0(M_ERROR_TERM, 0, "GZIP data stream found, but GZIP not configured!\n"); + Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n"); } #endif @@ -372,12 +448,16 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) /* If extracting, wierd stream (not 1 or 2), close output file anyway */ } else if (extract) { if (ofd < 0) { - Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n"); + Emsg0(M_ERROR, 0, "Logic error output file should be open\n"); } - close(ofd); - ofd = -1; extract = FALSE; - set_statp(jcr, fname, ofile, lname, type, &statp); + set_attributes(jcr, fname, ofile, lname, type, stream, &statp, + attribsEx, &ofd); + } else if (rec->Stream == STREAM_PROGRAM_NAMES || rec->Stream == STREAM_PROGRAM_DATA) { + if (!prog_name_msg) { + Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n"); + prog_name_msg = 1; + } } else if (rec->Stream != STREAM_MD5_SIGNATURE) { Pmsg2(0, "None of above!!! stream=%d data=%s\n", rec->Stream, rec->data); } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index cd6a0a1064..6d1df90b4d 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -3,6 +3,7 @@ * block.c -- tape block handling functions * * Kern Sibbald, March MMI + * added BB02 format October MMII * * Version $Id$ * @@ -69,28 +70,28 @@ void dump_block(DEV_BLOCK *b, char *msg) } if (block_len > 100000) { - Dmsg3(20, "Dump block %s %s blocksize too big %d\n", msg, b, block_len); + Dmsg3(20, "Dump block %s 0x%x blocksize too big %u\n", msg, b, block_len); return; } BlockCheckSum = bcrc32((uint8_t *)b->buf+BLKHDR_CS_LENGTH, block_len-BLKHDR_CS_LENGTH); - Dmsg6(10, "Dump block %s %x: size=%d BlkNum=%d\n\ + Pmsg6(000, "Dump block %s %x: size=%d BlkNum=%d\n\ Hdrcksum=%x cksum=%x\n", msg, b, block_len, BlockNumber, CheckSum, BlockCheckSum); p = b->buf + bhl; while (p < (b->buf + block_len+WRITE_RECHDR_LENGTH)) { unser_begin(p, WRITE_RECHDR_LENGTH); if (rhl == RECHDR1_LENGTH) { - unser_uint32(VolSessionId); - unser_uint32(VolSessionTime); + unser_uint32(VolSessionId); + unser_uint32(VolSessionTime); } unser_int32(FileIndex); unser_int32(Stream); unser_uint32(data_len); - Dmsg6(10, " Rec: VId=%d VT=%d FI=%s Strm=%s len=%d p=%x\n", - VolSessionId, VolSessionTime, FI_to_ascii(FileIndex), stream_to_ascii(Stream), - data_len, p); + Pmsg6(000, " Rec: VId=%u VT=%u FI=%s Strm=%s len=%d p=%x\n", + VolSessionId, VolSessionTime, FI_to_ascii(FileIndex), + stream_to_ascii(Stream, FileIndex), data_len, p); p += data_len + rhl; } } @@ -111,11 +112,14 @@ DEV_BLOCK *new_block(DEVICE *dev) } else { block->buf_len = dev->max_block_size; } + /* ****FIXME***** move this up to init_dev() */ if (block->buf_len % TAPE_BSIZE != 0) { - Mmsg2(&dev->errmsg, _("Block size %d forced to be multiple of %d\n"), - block->buf_len, TAPE_BSIZE); + uint32_t old_len = block->buf_len; + block->buf_len = ((old_len + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE; + Mmsg3(&dev->errmsg, _("Block size %u forced to %u to be multiple of %d\n"), + old_len, block->buf_len, TAPE_BSIZE); Emsg0(M_WARNING, 0, dev->errmsg); - block->buf_len = ((block->buf_len + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE; + dev->max_block_size = block->buf_len; /* force block size */ } block->block_len = block->buf_len; /* default block size */ block->buf = get_memory(block->buf_len); @@ -332,8 +336,6 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block) } } - dev->block_num++; - block->BlockNumber = dev->block_num; ser_block_header(block); /* Limit maximum Volume size to value specified by user */ @@ -351,7 +353,7 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block) } dev->VolCatInfo.VolCatWrites++; -// Dmsg1(000, "Pos before write=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR)); + Dmsg1(500, "Write block of %u bytes\n", wlen); if ((uint32_t) (stat=write(dev->fd, block->buf, (size_t)wlen)) != wlen) { /* We should check for errno == ENOSPC, BUT many * devices simply report EIO when it is full. @@ -368,11 +370,11 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block) dev->dev_errno = ENOSPC; /* out of space */ } - Dmsg2(0, "=== Write error errno=%d: ERR=%s\n", dev->dev_errno, - strerror(dev->dev_errno)); + Dmsg4(10, "=== Write error. size=%u rtn=%d errno=%d: ERR=%s\n", + wlen, stat, dev->dev_errno, strerror(dev->dev_errno)); - Mmsg2(&dev->errmsg, _("Write error on device %s. ERR=%s.\n"), - dev->dev_name, strerror(dev->dev_errno)); + Mmsg4(&dev->errmsg, _("Write error on device %s. Write of %u bytes got %d. ERR=%s.\n"), + dev->dev_name, wlen, stat, strerror(dev->dev_errno)); block->failed_write = TRUE; weof_dev(dev, 1); /* end the tape */ weof_dev(dev, 1); /* write second eof */ @@ -381,15 +383,17 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block) // Dmsg1(000, "Pos after write=%lld\n", lseek(dev->fd, (off_t)0, SEEK_CUR)); dev->VolCatInfo.VolCatBytes += block->binbuf; dev->VolCatInfo.VolCatBlocks++; - dev->file_bytes += block->binbuf; + dev->file_addr += wlen; /* Limit maximum File size on volume to user specified value */ if (dev->state & ST_TAPE) { - if ((dev->max_file_size > 0) && dev->file_bytes >= dev->max_file_size) { - weof_dev(dev, 1); /* write eof */ - } + if ((dev->max_file_size > 0) && dev->file_addr >= dev->max_file_size) { + weof_dev(dev, 1); /* write eof */ + } } + dev->block_num++; + block->BlockNumber++; Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num, wlen); empty_block(block); diff --git a/bacula/src/stored/block.h b/bacula/src/stored/block.h index ca265dea7c..90f10a06dd 100644 --- a/bacula/src/stored/block.h +++ b/bacula/src/stored/block.h @@ -41,18 +41,19 @@ #define BLKHDR1_LENGTH 16 /* Total length */ #define BLKHDR2_LENGTH 24 /* Total length */ -#define WRITE_BLKHDR_ID BLKHDR1_ID -#define WRITE_BLKHDR_LENGTH BLKHDR1_LENGTH -#define BLOCK_VER 1 +#define WRITE_BLKHDR_ID BLKHDR2_ID +#define WRITE_BLKHDR_LENGTH BLKHDR2_LENGTH +#define BLOCK_VER 2 /* Record header definitions */ #define RECHDR1_LENGTH 20 #define RECHDR2_LENGTH 12 -#define WRITE_RECHDR_LENGTH RECHDR1_LENGTH +#define WRITE_RECHDR_LENGTH RECHDR2_LENGTH /* Tape label and version definitions */ -#define BaculaId "Bacula 0.9 mortal\n" -#define BaculaTapeVersion 10 +#define BaculaId "Bacula 1.0 immortal\n" +#define OldBaculaId "Bacula 0.9 mortal\n" +#define BaculaTapeVersion 11 #define OldCompatibleBaculaTapeVersion1 10 #define OldCompatibleBaculaTapeVersion2 9 diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index 3cac57d2f7..231fae8315 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -36,7 +36,6 @@ static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sess static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec); static DEVICE *dev; -static int default_tape = FALSE; static int dump_label = FALSE; static int list_blocks = FALSE; static int list_jobs = FALSE; @@ -48,6 +47,10 @@ static SESSION_LABEL sessrec; static uint32_t num_files = 0; static long record_file_index; +#define CONFIG_FILE "bacula-sd.conf" +char *configfile; + + static FF_PKT ff; static BSR *bsr = NULL; @@ -58,6 +61,7 @@ static void usage() "\nVersion: " VERSION " (" DATE ")\n\n" "Usage: bls [-d debug_level] \n" " -b specify a bootstrap file\n" +" -c specify a config file\n" " -d specify debug level\n" " -e exclude list\n" " -i include list\n" @@ -65,7 +69,6 @@ static void usage() " -k list blocks\n" " -L list tape label\n" " (none of above) list saved files\n" -" -t use default tape device\n" " -v be verbose\n" " -? print this message\n\n"); exit(1); @@ -85,13 +88,20 @@ int main (int argc, char *argv[]) memset(&ff, 0, sizeof(ff)); init_include_exclude_files(&ff); - while ((ch = getopt(argc, argv, "b:d:e:i:jkLtv?")) != -1) { + while ((ch = getopt(argc, argv, "b:c:d:e:i:jkLtv?")) != -1) { switch (ch) { case 'b': bsr = parse_bsr(NULL, optarg); // dump_bsr(bsr); break; + case 'c': /* specify config file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; + case 'd': /* debug level */ debug_level = atoi(optarg); if (debug_level <= 0) @@ -138,10 +148,6 @@ int main (int argc, char *argv[]) dump_label = TRUE; break; - case 't': - default_tape = TRUE; - break; - case 'v': verbose++; break; @@ -155,24 +161,25 @@ int main (int argc, char *argv[]) argc -= optind; argv += optind; - if (!argc && !default_tape) { + if (!argc) { Pmsg0(0, "No archive name specified\n"); usage(); } - if (ff.included_files_list == NULL) { - add_fname_to_include_list(&ff, 0, "/"); + if (configfile == NULL) { + configfile = bstrdup(CONFIG_FILE); } - /* Try default device */ - if (default_tape) { - do_ls(DEFAULT_TAPE_DRIVE); - return 0; + parse_config(configfile); + + + if (ff.included_files_list == NULL) { + add_fname_to_include_list(&ff, 0, "/"); } for (i=0; i < argc; i++) { jcr = setup_jcr("bls", argv[i], bsr); - dev = setup_to_read_device(jcr); + dev = setup_to_access_device(jcr, 1); /* acquire for read */ if (!dev) { exit(1); } @@ -217,10 +224,8 @@ static void do_close(JCR *jcr) /* List just block information */ static void do_blocks(char *infname) { - - dump_volume_label(dev); - if (verbose) { + dump_volume_label(dev); rec = new_record(); } for ( ;; ) { @@ -252,15 +257,15 @@ static void do_blocks(char *infname) display_error_status(dev); break; } - Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%d SessTim=%d\n", + Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n", block->BlockNumber, block->block_len, block->BlockVer, block->VolSessionId, block->VolSessionTime); if (verbose == 1) { read_record_from_block(block, rec); - Pmsg6(-1, "Block: %u blen=%u First rec FI=%s SessId=%d Strm=%s rlen=%d\n", + Pmsg7(-1, "Block: %u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n", block->BlockNumber, block->block_len, - FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len); + FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); rec->remainder = 0; } else if (verbose > 1) { dump_block(block, ""); @@ -298,6 +303,7 @@ static void do_ls(char *infname) } read_records(jcr, dev, record_cb, mount_next_read_volume); + printf("%u files found.\n", num_files); } /* @@ -314,7 +320,7 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) return; } /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES) { + if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) { char *ap, *fp; sscanf(rec->data, "%ld %d", &record_file_index, &type); if (record_file_index != rec->FileIndex) { @@ -343,9 +349,6 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) num_files++; } } - if (verbose) { - printf("%u files found.\n", num_files); - } return; } diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 7f674276cd..9ab112e531 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -35,7 +35,7 @@ #include "cats/cats.h" /* Forward referenced functions */ -static void do_scan(char *fname); +static void do_scan(void); static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec); static int create_file_attributes_record(B_DB *db, JCR *mjcr, char *fname, char *lname, int type, @@ -57,7 +57,7 @@ static int update_MD5_record(B_DB *db, char *MD5buf, DEV_RECORD *rec); static DEVICE *dev = NULL; static B_DB *db; static JCR *bjcr; /* jcr for bscan */ -static BSR *bsr; +static BSR *bsr = NULL; static struct stat statp; static int type; static long record_file_index; @@ -85,12 +85,17 @@ static int update_db = 0; static int update_vol_info = 0; static int list_records = 0; +#define CONFIG_FILE "bacula-sd.conf" +char *configfile; + + static void usage() { fprintf(stderr, _( "\nVersion: " VERSION " (" DATE ")\n\n" "Usage: bscan [-d debug_level] \n" " -b bootstrap specify a bootstrap file\n" +" -c specify configuration file\n" " -dnn set debug level to nn\n" " -m update media info in database\n" " -n name specify the database name (default bacula)\n" @@ -112,11 +117,19 @@ int main (int argc, char *argv[]) init_msg(NULL, NULL); - while ((ch = getopt(argc, argv, "b:d:mn:p:rsu:vw:?")) != -1) { + while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vw:?")) != -1) { switch (ch) { case 'b': bsr = parse_bsr(NULL, optarg); break; + + case 'c': /* specify config file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; + case 'd': /* debug level */ debug_level = atoi(optarg); if (debug_level <= 0) @@ -171,7 +184,17 @@ int main (int argc, char *argv[]) working_directory = wd; + if (configfile == NULL) { + configfile = bstrdup(CONFIG_FILE); + } + + parse_config(configfile); + bjcr = setup_jcr("bscan", argv[0], bsr); + dev = setup_to_access_device(bjcr, 0); /* read device */ + if (!dev) { + exit(1); + } if ((db=db_init_database(NULL, db_name, db_user, db_password)) == NULL) { Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n")); @@ -184,21 +207,15 @@ int main (int argc, char *argv[]) Pmsg2(000, _("Using Database: %s, User: %s\n"), db_name, db_user); } - do_scan(argv[0]); + do_scan(); free_jcr(bjcr); return 0; } -static void do_scan(char *devname) +static void do_scan() { - - dev = setup_to_read_device(bjcr); - if (!dev) { - exit(1); - } - fname = get_pool_memory(PM_FNAME); ofile = get_pool_memory(PM_FNAME); lname = get_pool_memory(PM_FNAME); @@ -336,10 +353,15 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) mjcr = create_job_record(db, &jr, &label, rec); update_db = save_update_db; - jr.PoolId = pr.PoolId; - /* Set start positions into JCR */ - mjcr->StartBlock = dev->block_num; - mjcr->StartFile = dev->file; + jr.PoolId = pr.PoolId; + /* Set start positions into JCR */ + if (dev->state & ST_TAPE) { + mjcr->StartBlock = dev->block_num; + mjcr->StartFile = dev->file; + } else { + mjcr->StartBlock = (uint32_t)dev->file_addr; + mjcr->StartFile = (uint32_t)(dev->file_addr >> 32); + } mjcr->start_time = jr.StartTime; mjcr->JobLevel = jr.Level; @@ -438,7 +460,7 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) /* File Attributes stream */ - if (rec->Stream == STREAM_UNIX_ATTRIBUTES) { + if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_WIN32_ATTRIBUTES) { char *ap, *lp, *fp; if (sizeof_pool_memory(fname) < rec->data_len) { @@ -504,7 +526,7 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } free_jcr(mjcr); - /* Data stream and extracting */ + /* Data stream */ } else if (rec->Stream == STREAM_FILE_DATA) { mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { @@ -515,6 +537,16 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) mjcr->JobBytes += rec->data_len; free_jcr(mjcr); /* done using JCR */ + } else if (rec->Stream == STREAM_SPARSE_DATA) { + mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); + if (!mjcr) { + Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"), + rec->VolSessionId, rec->VolSessionTime); + return; + } + mjcr->JobBytes += rec->data_len - sizeof(uint64_t); + free_jcr(mjcr); /* done using JCR */ + } else if (rec->Stream == STREAM_GZIP_DATA) { mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); if (!mjcr) { @@ -522,9 +554,20 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) rec->VolSessionId, rec->VolSessionTime); return; } - mjcr->JobBytes += rec->data_len; + mjcr->JobBytes += rec->data_len; /* No correct, we should expand it */ free_jcr(mjcr); /* done using JCR */ + } else if (rec->Stream == STREAM_SPARSE_GZIP_DATA) { + mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime); + if (!mjcr) { + Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"), + rec->VolSessionId, rec->VolSessionTime); + return; + } + mjcr->JobBytes += rec->data_len - sizeof(uint64_t); /* No correct, we should expand it */ + free_jcr(mjcr); /* done using JCR */ + + } else if (rec->Stream == STREAM_MD5_SIGNATURE) { char MD5buf[30]; bin_to_base64(MD5buf, (char *)rec->data, 16); /* encode 16 bytes */ @@ -532,6 +575,15 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) Pmsg1(000, _("Got MD5 record: %s\n"), MD5buf); } update_MD5_record(db, MD5buf, rec); + + } else if (rec->Stream == STREAM_PROGRAM_NAMES) { + if (verbose) { + Pmsg1(000, _("Got Prog Names Stream: %s\n"), rec->data); + } + } else if (rec->Stream == STREAM_PROGRAM_DATA) { + if (verbose > 1) { + Pmsg0(000, _("Got Prog Data Stream record.\n")); + } } else { Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data); } @@ -608,11 +660,12 @@ static int create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl) struct tm tm; strcpy(mr->VolStatus, "Full"); - mr->VolRetention = 355 * 3600 * 24; /* 1 year */ + mr->VolRetention = 365 * 3600 * 24; /* 1 year */ if (vl->VerNum >= 11) { - mr->FirstWritten = (time_t)vl->write_btime; - mr->LabelDate = (time_t)vl->label_btime; + mr->FirstWritten = btime_to_etime(vl->write_btime); + mr->LabelDate = btime_to_etime(vl->label_btime); } else { + /* DEPRECATED DO NOT USE */ dt.julian_day_number = vl->write_date; dt.julian_day_fraction = vl->write_time; tm_decode(&dt, &tm); @@ -748,7 +801,7 @@ static JCR *create_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *label, strcpy(jr->Name, label->JobName); strcpy(jr->Job, label->Job); if (label->VerNum >= 11) { - jr->SchedTime = (time_t)label->write_btime; + jr->SchedTime = btime_to_etime(label->write_btime); } else { dt.julian_day_number = label->write_date; dt.julian_day_fraction = label->write_time; @@ -805,7 +858,7 @@ static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel, return 0; } if (elabel->VerNum >= 11) { - jr->EndTime = (time_t)elabel->write_btime; + jr->EndTime = btime_to_etime(elabel->write_btime); } else { dt.julian_day_number = elabel->write_date; dt.julian_day_fraction = elabel->write_time; @@ -899,8 +952,13 @@ static int create_jobmedia_record(B_DB *db, JCR *mjcr) { JOBMEDIA_DBR jmr; - mjcr->EndBlock = dev->block_num; - mjcr->EndFile = dev->file; + if (dev->state & ST_TAPE) { + mjcr->EndBlock = dev->block_num; + mjcr->EndFile = dev->file; + } else { + mjcr->EndBlock = (uint32_t)dev->file_addr; + mjcr->EndFile = (uint32_t)(dev->file_addr >> 32); + } memset(&jmr, 0, sizeof(jmr)); jmr.JobId = mjcr->JobId; @@ -1007,8 +1065,13 @@ int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev) if (verbose) { Pmsg1(000, "create JobMedia for Job %s\n", mjcr->Job); } - mjcr->EndBlock = dev->block_num; - mjcr->EndFile = dev->file; + if (dev->state & ST_TAPE) { + mjcr->EndBlock = dev->block_num; + mjcr->EndFile = dev->file; + } else { + mjcr->EndBlock = (uint32_t)dev->file_addr; + mjcr->StartBlock = (uint32_t)(dev->file_addr >> 32); + } if (!create_jobmedia_record(db, mjcr)) { Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"), dev->VolCatInfo.VolCatName, mjcr->Job); diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 8c0df2384d..c079ae7ae0 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -58,19 +58,20 @@ static void rewindcmd(); static void clearcmd(); static void wrcmd(); static void eodcmd(); -static int find_device_res(); static void fillcmd(); static void unfillcmd(); -static int flush_block(DEV_BLOCK *block); +static int flush_block(DEV_BLOCK *block, int dump); static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec); static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -#define CONFIG_FILE "stored.conf" -static char *configfile; +/* Static variables */ +#define CONFIG_FILE "bacula-sd.conf" +char *configfile; + +static BSR *bsr = NULL; static char cmd[1000]; static int signals = TRUE; -static int default_tape = FALSE; static int ok; static int stop; static uint64_t vol_size; @@ -81,6 +82,10 @@ static long file_index; static int verbose = 0; static int end_of_tape = 0; static uint32_t LastBlock = 0; +static uint32_t eot_block; +static uint32_t eot_block_len; +static uint32_t eot_FileIndex; +static int dumped = 0; static char *VolumeName = NULL; @@ -91,31 +96,6 @@ static void usage(); static void terminate_btape(int sig); int get_cmd(char *prompt); -static void my_free_jcr(JCR *jcr) -{ - if (jcr->pool_name) { - free_pool_memory(jcr->pool_name); - jcr->pool_name = NULL; - } - if (jcr->pool_type) { - free_pool_memory(jcr->pool_type); - jcr->pool_type = NULL; - } - if (jcr->job_name) { - free_pool_memory(jcr->job_name); - jcr->job_name = NULL; - } - if (jcr->client_name) { - free_pool_memory(jcr->client_name); - jcr->client_name = NULL; - } - if (jcr->fileset_name) { - free_pool_memory(jcr->fileset_name); - jcr->fileset_name = NULL; - } - - return; -} int write_dev(DEVICE *dev, char *buf, size_t len) { @@ -154,8 +134,13 @@ int main(int argc, char *argv[]) my_name_is(argc, argv, "btape"); init_msg(NULL, NULL); - while ((ch = getopt(argc, argv, "c:d:stv?")) != -1) { + while ((ch = getopt(argc, argv, "b:c:d:sv?")) != -1) { switch (ch) { + case 'b': /* bootstrap file */ + bsr = parse_bsr(NULL, optarg); +// dump_bsr(bsr); + break; + case 'c': /* specify config file */ if (configfile != NULL) { free(configfile); @@ -174,10 +159,6 @@ int main(int argc, char *argv[]) signals = FALSE; break; - case 't': - default_tape = TRUE; - break; - case 'v': verbose++; break; @@ -208,51 +189,22 @@ int main(int argc, char *argv[]) /* See if we can open a device */ - if (argc) { - if (!(dev = init_dev(NULL, *argv))) { - usage(); - exit(1); - } - } - - /* Try default device */ - if (!dev && default_tape) { - dev = init_dev(NULL, DEFAULT_TAPE_DRIVE); - } - - if (dev) { - if (!find_device_res()) { - exit(1); - } - if (!open_device(dev)) { - Pmsg1(0, "Warning could not open device. ERR=%s", strerror_dev(dev)); - term_dev(dev); - dev = NULL; - } + if (argc == 0) { + Pmsg0(000, "No archive name specified.\n"); + usage(); + exit(1); + } else if (argc != 1) { + Pmsg0(000, "Improper number of arguments specified.\n"); + usage(); + exit(1); + } + + jcr = setup_jcr("btape", argv[0], bsr); + dev = setup_to_access_device(jcr, 0); /* acquire for write */ + if (!dev) { + exit(1); } - /* Setup a "dummy" JCR that should work for most everything */ - jcr = new_jcr(sizeof(JCR), my_free_jcr); - jcr->VolSessionId = 1; - jcr->VolSessionTime = (uint32_t)time(NULL); - jcr->NumVolumes = 1; - jcr->pool_name = get_pool_memory(PM_FNAME); - strcpy(jcr->pool_name, "Default"); - jcr->pool_type = get_pool_memory(PM_FNAME); - strcpy(jcr->pool_type, "Backup"); - jcr->job_name = get_pool_memory(PM_FNAME); - strcpy(jcr->job_name, "Dummy.Job.Name"); - jcr->client_name = get_pool_memory(PM_FNAME); - strcpy(jcr->client_name, "Dummy.Client.Name"); - strcpy(jcr->Job, "Dummy.Job"); - jcr->fileset_name = get_pool_memory(PM_FNAME); - strcpy(jcr->fileset_name, "Dummy.fileset.name"); - jcr->JobId = 1; - jcr->JobType = JT_BACKUP; - jcr->JobLevel = L_FULL; - jcr->JobStatus = JS_Terminated; - - Dmsg0(200, "Do tape commands\n"); do_tape_cmds(); @@ -279,6 +231,10 @@ static void terminate_btape(int stat) free_jcr(jcr); jcr = NULL; + if (bsr) { + free_bsr(bsr); + } + term_msg(); close_memory_pool(); /* free memory in pool */ @@ -291,32 +247,6 @@ void quitcmd() quit = 1; } -/* - * Get a new device name - * Normally given on the command line - */ -static void devicecmd() -{ - if (dev) { - term_dev(dev); - dev = NULL; - } - if (!get_cmd("Enter Device Name: ")) { - return; - } - dev = init_dev(NULL, cmd); - if (dev) { - if (!find_device_res()) { - return; - } - if (!open_device(dev)) { - Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev)); - } - } else { - Pmsg0(0, "Device init failed.\n"); - } -} - /* * Write a label to the tape */ @@ -325,11 +255,6 @@ static void labelcmd() DEVRES *device; int found = 0; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } - LockRes(); for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { if (strcmp(device->device_name, dev->dev_name) == 0) { @@ -371,10 +296,6 @@ static void readlabelcmd() int stat; DEV_BLOCK *block; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } block = new_block(dev); stat = read_dev_volume_label(jcr, dev, block); switch (stat) { @@ -411,35 +332,6 @@ static void readlabelcmd() } -/* - * Search for device resource that corresponds to - * device name on command line (or default). - * - * Returns: 0 on failure - * 1 on success - */ -static int find_device_res() -{ - int found = 0; - - LockRes(); - for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { - if (strcmp(device->device_name, dev->dev_name) == 0) { - device->dev = dev; - dev->capabilities = device->cap_bits; - found = 1; - break; - } - } - UnlockRes(); - if (!found) { - Pmsg2(0, "Could not find device %s in %s\n", dev->dev_name, configfile); - return 0; - } - Pmsg1(0, "Using device: %s\n", dev->dev_name); - return 1; -} - /* * Load the tape should have prevously been taken * off line, otherwise this command is not necessary. @@ -447,10 +339,6 @@ static int find_device_res() static void loadcmd() { - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } if (!load_dev(dev)) { Pmsg1(0, "Bad status from load. ERR=%s\n", strerror_dev(dev)); } else @@ -462,15 +350,12 @@ static void loadcmd() */ static void rewindcmd() { - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } if (!rewind_dev(dev)) { Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); clrerror_dev(dev, -1); - } else + } else { Pmsg1(0, "Rewound %s\n", dev_name(dev)); + } } /* @@ -478,10 +363,6 @@ static void rewindcmd() */ static void clearcmd() { - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } clrerror_dev(dev, -1); } @@ -492,10 +373,6 @@ static void weofcmd() { int stat; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } if ((stat = weof_dev(dev, 1)) < 0) { Pmsg2(0, "Bad status from weof %d. ERR=%s\n", stat, strerror_dev(dev)); return; @@ -513,10 +390,6 @@ static void weofcmd() */ static void eomcmd() { - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } if (!eod_dev(dev)) { Pmsg1(0, "Bad status from eod. ERR=%s\n", strerror_dev(dev)); return; @@ -540,10 +413,7 @@ static void eodcmd() static void bsfcmd() { int stat; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } + if ((stat=bsf_dev(dev, 1)) < 0) { Pmsg1(0, "Bad status from bsf. ERR=%s\n", strerror(errno)); } else { @@ -557,10 +427,7 @@ static void bsfcmd() static void bsrcmd() { int stat; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } + if ((stat=bsr_dev(dev, 1)) < 0) { Pmsg1(0, "Bad status from bsr. ERR=%s\n", strerror(errno)); } else { @@ -574,10 +441,6 @@ static void bsrcmd() */ static void capcmd() { - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } Pmsg0(0, "Device capabilities: "); printf("%sEOF ", dev->capabilities & CAP_EOF ? "" : "!"); printf("%sBSR ", dev->capabilities & CAP_BSR ? "" : "!"); @@ -604,11 +467,6 @@ static void rectestcmd() DEV_RECORD *rec; int i, blkno = 0; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } - Pmsg0(0, "Test writting larger and larger records.\n\ This is a torture test for records.\nI am going to write\n\ larger and larger records. It will stop when the record size\n\ @@ -650,10 +508,6 @@ plus the header exceeds the block size (by default about 64K\n"); */ static void testcmd() { - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } Pmsg0(0, "Append files test.\n\n\ I'm going to write one record in file 0,\n\ two records in file 1,\n\ @@ -714,10 +568,7 @@ block in the first file.\n\n"); static void fsfcmd() { int stat; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } + if ((stat=fsf_dev(dev, 1)) < 0) { Pmsg2(0, "Bad status from fsf %d. ERR=%s\n", stat, strerror_dev(dev)); return; @@ -728,10 +579,7 @@ static void fsfcmd() static void fsrcmd() { int stat; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } + if ((stat=fsr_dev(dev, 1)) < 0) { Pmsg2(0, "Bad status from fsr %d. ERR=%s\n", stat, strerror_dev(dev)); return; @@ -744,10 +592,6 @@ static void rdcmd() #ifdef xxxxx int stat; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } if (!read_dev(dev, buf, 512*126)) { Pmsg1(0, "Bad status from read. ERR=%s\n", strerror_dev(dev)); return; @@ -765,36 +609,35 @@ static void wrcmd() DEV_RECORD *rec; int i; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } sm_check(__FILE__, __LINE__, False); block = new_block(dev); rec = new_record(); + dump_block(block, "test"); - i = 32001; - rec->data = (char *) check_pool_memory_size(rec->data, i); + i = block->buf_len - 100; + ASSERT (i > 0); + rec->data = check_pool_memory_size(rec->data, i); memset(rec->data, i & 0xFF, i); rec->data_len = i; sm_check(__FILE__, __LINE__, False); if (!write_record_to_block(block, rec)) { Pmsg0(0, "Error writing record to block.\n"); - return; + goto bail_out; } if (!write_block_to_dev(dev, block)) { Pmsg0(0, "Error writing block to device.\n"); - return; + goto bail_out; } else { Pmsg1(0, "Wrote one record of %d bytes.\n", ((i+TAPE_BSIZE-1)/TAPE_BSIZE) * TAPE_BSIZE); } + Pmsg0(0, "Wrote block to device.\n"); +bail_out: sm_check(__FILE__, __LINE__, False); free_record(rec); free_block(block); sm_check(__FILE__, __LINE__, False); - Pmsg0(0, "Wrote block to device.\n"); } @@ -809,10 +652,6 @@ static void scancmd() int block_size; uint64_t bytes; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } blocks = block_size = tot_blocks = 0; bytes = 0; @@ -876,10 +715,6 @@ static void statcmd() int debug; uint32_t status; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } debug = debug_level; debug_level = 30; if (!status_dev(dev, &status)) { @@ -903,11 +738,6 @@ static void fillcmd() char ec1[50]; char *p; - if (!dev) { - Pmsg0(0, "No device: Use device command.\n"); - return; - } - ok = TRUE; stop = FALSE; @@ -920,7 +750,7 @@ fills, it will ask for a second, and after writing a few \n\ blocks, it will stop. Then it will begin re-reading the\n\ This may take a long time. I.e. hours! ...\n\n"); - get_cmd("Do you wish to continue? (y/n): "); + get_cmd("Insert a blank tape then answer. Do you wish to continue? (y/n): "); if (cmd[0] != 'y') { Pmsg0(000, "Command aborted.\n"); return; @@ -988,13 +818,15 @@ This may take a long time. I.e. hours! ...\n\n"); *lp = (uint64_t)file_index; Dmsg4(250, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n", - rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream), + rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len); if (!write_record_to_block(block, &rec)) { Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len, rec.remainder); - if (!flush_block(block)) { + + /* Write block to tape */ + if (!flush_block(block, 1)) { return; } @@ -1014,7 +846,7 @@ This may take a long time. I.e. hours! ...\n\n"); */ if ((block->BlockNumber % 50000) == 0) { Pmsg0(000, "Flush block, write EOF\n"); - flush_block(block); + flush_block(block, 0); weof_dev(dev, 1); /* The weof resets the block number */ } @@ -1030,7 +862,7 @@ This may take a long time. I.e. hours! ...\n\n"); jcr->JobBytes += rec.data_len; /* increment bytes this job */ Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n", FI_to_ascii(rec.FileIndex), rec.VolSessionId, - stream_to_ascii(rec.Stream), rec.data_len); + stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len); } Dmsg0(000, "Write_end_session_label()\n"); /* Create Job status for end of session label */ @@ -1056,6 +888,7 @@ This may take a long time. I.e. hours! ...\n\n"); } free_block(block); + free_memory(rec.data); Pmsg0(000, "Done with fill command. Now beginning re-read of tapes...\n"); unfillcmd(); @@ -1069,6 +902,7 @@ static void unfillcmd() { DEV_BLOCK *block; + dumped = 0; VolBytes = 0; LastBlock = 0; block = new_block(dev); @@ -1088,6 +922,8 @@ static void unfillcmd() } time(&jcr->run_time); /* start counting time for rates */ + stop = 0; + file_index = 0; read_records(jcr, dev, record_cb, my_mount_next_read_volume); free_block(block); @@ -1095,9 +931,27 @@ static void unfillcmd() } +/* + * We are called here from "unfill" for each record on the + * tape. + */ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) { + SESSION_LABEL label; + if (stop > 1) { /* on second tape */ + Pmsg4(000, "Blk: FileIndex=%d: block=%u size=%d vol=%s\n", + rec->FileIndex, block->BlockNumber, block->block_len, dev->VolHdr.VolName); + Pmsg6(000, " Rec: VId=%d VT=%d FI=%s Strm=%s len=%d state=%x\n", + rec->VolSessionId, rec->VolSessionTime, + FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream, rec->FileIndex), + rec->data_len, rec->state); + + if (!dumped) { + dumped = 1; + dump_block(block, "Block not written to previous tape"); + } + } if (rec->FileIndex < 0) { if (verbose > 1) { dump_label_record(dev, rec, 1); @@ -1108,8 +962,9 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) return; case VOL_LABEL: unser_volume_label(dev, rec); - Pmsg2(000, "VOL_LABEL: block=%u vol=%s\n", block->BlockNumber, - dev->VolHdr.VolName); + Pmsg3(000, "VOL_LABEL: block=%u size=%d vol=%s\n", block->BlockNumber, + block->block_len, dev->VolHdr.VolName); + stop++; break; case SOS_LABEL: unser_session_label(&label, rec); @@ -1174,13 +1029,22 @@ static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) * not it is full. If the tape fills, attempt to * acquire another tape. */ -static int flush_block(DEV_BLOCK *block) +static int flush_block(DEV_BLOCK *block, int dump) { char ec1[50]; lock_device(dev); if (!write_block_to_dev(dev, block)) { - Pmsg2(000, "Doing fixup device error. FileIndex=%u Block=%u\n", - (unsigned)file_index, block->BlockNumber); + Pmsg0(000, strerror_dev(dev)); + Pmsg3(000, "Block not written: FileIndex=%u Block=%u Size=%u\n", + (unsigned)file_index, block->BlockNumber, block->block_len); + if (dump) { + dump_block(block, "Block not written"); + } + if (!stop) { + eot_block = block->BlockNumber; + eot_block_len = block->block_len; + eot_FileIndex = file_index; + } now = time(NULL); now -= jcr->run_time; if (now <= 0) { @@ -1196,7 +1060,6 @@ static int flush_block(DEV_BLOCK *block) unlock_device(dev); return 0; } - Pmsg1(000, "Changed tapes. Block=%u\n", block->BlockNumber); stop = 1; unlock_device(dev); return 1; /* write one more block to next tape then stop */ @@ -1212,7 +1075,6 @@ static struct cmdstruct commands[] = { {"bsr", bsrcmd, "backspace record"}, {"cap", capcmd, "list device capabilities"}, {"clear", clearcmd, "clear tape errors"}, - {"device", devicecmd, "specify the tape device name"}, {"eod", eodcmd, "go to end of Bacula data for append"}, {"test", testcmd, "General test Bacula tape functions"}, {"eom", eomcmd, "go to the physical end of medium"}, @@ -1325,6 +1187,7 @@ int dir_send_job_status(JCR *jcr) {return 1;} int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev) { + Pmsg0(000, dev->errmsg); /* print reason */ fprintf(stderr, "Mount Volume \"%s\" on device %s and press return when ready: ", jcr->VolumeName, dev_name(dev)); getchar(); diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 323e714ec8..68b2b9365f 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -32,6 +32,8 @@ #include "bacula.h" #include "stored.h" +/* Imported variables -- eliminate some day */ +extern char *configfile; #ifdef DEBUG char *rec_state_to_str(DEV_RECORD *rec) @@ -62,13 +64,16 @@ char *rec_state_to_str(DEV_RECORD *rec) /* - * Setup device, jcr, and prepare to read + * Setup device, jcr, and prepare to access device. + * If the caller wants read access, acquire the device, otherwise, + * the caller will do it. */ -DEVICE *setup_to_read_device(JCR *jcr) +DEVICE *setup_to_access_device(JCR *jcr, int read_access) { DEVICE *dev; DEV_BLOCK *block; char *p; + DEVRES *device; jcr->VolumeName[0] = 0; if (strncmp(jcr->dev_name, "/dev/", 5) != 0) { @@ -82,12 +87,17 @@ DEVICE *setup_to_read_device(JCR *jcr) } } - dev = init_dev(NULL, jcr->dev_name); + if ((device=find_device_res(jcr->dev_name)) == NULL) { + Emsg2(M_FATAL, 0, "Cannot find device %s in config file %s.\n", + jcr->dev_name, configfile); + return NULL; + } + + dev = init_dev(NULL, device); if (!dev) { Emsg1(M_FATAL, 0, "Cannot open %s\n", jcr->dev_name); return NULL; } - /* ***FIXME**** init capabilities */ if (!open_device(dev)) { Emsg1(M_FATAL, 0, "Cannot open %s\n", jcr->dev_name); return NULL; @@ -99,17 +109,79 @@ DEVICE *setup_to_read_device(JCR *jcr) create_vol_list(jcr); Dmsg1(100, "Volume=%s\n", jcr->VolumeName); - if (!acquire_device_for_read(jcr, dev, block)) { - Emsg0(M_ERROR, 0, dev->errmsg); - return NULL; + if (read_access) { + if (!acquire_device_for_read(jcr, dev, block)) { + Emsg0(M_ERROR, 0, dev->errmsg); + return NULL; + } } free_block(block); return dev; } +/* + * Search for device resource that corresponds to + * device name on command line (or default). + * + * Returns: NULL on failure + * Device resource pointer on success + */ +DEVRES *find_device_res(char *device_name) +{ + int found = 0; + DEVRES *device; + + LockRes(); + for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { + if (strcmp(device->device_name, device_name) == 0) { + found = 1; + break; + } + } + UnlockRes(); + if (!found) { + Pmsg2(0, "Could not find device %s in config file %s.\n", device_name, + configfile); + return NULL; + } + Pmsg1(0, "Using device: %s\n", device_name); + return device; +} + + + +/* + * Called here when freeing JCR so that we can get rid + * of "daemon" specific memory allocated. + */ static void my_free_jcr(JCR *jcr) { + if (jcr->pool_name) { + free_pool_memory(jcr->pool_name); + jcr->pool_name = NULL; + } + if (jcr->pool_type) { + free_pool_memory(jcr->pool_type); + jcr->pool_type = NULL; + } + if (jcr->job_name) { + free_pool_memory(jcr->job_name); + jcr->job_name = NULL; + } + if (jcr->client_name) { + free_pool_memory(jcr->client_name); + jcr->client_name = NULL; + } + if (jcr->fileset_name) { + free_pool_memory(jcr->fileset_name); + jcr->fileset_name = NULL; + } + if (jcr->dev_name) { + free_pool_memory(jcr->dev_name); + jcr->dev_name = NULL; + } + return; } @@ -123,9 +195,24 @@ JCR *setup_jcr(char *name, char *device, BSR *bsr) jcr->VolSessionId = 1; jcr->VolSessionTime = (uint32_t)time(NULL); jcr->bsr = bsr; + jcr->NumVolumes = 1; + jcr->pool_name = get_pool_memory(PM_FNAME); + strcpy(jcr->pool_name, "Default"); + jcr->pool_type = get_pool_memory(PM_FNAME); + strcpy(jcr->pool_type, "Backup"); + jcr->job_name = get_pool_memory(PM_FNAME); + strcpy(jcr->job_name, "Dummy.Job.Name"); + jcr->client_name = get_pool_memory(PM_FNAME); + strcpy(jcr->client_name, "Dummy.Client.Name"); strcpy(jcr->Job, name); + jcr->fileset_name = get_pool_memory(PM_FNAME); + strcpy(jcr->fileset_name, "Dummy.fileset.name"); + jcr->JobId = 1; + jcr->JobType = JT_BACKUP; + jcr->JobLevel = L_FULL; + jcr->JobStatus = JS_Terminated; jcr->dev_name = get_pool_memory(PM_FNAME); - strcpy(jcr->dev_name, device); + pm_strcpy(&jcr->dev_name, device); return jcr; } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 1ed4cf398b..6a9ab69d1e 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -95,24 +95,25 @@ extern int debug_level; * thus we neither allocate it nor free it. This allows * the caller to put the packet in shared memory. * - * Note, for a tape, the dev_name is the device name + * Note, for a tape, the device->device_name is the device name * (e.g. /dev/nst0), and for a file, the device name * is the directory in which the file will be placed. * */ DEVICE * -init_dev(DEVICE *dev, char *dev_name) +init_dev(DEVICE *dev, DEVRES *device) { struct stat statp; int tape; int errstat; /* Check that device is available */ - if (stat(dev_name, &statp) < 0) { + if (stat(device->device_name, &statp) < 0) { if (dev) { dev->dev_errno = errno; } - Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", dev_name, strerror(errno)); + Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name, + strerror(errno)); return NULL; } tape = FALSE; @@ -138,19 +139,26 @@ init_dev(DEVICE *dev, char *dev_name) if (tape) { dev->state |= ST_TAPE; } - dev->dev_name = get_memory(strlen(dev_name)+1); - strcpy(dev->dev_name, dev_name); + + /* Copy user supplied device parameters from Resource */ + dev->dev_name = get_memory(strlen(device->device_name)+1); + strcpy(dev->dev_name, device->device_name); + dev->capabilities = device->cap_bits; + dev->min_block_size = device->min_block_size; + dev->max_block_size = device->max_block_size; + dev->max_volume_jobs = device->max_volume_jobs; + dev->max_volume_files = device->max_volume_files; + dev->max_volume_size = device->max_volume_size; + dev->max_file_size = device->max_file_size; + dev->volume_capacity = device->volume_capacity; + dev->max_rewind_wait = device->max_rewind_wait; + dev->max_open_wait = device->max_open_wait; + dev->device = device; + dev->errmsg = get_pool_memory(PM_EMSG); *dev->errmsg = 0; -#ifdef NEW_LOCK - if ((errstat=rwl_init(&dev->lock)) != 0) { - Mmsg1(&dev->errmsg, _("Unable to initialize dev lock. ERR=%s\n"), strerror(errstat)); - Emsg0(M_FATAL, 0, dev->errmsg); - } -#endif - if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) { dev->dev_errno = errstat; Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat)); @@ -289,7 +297,7 @@ int rewind_dev(DEVICE *dev) } dev->state &= ~(ST_APPEND|ST_READ|ST_EOT | ST_EOF | ST_WEOT); /* remove EOF/EOT flags */ dev->block_num = dev->file = 0; - dev->file_bytes = 0; + dev->file_addr = 0; if (dev->state & ST_TAPE) { mt_com.mt_op = MTREW; mt_com.mt_count = 1; @@ -344,7 +352,7 @@ eod_dev(DEVICE *dev) } dev->state &= ~(ST_EOF); /* remove EOF flags */ dev->block_num = dev->file = 0; - dev->file_bytes = 0; + dev->file_addr = 0; if (!(dev->state & ST_TAPE)) { pos = lseek(dev->fd, (off_t)0, SEEK_END); // Dmsg1(000, "====== Seek to %lld\n", pos); @@ -418,7 +426,7 @@ int update_pos_dev(DEVICE *dev) /* Find out where we are */ if (!(dev->state & ST_TAPE)) { dev->file = 0; - dev->file_bytes = 0; + dev->file_addr = 0; pos = lseek(dev->fd, (off_t)0, SEEK_CUR); if (pos < 0) { Dmsg1(000, "Seek error: ERR=%s\n", strerror(dev->dev_errno)); @@ -427,7 +435,7 @@ int update_pos_dev(DEVICE *dev) dev->dev_name, strerror(dev->dev_errno)); } else { stat = 1; - dev->file_bytes = pos; + dev->file_addr = pos; } return stat; } @@ -559,7 +567,7 @@ int load_dev(DEVICE *dev) #else dev->block_num = dev->file = 0; - dev->file_bytes = 0; + dev->file_addr = 0; mt_com.mt_op = MTLOAD; mt_com.mt_count = 1; if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) { @@ -591,7 +599,7 @@ int offline_dev(DEVICE *dev) } dev->block_num = dev->file = 0; - dev->file_bytes = 0; + dev->file_addr = 0; #ifdef MTUNLOCK mt_com.mt_op = MTUNLOCK; mt_com.mt_count = 1; @@ -672,7 +680,7 @@ fsf_dev(DEVICE *dev, int num) } else { dev->state |= ST_EOF; dev->file++; - dev->file_bytes = 0; + dev->file_addr = 0; continue; } } else { /* Got data */ @@ -692,7 +700,7 @@ fsf_dev(DEVICE *dev, int num) } else { dev->state |= ST_EOF; /* just read EOF */ dev->file++; - dev->file_bytes = 0; + dev->file_addr = 0; } } @@ -744,7 +752,7 @@ bsf_dev(DEVICE *dev, int num) Dmsg0(29, "bsf_dev\n"); dev->state &= ~(ST_EOT|ST_EOF); dev->file -= num; - dev->file_bytes = 0; + dev->file_addr = 0; mt_com.mt_op = MTBSF; mt_com.mt_count = num; stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); @@ -790,7 +798,7 @@ fsr_dev(DEVICE *dev, int num) } else { dev->state |= ST_EOF; /* assume EOF */ dev->file++; - dev->file_bytes = 0; + dev->file_addr = 0; } clrerror_dev(dev, MTFSR); Mmsg2(&dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"), @@ -863,7 +871,7 @@ weof_dev(DEVICE *dev, int num) stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com); if (stat == 0) { dev->file++; - dev->file_bytes = 0; + dev->file_addr = 0; } else { clrerror_dev(dev, MTWEOF); Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), @@ -972,7 +980,7 @@ static void do_close(DEVICE *dev) dev->state &= ~(ST_OPENED|ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF); dev->block_num = 0; dev->file = 0; - dev->file_bytes = 0; + dev->file_addr = 0; dev->LastBlockNumWritten = 0; memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo)); memset(&dev->VolHdr, 0, sizeof(dev->VolHdr)); diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 83e794c1b2..252b932ca4 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -147,7 +147,7 @@ typedef struct s_device { char *errmsg; /* nicely edited error message */ uint32_t block_num; /* current block number base 0 */ uint32_t file; /* current file number base 0 */ - uint64_t file_bytes; /* bytes in this file */ + uint64_t file_addr; /* Current file read/write address */ uint32_t LastBlockNumWritten; /* last block written */ uint32_t min_block_size; /* min block size */ uint32_t max_block_size; /* max block size */ diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index e4cfe076b7..794c321786 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -92,8 +92,13 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { Dmsg1(100, "create JobMedia for Job %s\n", mjcr->Job); - mjcr->EndBlock = dev->block_num; - mjcr->EndFile = dev->file; + if (dev->state & ST_TAPE) { + mjcr->EndBlock = dev->block_num; + mjcr->EndFile = dev->file; + } else { + mjcr->EndBlock = (uint32_t)dev->file_addr; + mjcr->EndFile = (uint32_t)(dev->file_addr >> 32); + } if (!dir_create_jobmedia_record(mjcr)) { Jmsg(mjcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=%s Job=%s\n"), dev->VolCatInfo.VolCatName, mjcr->Job); @@ -165,8 +170,13 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) free_block(label_blk); for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) { /* Set new start/end positions */ - mjcr->StartBlock = dev->block_num; - mjcr->StartFile = dev->file; + if (dev->state & ST_TAPE) { + mjcr->StartBlock = dev->block_num; + mjcr->StartFile = dev->file; + } else { + mjcr->StartBlock = (uint32_t)dev->file_addr; + mjcr->StartFile = (uint32_t)(dev->file_addr >> 32); + } mjcr->VolFirstFile = mjcr->JobFiles; mjcr->run_time += time(NULL) - wait_time; /* correct run time */ } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 8e9e01cb64..210f30b8b9 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -69,6 +69,7 @@ static int unmount_cmd(JCR *jcr); static int status_cmd(JCR *sjcr); static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname, int Slot); +static void send_blocked_status(JCR *jcr, DEVICE *dev); struct s_cmds { char *cmd; @@ -654,29 +655,7 @@ static int status_cmd(JCR *jcr) } else { bnet_fsend(user, _("Device %s open but no Bacula volume is mounted.\n"), dev_name(dev)); } - switch (dev->dev_blocked) { - case BST_UNMOUNTED: - bnet_fsend(user, _(" Deviced is blocked. User unmounted.\n")); - break; - case BST_UNMOUNTED_WAITING_FOR_SYSOP: - bnet_fsend(user, _(" Deviced is blocked. User unmounted during wait for media/mount.\n")); - break; - case BST_WAITING_FOR_SYSOP: - if (jcr->JobStatus == JS_WaitMount) { - bnet_fsend(user, _(" Device is blocked waiting for mount.\n")); - } else { - bnet_fsend(user, _(" Device is blocked waiting for appendable media.\n")); - } - break; - case BST_DOING_ACQUIRE: - bnet_fsend(user, _(" Device is being initialized.\n")); - break; - case BST_WRITING_LABEL: - bnet_fsend(user, _(" Device is blocked labeling a Volume.\n")); - break; - default: - break; - } + send_blocked_status(jcr, dev); bpb = dev->VolCatInfo.VolCatBlocks; if (bpb <= 0) { bpb = 1; @@ -692,6 +671,7 @@ static int status_cmd(JCR *jcr) } else { bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev)); + send_blocked_status(jcr, dev); } } } @@ -745,3 +725,32 @@ static int status_cmd(JCR *jcr) bnet_sig(user, BNET_EOD); return 1; } + +static void send_blocked_status(JCR *jcr, DEVICE *dev) +{ + BSOCK *user = jcr->dir_bsock; + + switch (dev->dev_blocked) { + case BST_UNMOUNTED: + bnet_fsend(user, _(" Device is BLOCKED. User unmounted.\n")); + break; + case BST_UNMOUNTED_WAITING_FOR_SYSOP: + bnet_fsend(user, _(" Device is BLOCKED. User unmounted during wait for media/mount.\n")); + break; + case BST_WAITING_FOR_SYSOP: + if (jcr->JobStatus == JS_WaitMount) { + bnet_fsend(user, _(" Device is BLOCKED waiting for mount.\n")); + } else { + bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n")); + } + break; + case BST_DOING_ACQUIRE: + bnet_fsend(user, _(" Device is being initialized.\n")); + break; + case BST_WRITING_LABEL: + bnet_fsend(user, _(" Device is blocked labeling a Volume.\n")); + break; + default: + break; + } +} diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index c97203f7be..3de4d1c69a 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -38,7 +38,7 @@ static int use_device_cmd(JCR *jcr); /* Requests from the Director daemon */ static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s \ -type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d\n"; +type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s\n"; static char use_device[] = "use device=%s media_type=%s pool_name=%s pool_type=%s\n"; /* Responses sent to Director daemon */ @@ -65,7 +65,7 @@ int job_cmd(JCR *jcr) int JobId, errstat; char auth_key[100]; BSOCK *dir = jcr->dir_bsock; - POOLMEM *job_name, *client_name, *job, *fileset_name; + POOLMEM *job_name, *client_name, *job, *fileset_name, *fileset_md5; int JobType, level, spool_attributes, no_attributes; struct timeval tv; struct timezone tz; @@ -80,15 +80,17 @@ int job_cmd(JCR *jcr) job_name = get_memory(dir->msglen); client_name = get_memory(dir->msglen); fileset_name = get_memory(dir->msglen); + fileset_md5 = get_memory(dir->msglen); if (sscanf(dir->msg, jobcmd, &JobId, job, job_name, client_name, &JobType, &level, fileset_name, &no_attributes, - &spool_attributes) != 9) { + &spool_attributes, fileset_md5) != 10) { bnet_fsend(dir, BAD_job, dir->msg); Emsg1(M_FATAL, 0, _("Bad Job Command from Director: %s\n"), dir->msg); free_memory(job); free_memory(job_name); free_memory(client_name); free_memory(fileset_name); + free_memory(fileset_md5); jcr->JobStatus = JS_ErrorTerminated; return 0; } @@ -109,10 +111,13 @@ int job_cmd(JCR *jcr) jcr->JobLevel = level; jcr->no_attributes = no_attributes; jcr->spool_attributes = spool_attributes; + jcr->fileset_md5 = get_memory(strlen(fileset_md5) + 1); + strcpy(jcr->fileset_md5, fileset_md5); free_memory(job); free_memory(job_name); free_memory(client_name); free_memory(fileset_name); + free_memory(fileset_md5); /* Initialize FD start condition variable */ if ((errstat = pthread_cond_init(&jcr->job_start_wait, NULL)) != 0) { @@ -339,6 +344,9 @@ void stored_free_jcr(JCR *jcr) if (jcr->fileset_name) { free_memory(jcr->fileset_name); } + if (jcr->fileset_md5) { + free_memory(jcr->fileset_md5); + } if (jcr->bsr) { free_bsr(jcr->bsr); jcr->bsr = NULL; diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 92a34507ff..137ea73e24 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -104,7 +104,8 @@ because:\n %s"), dev_name(dev), strerror_dev(dev)); } else if (!unser_volume_label(dev, record)) { Mmsg(&jcr->errmsg, _("Could not unserialize Volume label: %s\n"), strerror_dev(dev)); - } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0) { + } else if (strcmp(dev->VolHdr.Id, BaculaId) != 0 && + strcmp(dev->VolHdr.Id, OldBaculaId) != 0) { Mmsg(&jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id); } else { ok = 1; @@ -179,7 +180,8 @@ int unser_volume_label(DEVICE *dev, DEV_RECORD *rec) if (rec->FileIndex != VOL_LABEL && rec->FileIndex != PRE_LABEL) { Mmsg3(&dev->errmsg, _("Expecting Volume Label, got FI=%s Stream=%s len=%d\n"), - FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream), + FI_to_ascii(rec->FileIndex), + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); return 0; } @@ -280,15 +282,15 @@ static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec) Fld(write_date) = 0; Fld(write_time) = 0; } else { - ser_float64(Fld(label_date)); - ser_float64(Fld(label_time)); - get_current_time(&dt); - Fld(write_date) = dt.julian_day_number; - Fld(write_time) = dt.julian_day_fraction; + /* OLD WAY DEPRECATED */ + ser_float64(Fld(label_date)); + ser_float64(Fld(label_time)); + get_current_time(&dt); + Fld(write_date) = dt.julian_day_number; + Fld(write_time) = dt.julian_day_fraction; } - - ser_float64(Fld(write_date)); /* unused if VerNum >= 11 */ - ser_float64(Fld(write_time)); /* unused if VerNum >= 11 */ + ser_float64(Fld(write_date)); /* 0 if VerNum >= 11 */ + ser_float64(Fld(write_time)); /* 0 if VerNum >= 11 */ ser_string(Fld(VolName)); ser_string(Fld(PrevVolName)); @@ -347,9 +349,10 @@ static int create_volume_label(DEVICE *dev, char *VolName) dev->VolHdr.label_date = 0; dev->VolHdr.label_time = 0; } else { - get_current_time(&dt); - dev->VolHdr.label_date = dt.julian_day_number; - dev->VolHdr.label_time = dt.julian_day_fraction; + /* OLD WAY DEPRECATED */ + get_current_time(&dt); + dev->VolHdr.label_date = dt.julian_day_number; + dev->VolHdr.label_time = dt.julian_day_fraction; } strcpy(dev->VolHdr.LabelProg, my_name); @@ -453,6 +456,7 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) ser_btime(get_current_btime()); ser_float64(0); } else { + /* OLD WAY DEPRECATED */ get_current_time(&dt); ser_float64(dt.julian_day_number); ser_float64(dt.julian_day_fraction); @@ -468,6 +472,9 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label) ser_string(jcr->fileset_name); ser_uint32(jcr->JobType); ser_uint32(jcr->JobLevel); + if (BaculaTapeVersion >= 11) { + ser_string(jcr->fileset_md5); + } if (label == EOS_LABEL) { ser_uint32(jcr->JobFiles); @@ -498,12 +505,22 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) Dmsg1(90, "session_label record=%x\n", rec); switch (label) { case SOS_LABEL: - jcr->StartBlock = dev->block_num; - jcr->StartFile = dev->file; + if (dev->state & ST_TAPE) { + jcr->StartBlock = dev->block_num; + jcr->StartFile = dev->file; + } else { + jcr->StartBlock = (uint32_t)dev->file_addr; + jcr->StartFile = (uint32_t)(dev->file_addr >> 32); + } break; case EOS_LABEL: - jcr->EndBlock = dev->block_num; - jcr->EndFile = dev->file; + if (dev->state & ST_TAPE) { + jcr->EndBlock = dev->block_num; + jcr->EndFile = dev->file; + } else { + jcr->EndBlock = (uint32_t)dev->file_addr; + jcr->EndFile = (uint32_t)(dev->file_addr >> 32); + } break; default: Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label); @@ -539,7 +556,7 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label) Dmsg6(20, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n\ remainder=%d\n", jcr->JobId, FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len, rec->remainder); free_record(rec); @@ -604,7 +621,7 @@ HostName : %s\n\ if (dev->VolHdr.VerNum >= 11) { char dt[50]; - bstrftime(dt, sizeof(dt), (time_t)dev->VolHdr.label_btime); + bstrftime(dt, sizeof(dt), btime_to_etime(dev->VolHdr.label_btime)); Pmsg1(-1, "Date label written: %s\n", dt); } else { dt.julian_day_number = dev->VolHdr.label_date; @@ -643,6 +660,9 @@ int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec) unser_uint32(label->JobType); unser_uint32(label->JobLevel); } + if (label->VerNum >= 11) { + unser_string(label->FileSetMD5); + } if (rec->FileIndex == EOS_LABEL) { unser_uint32(label->JobFiles); unser_uint64(label->JobBytes); @@ -714,7 +734,7 @@ JobStatus : %c\n\ } if (label.VerNum >= 11) { char dt[50]; - bstrftime(dt, sizeof(dt), (time_t)label.write_btime); + bstrftime(dt, sizeof(dt), btime_to_etime(label.write_btime)); Pmsg1(-1, _("Date written : %s\n"), dt); } else { dt.julian_day_number = label.write_date; diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 33b01fc8cf..52dc067d07 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -162,9 +162,9 @@ read_volume: break; /* got it */ case VOL_NAME_ERROR: Dmsg1(500, "Vol NAME Error Name=%s\n", jcr->VolumeName); - /* Check if we can accept this as an anonymous volume */ + /* Check if this is a valid Volume in the pool */ strcpy(jcr->VolumeName, dev->VolHdr.VolName); - if (!dev->capabilities & CAP_ANONVOLS || !dir_get_volume_info(jcr, 1)) { + if (!dir_get_volume_info(jcr, 1)) { goto mount_next_vol; } Dmsg1(200, "want new name=%s\n", jcr->VolumeName); diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 46720315de..d8cc8fd3d8 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -57,15 +57,16 @@ int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block); int read_block_from_device(DEVICE *dev, DEV_BLOCK *block); int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block); -/* From butil.c */ -void print_ls_output(char *fname, char *link, int type, struct stat *statp); -JCR *setup_jcr(char *name, char *device, BSR *bsr); -DEVICE *setup_to_read_device(JCR *jcr); -void display_error_status(DEVICE *dev); +/* From butil.c -- utilities for SD tool programs */ +void print_ls_output(char *fname, char *link, int type, struct stat *statp); +JCR *setup_jcr(char *name, char *device, BSR *bsr); +DEVICE *setup_to_access_device(JCR *jcr, int read_access); +void display_error_status(DEVICE *dev); +DEVRES *find_device_res(char *device_name); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, char *device); +DEVICE *init_dev(DEVICE *dev, DEVRES *device); int open_dev(DEVICE *dev, char *VolName, int mode); void close_dev(DEVICE *dev); void force_close_dev(DEVICE *dev); @@ -164,7 +165,7 @@ extern void create_vol_list(JCR *jcr); /* From record.c */ char *FI_to_ascii(int fi); -char *stream_to_ascii(int stream); +char *stream_to_ascii(int stream, int fi); int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 90f508be80..f747da67c2 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -133,7 +133,8 @@ next_record: } if (debug_level >= 30) { Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId, - FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream), + FI_to_ascii(rec->FileIndex), + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); } diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index 991cc7ad9c..410daa54f5 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -3,6 +3,7 @@ * record.c -- tape record handling functions * * Kern Sibbald, April MMI + * added BB02 format October MMII * * Version $Id$ * @@ -58,6 +59,9 @@ char *FI_to_ascii(int fi) return "SOS_LABEL"; case EOS_LABEL: return "EOS_LABEL"; + case EOT_LABEL: + return "EOT_LABEL"; + break; default: sprintf(buf, "unknown: %d", fi); return buf; @@ -68,10 +72,21 @@ char *FI_to_ascii(int fi) /* * Convert a Stream ID into a printable * ASCII string. Not reentrant. + + * A negative stream number represents + * stream data that is continued from a + * record in the previous block. + * If the FileIndex is negative, we are + * dealing with a Label, hence the + * stream is the JobId. */ -char *stream_to_ascii(int stream) +char *stream_to_ascii(int stream, int fi) { static char buf[20]; + if (fi < 0) { + sprintf(buf, "%d", stream); + return buf; + } switch (stream) { case STREAM_UNIX_ATTRIBUTES: return "UATTR"; @@ -81,6 +96,34 @@ char *stream_to_ascii(int stream) return "MD5"; case STREAM_GZIP_DATA: return "GZIP"; + case STREAM_WIN32_ATTRIBUTES: + return "WIN32-ATTR"; + case STREAM_SPARSE_DATA: + return "SPARSE-DATA"; + case STREAM_SPARSE_GZIP_DATA: + return "SPARSE-GZIP"; + case STREAM_PROGRAM_NAMES: + return "PROG-NAMES"; + case STREAM_PROGRAM_DATA: + return "PROG-DATA"; + case -STREAM_UNIX_ATTRIBUTES: + return "contUATTR"; + case -STREAM_FILE_DATA: + return "contDATA"; + case -STREAM_MD5_SIGNATURE: + return "contMD5"; + case -STREAM_GZIP_DATA: + return "contGZIP"; + case -STREAM_WIN32_ATTRIBUTES: + return "contWIN32-ATTR"; + case -STREAM_SPARSE_DATA: + return "contSPARSE-DATA"; + case -STREAM_SPARSE_GZIP_DATA: + return "contSPARSE-GZIP"; + case -STREAM_PROGRAM_NAMES: + return "contPROG-NAMES"; + case -STREAM_PROGRAM_DATA: + return "contPROG-DATA"; default: sprintf(buf, "%d", stream); return buf; @@ -144,7 +187,7 @@ int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) Dmsg6(190, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n\ rem=%d remainder=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len, remlen, rec->remainder); /* @@ -182,8 +225,8 @@ rem=%d remainder=%d\n", * time. Presumably we have a new buffer (possibly * containing a volume label), so the new header * should be able to fit in the block -- otherwise we have - * an error. Note, we may have to continue splitting the - * data record though. + * an error. Note, we have to continue splitting the + * data record if it is longer than the block. * * First, write the header, then write as much as * possible of the data record. @@ -237,12 +280,13 @@ rem=%d remainder=%d\n", } else { memcpy(block->bufp, rec->data+rec->data_len-rec->remainder, remlen); +#ifdef SMCHECK if (!sm_check_rtn(__FILE__, __LINE__, False)) { /* We damaged a buffer */ Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n\ rem=%d remainder=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len, + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len, remlen, rec->remainder); Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n", block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf, @@ -252,6 +296,7 @@ rem=%d remainder=%d\n", Emsg0(M_ABORT, 0, "Damaged buffer\n"); } +#endif block->bufp += remlen; block->binbuf += remlen; @@ -383,7 +428,8 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) Dmsg6(100, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n\ remlen=%d data_len=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), data_bytes, remlen, rec->data_len); + stream_to_ascii(rec->Stream, rec->FileIndex), data_bytes, remlen, + rec->data_len); } else { /* * No more records in this block because the number @@ -436,6 +482,6 @@ remlen=%d data_len=%d\n", rec->remainder = 0; Dmsg4(90, "Rtn full rd_rec_blk FI=%s SessId=%d Strm=%s len=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, - stream_to_ascii(rec->Stream), rec->data_len); + stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); return 1; /* transferred full record */ } diff --git a/bacula/src/stored/record.h b/bacula/src/stored/record.h index 2f300b1e6e..4c52729f3a 100644 --- a/bacula/src/stored/record.h +++ b/bacula/src/stored/record.h @@ -30,14 +30,14 @@ #define __RECORD_H 1 /* Return codes from read_device_volume_label() */ -#define VOL_NOT_READ 0 /* Volume label not read */ -#define VOL_OK 1 /* volume name OK */ -#define VOL_NO_LABEL 2 /* volume not labeled */ -#define VOL_IO_ERROR 3 /* volume I/O error */ -#define VOL_NAME_ERROR 4 /* Volume name mismatch */ -#define VOL_CREATE_ERROR 5 /* Error creating label */ -#define VOL_VERSION_ERROR 6 /* Bacula version error */ -#define VOL_LABEL_ERROR 7 /* Bad label type */ +#define VOL_NOT_READ 0 /* Volume label not read */ +#define VOL_OK 1 /* volume name OK */ +#define VOL_NO_LABEL 2 /* volume not labeled */ +#define VOL_IO_ERROR 3 /* volume I/O error */ +#define VOL_NAME_ERROR 4 /* Volume name mismatch */ +#define VOL_CREATE_ERROR 5 /* Error creating label */ +#define VOL_VERSION_ERROR 6 /* Bacula version error */ +#define VOL_LABEL_ERROR 7 /* Bad label type */ /* See block.h for RECHDR_LENGTH */ @@ -60,10 +60,10 @@ */ /* Record state bit definitions */ -#define REC_NO_HEADER 0x01 /* No header read */ +#define REC_NO_HEADER 0x01 /* No header read */ #define REC_PARTIAL_RECORD 0x02 /* returning partial record */ #define REC_BLOCK_EMPTY 0x04 /* not enough data in block */ -#define REC_NO_MATCH 0x08 /* No match on continuation data */ +#define REC_NO_MATCH 0x08 /* No match on continuation data */ #define REC_CONTINUATION 0x10 /* Continuation record found */ #define is_partial_record(r) ((r)->state & REC_PARTIAL_RECORD) @@ -76,21 +76,21 @@ * This is the memory structure for the record header. */ typedef struct s_dev_rec { - int sync; /* synchronous */ + int sync; /* synchronous */ /* File and Block are always returned on reading records, but * only returned on writing if sync is set (obviously). */ - uint32_t File; /* File number */ - uint32_t Block; /* Block number */ - uint32_t VolSessionId; /* sequential id within this session */ - uint32_t VolSessionTime; /* session start time */ - int32_t FileIndex; /* sequential file number */ - int32_t Stream; /* stream number */ - uint32_t data_len; /* current record length */ - uint32_t remainder; /* remaining bytes to read/write */ - uint32_t state; /* state bits */ + uint32_t File; /* File number */ + uint32_t Block; /* Block number */ + uint32_t VolSessionId; /* sequential id within this session */ + uint32_t VolSessionTime; /* session start time */ + int32_t FileIndex; /* sequential file number */ + int32_t Stream; /* stream number */ + uint32_t data_len; /* current record length */ + uint32_t remainder; /* remaining bytes to read/write */ + uint32_t state; /* state bits */ uint8_t ser_buf[WRITE_RECHDR_LENGTH]; /* serialized record header goes here */ - POOLMEM *data; /* Record data. This MUST be a memory pool item */ + POOLMEM *data; /* Record data. This MUST be a memory pool item */ } DEV_RECORD; @@ -99,12 +99,12 @@ typedef struct s_dev_rec { * Note, these values are negative to distinguish them * from user records where the FileIndex is forced positive. */ -#define PRE_LABEL -1 /* Vol label on unwritten tape */ -#define VOL_LABEL -2 /* Volume label first file */ -#define EOM_LABEL -3 /* Writen at end of tape */ -#define SOS_LABEL -4 /* Start of Session */ -#define EOS_LABEL -5 /* End of Session */ -#define EOT_LABEL -6 /* End of physical tape (2 eofs) */ +#define PRE_LABEL -1 /* Vol label on unwritten tape */ +#define VOL_LABEL -2 /* Volume label first file */ +#define EOM_LABEL -3 /* Writen at end of tape */ +#define SOS_LABEL -4 /* Start of Session */ +#define EOS_LABEL -5 /* End of Session */ +#define EOT_LABEL -6 /* End of physical tape (2 eofs) */ /* * Volume Label Record. This is the in-memory definition. The @@ -119,27 +119,27 @@ struct Volume_Label { * in the DEVICE buffer, but are not actually written * to the tape. */ - int32_t LabelType; /* This is written in header only */ - uint32_t LabelSize; /* length of serialized label */ + int32_t LabelType; /* This is written in header only */ + uint32_t LabelSize; /* length of serialized label */ /* * The items below this line are stored on * the tape */ - char Id[32]; /* Bacula Immortal ... */ + char Id[32]; /* Bacula Immortal ... */ - uint32_t VerNum; /* Label version number */ + uint32_t VerNum; /* Label version number */ /* VerNum <= 10 */ - float64_t label_date; /* Date tape labeled */ - float64_t label_time; /* Time tape labeled */ + float64_t label_date; /* Date tape labeled */ + float64_t label_time; /* Time tape labeled */ /* VerNum >= 11 */ - btime_t label_btime; /* tdate tape labeled */ - btime_t write_btime; /* tdate tape written */ + btime_t label_btime; /* tdate tape labeled */ + btime_t write_btime; /* tdate tape written */ /* Unused with VerNum >= 11 */ - float64_t write_date; /* Date this label written */ - float64_t write_time; /* Time this label written */ + float64_t write_date; /* Date this label written */ + float64_t write_time; /* Time this label written */ char VolName[MAX_NAME_LENGTH]; /* Volume name */ char PrevVolName[MAX_NAME_LENGTH]; /* Previous Volume Name */ @@ -148,9 +148,9 @@ struct Volume_Label { char MediaType[MAX_NAME_LENGTH]; /* Type of this media */ char HostName[MAX_NAME_LENGTH]; /* Host name of writing computer */ - char LabelProg[32]; /* Label program name */ - char ProgVersion[32]; /* Program version */ - char ProgDate[32]; /* Program build date/time */ + char LabelProg[32]; /* Label program name */ + char ProgVersion[32]; /* Program version */ + char ProgDate[32]; /* Program build date/time */ }; #define SER_LENGTH_Volume_Label 1024 /* max serialised length of volume label */ @@ -163,28 +163,29 @@ typedef struct Volume_Label VOLUME_LABEL; * This record is at the beginning and end of each session */ struct Session_Label { - char Id[32]; /* Bacula Immortal ... */ + char Id[32]; /* Bacula Immortal ... */ - uint32_t VerNum; /* Label version number */ + uint32_t VerNum; /* Label version number */ - uint32_t JobId; /* Job id */ - uint32_t VolumeIndex; /* Sequence no of volume for this job */ + uint32_t JobId; /* Job id */ + uint32_t VolumeIndex; /* Sequence no of volume for this job */ /* VerNum >= 11 */ - btime_t write_btime; /* Tdate this label written */ + btime_t write_btime; /* Tdate this label written */ /* VerNum < 11 */ - float64_t write_date; /* Date this label written */ + float64_t write_date; /* Date this label written */ /* Unused VerNum >= 11 */ - float64_t write_time; /* Time this label written */ + float64_t write_time; /* Time this label written */ char PoolName[MAX_NAME_LENGTH]; /* Pool name */ char PoolType[MAX_NAME_LENGTH]; /* Pool type */ char JobName[MAX_NAME_LENGTH]; /* base Job name */ char ClientName[MAX_NAME_LENGTH]; - char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */ + char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */ char FileSetName[MAX_NAME_LENGTH]; + char FileSetMD5[MAX_NAME_LENGTH]; uint32_t JobType; uint32_t JobLevel; /* The remainder are part of EOS label only */ @@ -195,11 +196,11 @@ struct Session_Label { uint32_t StartFile; uint32_t EndFile; uint32_t JobErrors; - uint32_t JobStatus; /* Job status */ + uint32_t JobStatus; /* Job status */ }; typedef struct Session_Label SESSION_LABEL; -#define SERIAL_BUFSIZE 1024 /* volume serialisation buffer size */ +#define SERIAL_BUFSIZE 1024 /* volume serialisation buffer size */ #endif diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 43d2145034..04571249b4 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -56,7 +56,7 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t VolSessionId = 0; uint32_t VolSessionTime; -static char *configfile; +char *configfile; static int foreground = 0; static workq_t dird_workq; /* queue for processing connections */ @@ -201,21 +201,7 @@ int main (int argc, char *argv[]) Emsg1(M_ABORT, 0, _("Too many Device Resources. Max=%d\n"), MAX_DEVICES); } Dmsg1(90, "calling init_dev %s\n", device->device_name); - device->dev = init_dev(&shm->dev[i], device->device_name); - /* Copy some attributes from the Device Resource to the DEV structure */ - if (device->dev) { - device->dev->capabilities = device->cap_bits; - device->dev->min_block_size = device->min_block_size; - device->dev->max_block_size = device->max_block_size; - device->dev->max_volume_jobs = device->max_volume_jobs; - device->dev->max_volume_files = device->max_volume_files; - device->dev->max_volume_size = device->max_volume_size; - device->dev->max_file_size = device->max_file_size; - device->dev->volume_capacity = device->volume_capacity; - device->dev->max_rewind_wait = device->max_rewind_wait; - device->dev->max_open_wait = device->max_open_wait; - device->dev->device = device; - } + device->dev = init_dev(&shm->dev[i], device); Dmsg1(10, "SD init done %s\n", device->device_name); if (!device->dev) { Emsg1(M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); diff --git a/bacula/src/tools/testfind.c b/bacula/src/tools/testfind.c index f98cf4297d..7182fdc22c 100644 --- a/bacula/src/tools/testfind.c +++ b/bacula/src/tools/testfind.c @@ -13,6 +13,7 @@ static int max_file_len = 0; static int max_path_len = 0; static int trunc_fname = 0; static int trunc_path = 0; +static int attrs = 0; static int print_file(FF_PKT *ff, void *pkt); @@ -46,8 +47,12 @@ main (int argc, char *const *argv) char name[1000]; int i, ch; - while ((ch = getopt(argc, argv, "d:?")) != -1) { + while ((ch = getopt(argc, argv, "ad:?")) != -1) { switch (ch) { + case 'a': /* print extended attributes *debug* */ + attrs = 1; + break; + case 'd': /* set debug level */ debug_level = atoi(optarg); if (debug_level <= 0) { @@ -98,6 +103,7 @@ Paths truncated: %d\n"), static int print_file(FF_PKT *ff, void *pkt) { + switch (ff->type) { case FT_LNKSAVED: if (debug_level == 1) { @@ -174,6 +180,14 @@ static int print_file(FF_PKT *ff, void *pkt) printf(_("Err: Unknown file ff->type %d: %s\n"), ff->type, ff->fname); break; } + if (attrs) { + char attr[200]; + encode_attribsEx(NULL, attr, ff); + if (*attr != 0) { + printf("AttrEx=%s\n", attr); + } + set_attribsEx(NULL, ff->fname, NULL, NULL, ff->type, attr); + } return 1; } diff --git a/bacula/src/version.h b/bacula/src/version.h index d68602ab23..4c0c418203 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ -#define VERSION "1.26" +#define VERSION "1.27" #define VSTRING "1" -#define DATE "10 October 2002" -#define LSMDATE "10Oct02" +#define DATE "22 October 2002" +#define LSMDATE "22Oct02" /* Debug flags */ #define DEBUG 1 -- 2.39.5