2002-mm-dd Version 1.27 (22Oct02) not yet released
+General: from kes29Oct02
+- Major change to the bnet communications routines.
+
+Changes submitted this submission:
+- Modified the bacula script to use pid files, so this script should
+ now work on more platforms. Updated devel_bacula as well.
+- Added the full GNU hostname on the configuration print output.
+- Added gettimeofday() to configure, and tweaked a few variables for
+ OpenBSD.
+- Added a chapter to the manual on Porting Bacula to other platforms.
+- Documented in Tips how to use the WriteBootstrap record.
+- Modified bc_types.h to error if 64 bit types are not found.
+- Pass replace option for restore to the FD (no code to use it yet).
+- Modify the FD to pass back the GNU OS string as well as the DISTNAME
+ and DISTVER. This needs to be put in the Client record in the catalog.
+- Major reworking of the bnet routines to eliminate the zero length which
+ previously indicated a signal. This risks to create some subtle communications
+ bugs. The changes now permit blank lines to be sent from the user to the
+ Director.
+- Found and corrected a few more places where the Win32 attributes were not
+ being recognized.
+- Permit spaces in the Where string (restore) by bashing/unbashing them.
+- Handle quotes correctly in the Console program (actually Dir ua code).
+ Previously they were not handled in the middle of a string.
+- Corrected two error message (error reading file), which previously stated
+ it was a network error.
+- Reworked the files in the binary Windows release. Removed unused programs
+ and added a README with the copyright as suggested by John. Also added
+ console.exe to the release.
+- Found and corrected an autoloader mount problem where the wrong tape
+ was specified. Previously it looped, then gave up. Now it correctly
+ detects the volume is not correct and zaps the Slot in the catalog.
+
General: from kes23Oct02
- I have mainly worked on getting all the details of a Restore
to work correctly (new tape format, support for Win32
Release Notes for Bacula 1.27
- Bacula code: Total files = 218 Total lines = 59,267 (*.h *.c *.in)
+ Bacula code: Total files = 220 Total lines = 59,468 (*.h *.c *.in)
Major Changes this Release:
- Implemented support for Sparse files.
- New Volume format. Will permit faster restores,
and correct restores of Volumes written with multiple
simultaneous jobs.
+- Important change to communications protocol. Eliminated
+ deprecated 0 signal.
Minor Changes this Release:
- Mount Anonymous Volumes is now dropped from the Storage
- Improve handling of the "Where" prefix on Win32 by first
stripping any previous drive. This allows restoration to
any drive.
+- Modified Director-FD logon sequence to pass the OS id strings
+ to the director.
+- Fixed mount loop when the autochanger slot is incorrect in
+ the catalog.
+- Updated the bacula script to work on more systems.
Items to note:
- The Dir-SD protocol has changed since 1.26, so you must
update the Director and Storage daemons.
+- The Dir-FD protocol has changed since 1.26 (and earlier versions
+ of 1.27).
/* Define if you have the getpid function. */
#undef HAVE_GETPID
+/* Define if you have the gettimeofday function. */
+#undef HAVE_GETTIMEOFDAY
+
/* Define if you have the inet_pton function. */
#undef HAVE_INET_PTON
getcwd \
gethostname \
getpid \
+ gettimeofday \
setpgid \
setpgrp \
setsid \
llu="qu"
TAPEDRIVE="/dev/nrst0"
PSCMD="ps -a -o pid,command"
+ PTHREAD_LIB="-pthread"
+ CFLAGS="${CFLAGS} -pthread"
;;
openbsd)
DISTVER=`uname -a |awk '{print $3}'`
llu="qu"
TAPEDRIVE="/dev/nrst0"
PSCMD="ps -a -o pid,command"
+ PTHREAD_LIB="-pthread"
+ CFLAGS="${CFLAGS} -pthread"
;;
redhat)
DISTVER=`cat /etc/redhat-release | grep release |\
src/stored/Makefile \
src/stored/bacula-sd.conf \
src/filed/Makefile \
+ src/filed/host.h \
src/filed/bacula-fd.conf \
src/filed/win32/Makefile \
src/cats/Makefile \
echo "
Configuration on `date`:
- Host: ${DISTNAME} ${DISTVER}
+ Host: $host -- ${DISTNAME} ${DISTVER}
Bacula version: ${VERSION} (${DATE})
Source code location: ${srcdir}
Install binaries: ${sbindir}
getcwd \
gethostname \
getpid \
+ gettimeofday \
setpgid \
setpgrp \
setsid \
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7492: checking for $ac_func" >&5
+echo "configure:7493: 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 <<EOF
-#line 7497 "configure"
+#line 7498 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7520: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7521: \"$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
for ac_func in fchdir
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7550: checking for $ac_func" >&5
+echo "configure:7551: 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 <<EOF
-#line 7555 "configure"
+#line 7556 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7578: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7579: \"$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
for ac_func in snprintf vsnprintf gethostid getdomainname
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7609: checking for $ac_func" >&5
+echo "configure:7610: 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 <<EOF
-#line 7614 "configure"
+#line 7615 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7638: \"$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
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:7665: checking for $ac_func" >&5
+echo "configure:7666: 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 <<EOF
-#line 7670 "configure"
+#line 7671 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:7693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7694: \"$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
# 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:7720: checking for gethostbyname_r" >&5
+echo "configure:7721: 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 <<EOF
-#line 7725 "configure"
+#line 7726 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char gethostbyname_r(); below. */
; return 0; }
EOF
-if { (eval echo configure:7748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7749: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for gethostbyname_r in -lnsl""... $ac_c" 1>&6
-echo "configure:7766: checking for gethostbyname_r in -lnsl" >&5
+echo "configure:7767: 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
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7774 "configure"
+#line 7775 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
gethostbyname_r()
; return 0; }
EOF
-if { (eval echo configure:7785: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7786: \"$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
fi
echo $ac_n "checking for gethostbyname_r in -lresolv""... $ac_c" 1>&6
-echo "configure:7813: checking for gethostbyname_r in -lresolv" >&5
+echo "configure:7814: 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
ac_save_LIBS="$LIBS"
LIBS="-lresolv $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7821 "configure"
+#line 7822 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
gethostbyname_r()
; return 0; }
EOF
-if { (eval echo configure:7832: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7833: \"$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
# Find where sockets are (especially for Solaris)
echo $ac_n "checking for socket""... $ac_c" 1>&6
-echo "configure:7865: checking for socket" >&5
+echo "configure:7866: 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 <<EOF
-#line 7870 "configure"
+#line 7871 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char socket(); below. */
; return 0; }
EOF
-if { (eval echo configure:7893: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7894: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for socket in -lxnet""... $ac_c" 1>&6
-echo "configure:7911: checking for socket in -lxnet" >&5
+echo "configure:7912: 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
ac_save_LIBS="$LIBS"
LIBS="-lxnet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7919 "configure"
+#line 7920 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
socket()
; return 0; }
EOF
-if { (eval echo configure:7930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7931: \"$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
fi
echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
-echo "configure:7958: checking for socket in -lsocket" >&5
+echo "configure:7959: 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
ac_save_LIBS="$LIBS"
LIBS="-lsocket $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 7966 "configure"
+#line 7967 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
socket()
; return 0; }
EOF
-if { (eval echo configure:7977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7978: \"$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
fi
echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6
-echo "configure:8005: checking for socket in -linet" >&5
+echo "configure:8006: 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
ac_save_LIBS="$LIBS"
LIBS="-linet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8013 "configure"
+#line 8014 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
socket()
; return 0; }
EOF
-if { (eval echo configure:8024: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8025: \"$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
for ac_func in inet_pton
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8057: checking for $ac_func" >&5
+echo "configure:8058: 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 <<EOF
-#line 8062 "configure"
+#line 8063 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:8085: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8086: \"$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
echo $ac_n "checking for strftime""... $ac_c" 1>&6
-echo "configure:8114: checking for strftime" >&5
+echo "configure:8115: 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 <<EOF
-#line 8119 "configure"
+#line 8120 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char strftime(); below. */
; return 0; }
EOF
-if { (eval echo configure:8142: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8143: \"$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
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:8164: checking for strftime in -lintl" >&5
+echo "configure:8165: 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
ac_save_LIBS="$LIBS"
LIBS="-lintl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8172 "configure"
+#line 8173 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
strftime()
; return 0; }
EOF
-if { (eval echo configure:8183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8184: \"$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
fi
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:8210: checking for vprintf" >&5
+echo "configure:8211: 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 <<EOF
-#line 8215 "configure"
+#line 8216 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
; return 0; }
EOF
-if { (eval echo configure:8238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8239: \"$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
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:8262: checking for _doprnt" >&5
+echo "configure:8263: 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 <<EOF
-#line 8267 "configure"
+#line 8268 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
; return 0; }
EOF
-if { (eval echo configure:8290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8291: \"$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
# 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:8317: checking for working alloca.h" >&5
+echo "configure:8318: 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 <<EOF
-#line 8322 "configure"
+#line 8323 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:8329: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8330: \"$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
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:8350: checking for alloca" >&5
+echo "configure:8351: 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 <<EOF
-#line 8355 "configure"
+#line 8356 "configure"
#include "confdefs.h"
#ifdef __GNUC__
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:8383: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8384: \"$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
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:8415: checking whether alloca needs Cray hooks" >&5
+echo "configure:8416: 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 <<EOF
-#line 8420 "configure"
+#line 8421 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
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:8445: checking for $ac_func" >&5
+echo "configure:8446: 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 <<EOF
-#line 8450 "configure"
+#line 8451 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:8473: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8474: \"$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
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:8500: checking stack direction for C alloca" >&5
+echo "configure:8501: 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
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 8508 "configure"
+#line 8509 "configure"
#include "confdefs.h"
find_stack_direction ()
{
exit (find_stack_direction() < 0);
}
EOF
-if { (eval echo configure:8527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8528: \"$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
# 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:8550: checking for getmntent in -lsun" >&5
+echo "configure:8551: 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
ac_save_LIBS="$LIBS"
LIBS="-lsun $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8558 "configure"
+#line 8559 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
getmntent()
; return 0; }
EOF
-if { (eval echo configure:8569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8570: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for getmntent in -lseq""... $ac_c" 1>&6
-echo "configure:8588: checking for getmntent in -lseq" >&5
+echo "configure:8589: 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
ac_save_LIBS="$LIBS"
LIBS="-lseq $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8596 "configure"
+#line 8597 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
getmntent()
; return 0; }
EOF
-if { (eval echo configure:8607: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8608: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for getmntent in -lgen""... $ac_c" 1>&6
-echo "configure:8626: checking for getmntent in -lgen" >&5
+echo "configure:8627: 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
ac_save_LIBS="$LIBS"
LIBS="-lgen $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8634 "configure"
+#line 8635 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
getmntent()
; return 0; }
EOF
-if { (eval echo configure:8645: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8646: \"$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
fi
echo $ac_n "checking for getmntent""... $ac_c" 1>&6
-echo "configure:8670: checking for getmntent" >&5
+echo "configure:8671: 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 <<EOF
-#line 8675 "configure"
+#line 8676 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char getmntent(); below. */
; return 0; }
EOF
-if { (eval echo configure:8698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8699: \"$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
fi
echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6
-echo "configure:8721: checking whether closedir returns void" >&5
+echo "configure:8722: 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
ac_cv_func_closedir_void=yes
else
cat > conftest.$ac_ext <<EOF
-#line 8729 "configure"
+#line 8730 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_header_dirent>
int closedir(); main() { exit(closedir(opendir(".")) != 0); }
EOF
-if { (eval echo configure:8735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8736: \"$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
fi
echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6
-echo "configure:8758: checking whether setpgrp takes no argument" >&5
+echo "configure:8759: 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
{ echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 8766 "configure"
+#line 8767 "configure"
#include "confdefs.h"
#ifdef HAVE_UNISTD_H
}
EOF
-if { (eval echo configure:8786: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8787: \"$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
fi
echo $ac_n "checking for working fnmatch""... $ac_c" 1>&6
-echo "configure:8809: checking for working fnmatch" >&5
+echo "configure:8810: 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
ac_cv_func_fnmatch_works=no
else
cat > conftest.$ac_ext <<EOF
-#line 8820 "configure"
+#line 8821 "configure"
#include "confdefs.h"
main() { exit (fnmatch ("a*", "abc", 0) != 0); }
EOF
-if { (eval echo configure:8824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:8825: \"$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
echo $ac_n "checking for setlocale in -lxpg4""... $ac_c" 1>&6
-echo "configure:8849: checking for setlocale in -lxpg4" >&5
+echo "configure:8850: 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
ac_save_LIBS="$LIBS"
LIBS="-lxpg4 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8857 "configure"
+#line 8858 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
setlocale()
; return 0; }
EOF
-if { (eval echo configure:8868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8869: \"$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
echo $ac_n "checking for getpwnam in -lsun""... $ac_c" 1>&6
-echo "configure:8891: checking for getpwnam in -lsun" >&5
+echo "configure:8892: 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
ac_save_LIBS="$LIBS"
LIBS="-lsun $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8899 "configure"
+#line 8900 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
getpwnam()
; return 0; }
EOF
-if { (eval echo configure:8910: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8911: \"$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
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:8942: checking for $ac_hdr" >&5
+echo "configure:8943: 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
-#line 8947 "configure"
+#line 8948 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8952: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8953: \"$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*
done
echo $ac_n "checking for deflate in -lz""... $ac_c" 1>&6
-echo "configure:8979: checking for deflate in -lz" >&5
+echo "configure:8980: 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
ac_save_LIBS="$LIBS"
LIBS="-lz $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 8987 "configure"
+#line 8988 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
deflate()
; return 0; }
EOF
-if { (eval echo configure:8998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8999: \"$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
PTHREAD_LIB=""
echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
-echo "configure:9029: checking for pthread_create in -lpthread" >&5
+echo "configure:9030: 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
ac_save_LIBS="$LIBS"
LIBS="-lpthread $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9037 "configure"
+#line 9038 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
pthread_create()
; return 0; }
EOF
-if { (eval echo configure:9048: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9049: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6
-echo "configure:9067: checking for pthread_create in -lpthreads" >&5
+echo "configure:9068: 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
ac_save_LIBS="$LIBS"
LIBS="-lpthreads $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9075 "configure"
+#line 9076 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
pthread_create()
; return 0; }
EOF
-if { (eval echo configure:9086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9087: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
-echo "configure:9105: checking for pthread_create in -lc_r" >&5
+echo "configure:9106: 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
ac_save_LIBS="$LIBS"
LIBS="-lc_r $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 9113 "configure"
+#line 9114 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
pthread_create()
; return 0; }
EOF
-if { (eval echo configure:9124: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9125: \"$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
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for pthread_create""... $ac_c" 1>&6
-echo "configure:9143: checking for pthread_create" >&5
+echo "configure:9144: 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 <<EOF
-#line 9148 "configure"
+#line 9149 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char pthread_create(); below. */
; return 0; }
EOF
-if { (eval echo configure:9171: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9172: \"$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
llu="qu"
TAPEDRIVE="/dev/nrst0"
PSCMD="ps -a -o pid,command"
+ PTHREAD_LIB="-pthread"
+ CFLAGS="${CFLAGS} -pthread"
;;
openbsd)
DISTVER=`uname -a |awk '{print $3}'`
llu="qu"
TAPEDRIVE="/dev/nrst0"
PSCMD="ps -a -o pid,command"
+ PTHREAD_LIB="-pthread"
+ CFLAGS="${CFLAGS} -pthread"
;;
redhat)
DISTVER=`cat /etc/redhat-release | grep release |\
src/stored/Makefile \
src/stored/bacula-sd.conf \
src/filed/Makefile \
+ src/filed/host.h \
src/filed/bacula-fd.conf \
src/filed/win32/Makefile \
src/cats/Makefile \
src/stored/Makefile \
src/stored/bacula-sd.conf \
src/filed/Makefile \
+ src/filed/host.h \
src/filed/bacula-fd.conf \
src/filed/win32/Makefile \
src/cats/Makefile \
echo "
Configuration on `date`:
- Host: ${DISTNAME} ${DISTVER}
+ Host: $host -- ${DISTNAME} ${DISTVER}
Bacula version: ${VERSION} (${DATE})
Source code location: ${srcdir}
Install binaries: ${sbindir}
Kern's ToDo List
- 23 October 2002
+ 25 October 2002
To do:
- 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 Include (does it cross file systems ?).
-- Document specifically how to add new File daemon to config files.
- Figure out why my Catalog size keeps growing (Filename and Path
tables keep growing) -- fix it.
-- Label (asks for slot, return and it stops).
+- Add Doc on saving MySQL databases, where to find code for shutting
+ down and saving other databases.
+
+For 1.27 release:
+- Continue improving the restore process (handling
+ of tapes, efficiency improvements e.g. use FSF to
+ position the tape, ...)
+- Allow restore with options (e.g. overwrite, overwrite
+ if newer, no overwrite, permit changing ownership, ...).
+- Test recovery of a damaged tape.
+- Work more on how to to a Bacula restore beginning with
+ just a Bacula tape and a boot floppy (bare metal recovery).
+- Possibly add a File System Module permitting an external
+ program do the file reading and writing during save and
+ restore (i.e. with this you could backup/restore
+ ANYTHING to and from a Bacula Volume, including horrible
+ stuff like Windows ACLs).
+- Preprocessing command per file.
+- Postprocessing command per file (when restoring).
+- File system type from File daemon
+- Decide what to do with JobTDate in catalog (make real btime_t?)
+- File daemon should pass Director the operating system info
+ to be stored in the Client Record (or verified that it has
+ not changed).
+- Add VOLUME_CAT_INFO to the EOS tape record (as
+ well as to the EOD record).
+- Send Volumes needed during restore to Console (just after
+ create_volume_list) -- also in restore command?
- 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().
- 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.
- 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.
+- Recovery of a bad tape (bcopy)
- 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
- it, if cancel gnome-console during sql command, DIR crashed. However,
- with it, blank line input for Where: is not possible.
-- Make SD disallow writing on Volume with fewer files than in
- the catalog.
- Put MaximumVolumeSize in Director.
- Document to have patience when SD first starts.
- Document running a test version.
in block, done when count is reached, and possibly other
optimizations. I.e. add a state word.
-
+After 1.27
- 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
- Make Restore report an error if FD or SD term codes are not OK.
- Convert all %x substitution variables, which are hard to remember
and read to %(variable-name). Idea from TMDA.
-- Report compression % and other compression statistics if turned on.
- Add JobLevel in FD status (but make sure it is defined).
- Make Pool resource handle Counter resources.
- Remove NextId for SQLite. Optimize.
- Fix Win32 config file definition name on /install
- No READLINE_SRC if found in alternate directory.
- Add Client FS/OS id (Linux, Win95/98, ...).
-- Put Windows files in Windows stream?
-- Ensure that everyone uses btime routines (mostly done).
Projects:
- Restore to a particular time -- e.g. before date, after date.
- Make all database Ids 64 bit.
- Write an applet for Linux.
-- Make SD reject writing on tape where Catalog and tape # files
- don't agree (possibly OK if tape > catalog).
-- Implement new daemon communications protocol.
-- Send Volumes needed during restore to Console (just after
- create_volume_list) -- also in restore command?
- Add estimate to Console commands
- Find solution to blank filename (i.e. path only) problem.
+- Implement new daemon communications protocol.
Dump:
mysqldump -f --opt bacula >bacula
- Remove PoolId from Job table, it exists in Media.
- Allow console commands to detach or run in background.
- Fix status delay on storage daemon during rewind.
-- Add VerNo to each Session label record.
-- Add Job to Session records.
-- Add VOLUME_CAT_INFO to the EOS tape record (as
- well as to the EOD record).
- Add SD message variables to control operator wait time
- Maximum Operator Wait
- Minimum Message Interval
- Require EOD records
- Send Operator message when cannot read tape label.
- Think about how to handle I/O error on MTEOM.
-- If Storage daemon aborts a job, ensure that this
- is printed in the error message.
- Verify level=Volume (scan only), level=Data (compare of data to file).
Verify level=Catalog, level=InitCatalog
-- Dump of Catalog
-- Cold start full restore (restore catalog then
- user selects what to restore). Write summary file containing only
- Job, Media, and Catalog information. Store on another machine.
-- Dump/Restore database
-- File system type
- Events file
- Add keyword search to show command in Console.
- Fix Win2000 error with no messages during startup.
- Events : tape has more than xxx bytes.
-- In Storage daemon, status should include job cancelled.
- Write general list maintenance subroutines.
-- Implement immortal format with EDOs.
- Restrict characters permitted in a Resource name.
-- Provide definitive identification of type in backup.
- Complete code in Bacula Resources -- this will permit
reading a new config file at any time.
-- Document new Console
- Handle ctl-c in Console
-- Test restore of Windows backup
- Implement LabelTemplate (at least first cut).
-- Implement script driven addition of File daemon to
- config files.
+- Implement script driven addition of File daemon to config files.
-- Bug: anonymous Volumes requires mount in some cases.
- see setgroup and user for Bacula p4-5 of stunnel.c
- Implement new serialize subroutines
send(socket, "string", &Vol, "uint32", &i, NULL)
-- Add save type to Session label.
-- Correct date on Session label.
-- On I/O error, write EOF, then try to write again.
-- Audit all UA commands to ensure that we always prompt where
- possible.
-- If ./btape is called without /dev, assume argument is
- a Storage resource name.
+- On I/O error, write EOF, then try to write again ????
+- Audit all UA commands to ensure that we always prompt where possible.
+- If ./btape is called without /dev, assume argument is a Storage resource name.
- Put memory utilization in Status output of each daemon
if full status requested or if some level of debug on.
- Make database type selectable by .conf files i.e. at runtime
- gethostbyname failure in bnet_connect() continues
generating errors -- should stop.
-- Don't create a volume that is already written. I.e. create only once.
-- If error at end of tape, implement some way to kill waiting processes.
- Add HOST to Volume label.
- Set flag for uname -a. Add to Volume label.
- Implement throttled work queue.
-- Write bscan program that will syncronize the DB Media record with
- the contents of the Volume -- for use after a crash.
- Check for EOT at ENOSPC or EIO or ENXIO (unix Pc)
- Allow multiple Storage specifications (or multiple names on
a single Storage specification) in the Job record. Thus a job
- Restore options (do not overwrite)
- Restore -- do nothing but show what would happen
- SET LD_RUN_PATH=$HOME/mysql/lib/mysql
-- Put Job statistics in End Session Label (files saved,
- total bytes, start time, ...).
-- Put FileSet name in the SOS label.
- Implement Restore FileSet=
- Write a scanner for the UA (keyword, scan-routine, result, prompt).
- Create a protocol.h and protocol.c where all protocol messages
- If SD cannot open a drive, make it periodically retry.
- Put Bacula version somewhere in Job stream, probably Start Session
Labels.
-- Remove duplicate fields from jcr (e.g. jcr.level and
- jcr.jr.Level, ...).
+- Remove duplicate fields from jcr (e.g. jcr.level and jcr.jr.Level, ...).
- Timout a job or terminate if link goes down, or reopen link and query.
-- Define how we handle times to avoid problem with Unix dates (2049 ?).
- Fill all fields in Vol/Job Header -- ensure that everything
needed is written to tape. Think about restore to Catalog
from tape. Client record needs improving.
- Find general solution for sscanf size problems (as well
as sprintf. Do at run time?
-
- Concept of precious tapes (cannot be reused).
- Allow FD to run from inetd ???
-- Preprocessing command per file.
-- Postprocessing command per file (when restoring).
- Restore should get Device and Pool information from
job record rather than from config.
- Autolabel should be specified by DR instead of SD.
-- Ability to recreate the catalog from a tape.
- Find out how to get the system tape block limits, e.g.:
Apr 22 21:22:10 polymatou kernel: st1: Block limits 1 - 245760 bytes.
Apr 22 21:22:10 polymatou kernel: st0: Block limits 2 - 16777214 bytes.
- MaxWarnings
- MaxErrors (job?)
=====
-- Eliminate duplicate File records to shrink database.
- FD sends unsaved file list to Director at end of job.
- Write a Storage daemon that uses pipes and
standard Unix programs to write to the tape.
See afbackup.
- Need something that monitors the JCR queue and
times out jobs by asking the deamons where they are.
-- Add daemon JCR JobId=0 to have a daemon context
-- Pool resource
- - Auto label
- - Auto media verify
- - Client (list of clients to force client)
- - Devices (list of devices to force device)
- - enable/disable
- - Groups
- - Levels
- - Type: Backup, ...
- - Recycle from other pools: Yes, No
- - Recycle to other pools: Yes, no
- - FileSets
- - MaxBytes?
- - Optional MediaType to force media?
- - Maintain Catalog
- - Label Template
- - Retention Period
- ============
- - Name
- - NumVols
- - NaxVols
- - CurrentVol
-=====
- if(connect(sockfd, (struct sockaddr * ) (& addr), sizeof(addr)) .lt. 0){
- close(sockfd);
- return(-6);
- }
-
- linger.l_onoff = 1;
- linger.l_linger = 60;
- i = setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *) &linger,
- sizeof (linger));
-
- fl = fcntl(sockfd, F_GETFL);
- fcntl(sockfd, F_SETFL, fl & (~ O_NONBLOCK) & (~ O_NDELAY));
-====
- Enhance Jmsg code to permit buffering and saving to disk.
- device driver = "xxxx" for drives.
- restart: paranoid: read label fsf to
at end of save retry and report any errors.
- Need report class for messages. Perhaps
report resource where report=group of messages
-- Verify from Tape
- enhance scan_attrib and rename scan_jobtype, and
fill in code for "since" option
- To buffer messages, we need associated jobid and Director name.
Don't reschedule a job if previous incarnation is still running.
- Figure out how to save the catalog (possibly a special FileSet).
- Figure out how to restore the catalog.
-- Figure out how to put a Volume into the catalog (from the tape)
-- Figure out how to do a restore from a Volume
- Some way to automatically backup everything is needed????
- Need a structure for pending actions:
- buffered messages
- Drive management
Read, Write, Clean, Delete
- Login to Bacula; Bacula users with different permissions:
- owner, group, user
+ owner, group, user, quotas
- Tape recycle destination
- Job Schedule Status
- Automatic
- Manual
- Running
-- File daemon should pass Director the operating system info
- to be stored in the Client Record (or verified that it has
- not changed).
- Store info on each file system type (probably in the job header on tape.
This could be the output of df; or perhaps some sort of /etc/mtab record.
- Look into MinGW
- Implement sparse files.
- Document sparse files.
+- Document better Include (does it cross file systems ?).
+- Document default config file locations.
+- Document specifically how to add new File daemon to config files.
+- Add VerNo to each Session label record.
+- Add Job to Session records.
+- Cold start full restore (restore catalog then
+ user selects what to restore). Write summary file containing only
+ Job, Media, and Catalog information. Store on another machine.
+- Dump/Restore database
+- Write bscan program that will syncronize the DB Media record with
+ the contents of the Volume -- for use after a crash.
+- Figure out how to put a Volume into the catalog (from the tape)
+- Figure out how to do a restore from a Volume
+- Report compression % and other compression statistics if turned on.
+- Put Windows files in Windows stream?
+- Ensure that everyone uses btime routines (mostly done).
+- Put Job statistics in End Session Label (files saved,
+ total bytes, start time, ...).
+- Put FileSet name in the SOS label.
+- Eliminate duplicate File records to shrink database.
+- If Storage daemon aborts a job, ensure that this
+ is printed in the error message.
+- Add save type to Session label.
+- Correct date on Session label.
+- Test restore of Windows backup
+- Ability to recreate the catalog from a tape.
+- Bug: anonymous Volumes requires mount in some cases.
+- Define how we handle times to avoid problem with Unix dates (2049 ?).
+- Add daemon JCR JobId=0 to have a daemon context
+- Implement full restoration of all Windows attributes
+ (such as Hidden, System, creation dates, ...)
+- Handle sparse files (i.e. files with holes in them)
+- Enhance testing for Bacula compatibility with
+ tape drives.
+- Turn on new BB02 tape format implemented in 1.26 but
+ not yet turned on.
+- More testing of restoring on Unix systems.
+- Implement additional tape format enhancements to better
+ support Windows and other non-Unix systems e.g.
+ extended attributes.
+- Upgrade to latest version of cygwin. (not possible)
+- Add configure for gettimeofday.
+- At line 51 of ua_input.c, why is = 0 necessary. Previously without
+ it, if cancel gnome-console during sql command, DIR crashed. However,
+ with it, blank line input for Where: is not possible.
+- Make SD disallow writing on Volume with fewer files than in
+ the catalog.
+- Label (asks for slot, return and it stops).
+- Make SD reject writing on tape where Catalog and tape # files
+ don't agree (possibly OK if tape > catalog).
# if (SIZEOF_CHAR == 1)
typedef unsigned char u_int8_t;
# else
-# error "8 bit int type not found."
+# error "8 bit int type not found. Required!"
# endif
# if (SIZEOF_SHORT_INT == 2)
typedef unsigned short int u_int16_t;
# else
-# error "16 bit int type not found."
+# error "16 bit int type not found. Required!"
# endif
# if (SIZEOF_INT == 4)
typedef unsigned int u_int32_t;
# else
-# error "32 bit int type not found."
+# error "32 bit int type not found. Required!"
# endif
# endif
#endif
# ifdef HAVE_INT64_T
typedef int64_t intmax_t;
# else
-typedef int32_t intmax_t;
+# error "64 bit type not found. Required!"
# endif
#endif
# if (SIZEOF_LONG_INT == 8)
typedef unsigned long int u_int64_t;
# define HAVE_U_INT64_T 1
+# else
+# error "64 bit type not found. Required!"
# endif
# endif
#endif
# ifdef HAVE_U_INT64_T
typedef u_int64_t u_intmax_t;
# else
-typedef u_int32_t u_intmax_t;
+# error "64 bit type not found. Required!"
# endif
#endif
char ed1[30], ed2[30];
db_lock(mdb);
- Mmsg(&mdb->cmd, "SELECT ClientId FROM Client WHERE Name='%s'", cr->Name);
+ Mmsg(&mdb->cmd, "SELECT ClientId,Uname FROM Client WHERE Name='%s'", cr->Name);
cr->ClientId = 0;
if (QUERY_DB(mdb, mdb->cmd)) {
return 0;
}
cr->ClientId = atoi(row[0]);
+ if (row[1]) {
+ strncpy(cr->Uname, row[1], sizeof(cr->Uname)-2);
+ cr->Uname[sizeof(cr->Uname)-1] = 0;
+ } else {
+ cr->Uname[0] = 0; /* no name */
+ }
sql_free_result(mdb);
db_unlock(mdb);
return 1;
stat = 1;
}
}
- if (stat < 0) {
+ if (stat < 0) {
break; /* error */
} else if (stat == 0) { /* timeout */
bnet_fsend(UA_sock, ".messages");
if (strcmp(UA_sock->msg, ".quit") == 0 || strcmp(UA_sock->msg, ".exit") == 0) {
break;
}
- while ((stat = bnet_recv(UA_sock)) > 0) {
+ while ((stat = bnet_recv(UA_sock)) >= 0) {
if (at_prompt) {
if (!stop) {
fprintf(output, "\n");
if (!stop) {
fflush(output);
}
- if (stat < 0) {
- break; /* error */
- } else if (stat == 0) {
+ if (is_bnet_stop(UA_sock)) {
+ break; /* error or term */
+ } else if (stat == BNET_SIGNAL) {
if (UA_sock->msglen == BNET_PROMPT) {
at_prompt = TRUE;
}
jcr->JobStatus = JS_WaitFD;
/* Wait for Client to terminate */
- while ((n = bget_msg(fd, 0)) > 0 && !job_cancelled(jcr)) {
+ while ((n = bget_msg(fd, 0)) >= 0 && !job_cancelled(jcr)) {
if (sscanf(fd->msg, EndBackup, &jcr->JobStatus, &jcr->JobFiles,
&jcr->ReadBytes, &jcr->JobBytes) == 4) {
fd_ok = TRUE;
+ Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus);
}
}
- bnet_sig(fd, BNET_TERMINATE); /* tell Client we are terminating */
- if (n < 0) {
+ if (is_bnet_error(fd)) {
Jmsg(jcr, M_FATAL, 0, _("<filed: network error during BACKUP command. ERR=%s\n"),
bnet_strerror(fd));
}
+ bnet_sig(fd, BNET_TERMINATE); /* tell Client we are terminating */
wait_for_storage_daemon_termination(jcr);
if (fd_ok && jcr->JobStatus != JS_Terminated) {
return jcr->JobStatus;
}
- if (!fd_ok || n < 0) {
+ if (!fd_ok || is_bnet_error(fd)) {
return JS_ErrorTerminated;
}
return jcr->SDJobStatus;
} else if (Stream == STREAM_MD5_SIGNATURE) {
fname = p;
if (jcr->FileIndex != FileIndex) {
- Jmsg(jcr, M_WARNING, 0, "Got MD5 but not same block as attributes\n");
+ Jmsg(jcr, M_WARNING, 0, "Got MD5 but not same File as attributes\n");
} else {
/* Update MD5 signature in catalog */
char MD5buf[50]; /* 24 bytes should be enough */
/* Options permitted in Restore replace= */
static struct s_kw ReplaceOptions[] = {
- {"always", 'A'}, /* always */
- {"ifnewer", 'W'},
- {"never", 'N'},
+ {"always", 'a'}, /* always */
+ {"ifnewer", 'w'},
+ {"never", 'n'},
{NULL, 0}
};
/* Define FileSet KeyWord values */
-#define FS_KW_NONE 0
-#define FS_KW_COMPRESSION 1
-#define FS_KW_SIGNATURE 2
-#define FS_KW_ENCRYPTION 3
-#define FS_KW_VERIFY 4
-#define FS_KW_ONEFS 5
-#define FS_KW_RECURSE 6
-#define FS_KW_SPARSE 7
-
-/* FileSet keywords */
+#define INC_KW_NONE 0
+#define INC_KW_COMPRESSION 1
+#define INC_KW_SIGNATURE 2
+#define INC_KW_ENCRYPTION 3
+#define INC_KW_VERIFY 4
+#define INC_KW_ONEFS 5
+#define INC_KW_RECURSE 6
+#define INC_KW_SPARSE 7
+#define INC_KW_REPLACE 8 /* restore options */
+
+/* Include keywords */
static struct s_kw FS_option_kw[] = {
- {"compression", FS_KW_COMPRESSION},
- {"signature", FS_KW_SIGNATURE},
- {"encryption", FS_KW_ENCRYPTION},
- {"verify", FS_KW_VERIFY},
- {"onefs", FS_KW_ONEFS},
- {"recurse", FS_KW_RECURSE},
- {"sparse", FS_KW_SPARSE},
+ {"compression", INC_KW_COMPRESSION},
+ {"signature", INC_KW_SIGNATURE},
+ {"encryption", INC_KW_ENCRYPTION},
+ {"verify", INC_KW_VERIFY},
+ {"onefs", INC_KW_ONEFS},
+ {"recurse", INC_KW_RECURSE},
+ {"sparse", INC_KW_SPARSE},
+ {"replace", INC_KW_REPLACE},
{NULL, 0}
};
/* Options permitted for each keyword and resulting value */
static struct s_fs_opt FS_options[] = {
- {"md5", FS_KW_SIGNATURE, "M"},
- {"gzip", FS_KW_COMPRESSION, "Z6"},
- {"gzip1", FS_KW_COMPRESSION, "Z1"},
- {"gzip2", FS_KW_COMPRESSION, "Z2"},
- {"gzip3", FS_KW_COMPRESSION, "Z3"},
- {"gzip4", FS_KW_COMPRESSION, "Z4"},
- {"gzip5", FS_KW_COMPRESSION, "Z5"},
- {"gzip6", FS_KW_COMPRESSION, "Z6"},
- {"gzip7", FS_KW_COMPRESSION, "Z7"},
- {"gzip8", FS_KW_COMPRESSION, "Z8"},
- {"gzip9", FS_KW_COMPRESSION, "Z9"},
- {"blowfish", FS_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
- {"3des", FS_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
- {"yes", FS_KW_ONEFS, "0"},
- {"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"},
+ {"md5", INC_KW_SIGNATURE, "M"},
+ {"gzip", INC_KW_COMPRESSION, "Z6"},
+ {"gzip1", INC_KW_COMPRESSION, "Z1"},
+ {"gzip2", INC_KW_COMPRESSION, "Z2"},
+ {"gzip3", INC_KW_COMPRESSION, "Z3"},
+ {"gzip4", INC_KW_COMPRESSION, "Z4"},
+ {"gzip5", INC_KW_COMPRESSION, "Z5"},
+ {"gzip6", INC_KW_COMPRESSION, "Z6"},
+ {"gzip7", INC_KW_COMPRESSION, "Z7"},
+ {"gzip8", INC_KW_COMPRESSION, "Z8"},
+ {"gzip9", INC_KW_COMPRESSION, "Z9"},
+ {"blowfish", INC_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
+ {"3des", INC_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
+ {"yes", INC_KW_ONEFS, "0"},
+ {"no", INC_KW_ONEFS, "f"},
+ {"yes", INC_KW_RECURSE, "0"},
+ {"no", INC_KW_RECURSE, "h"},
+ {"yes", INC_KW_SPARSE, "s"},
+ {"no", INC_KW_SPARSE, "0"},
+ {"always", INC_KW_REPLACE, "a"},
+ {"ifnewer", INC_KW_REPLACE, "w"},
+ {"never", INC_KW_REPLACE, "n"},
{NULL, 0, 0}
};
/*
- * Scan for FileSet options (keyword=option) is converted into one or
+ * Scan for Include options (keyword=option) is converted into one or
* two characters. Verifyopts=xxxx is Vxxxx:
*/
-static char *scan_fs_options(LEX *lc, int keyword)
+static char *scan_include_options(LEX *lc, int keyword)
{
int token, i;
static char opts[100];
opts[0] = option[2] = 0; /* terminate options */
for (;;) {
token = lex_get_token(lc, T_NAME); /* expect at least one option */
- if (keyword == FS_KW_VERIFY) { /* special case */
+ if (keyword == INC_KW_VERIFY) { /* special case */
/* ***FIXME**** ensure these are in permitted set */
strcpy(option, "V"); /* indicate Verify */
strcat(option, lc->str);
/* Get include options */
strcpy(inc_opts, "0"); /* set no options */
while ((token=lex_get_token(lc, T_ALL)) != T_BOB) {
- keyword = FS_KW_NONE;
+ keyword = INC_KW_NONE;
for (i=0; FS_option_kw[i].name; i++) {
if (strcasecmp(lc->str, FS_option_kw[i].name) == 0) {
keyword = FS_option_kw[i].token;
break;
}
}
- if (keyword == FS_KW_NONE) {
+ if (keyword == INC_KW_NONE) {
scan_err1(lc, "Expected a FileSet keyword, got: %s", lc->str);
}
/* Option keyword should be following by = <option> */
if ((token=lex_get_token(lc, T_ALL)) != T_EQUALS) {
scan_err1(lc, "expected an = following keyword, got: %s", lc->str);
}
- strcat(inc_opts, scan_fs_options(lc, keyword));
+ strcat(inc_opts, scan_include_options(lc, keyword));
if (token == T_BOB) {
break;
}
/* Responses received from File daemon */
static char OKinc[] = "2000 OK include\n";
static char OKexc[] = "2000 OK exclude\n";
-static char OKjob[] = "2000 OK Job\n";
+static char OKjob[] = "2000 OK Job";
/* Forward referenced functions */
Dmsg1(110, ">filed: %s", fd->msg);
if (bnet_recv(fd) > 0) {
Dmsg1(110, "<filed: %s", fd->msg);
- if (strcmp(fd->msg, OKjob) != 0) {
+ if (strncmp(fd->msg, OKjob, strlen(OKjob)) != 0) {
Jmsg(jcr, M_FATAL, 0, _("File daemon rejected Job command: %s\n"), fd->msg);
jcr->JobStatus = JS_ErrorTerminated;
return 0;
- }
+ } else {
+ /***** ***FIXME***** update Client Uname */
+ }
} else {
Jmsg(jcr, M_FATAL, 0, _("<filed: bad response to JobId command: %s\n"),
bnet_strerror(fd));
*fn = *p++; /* term filename and point to attribs */
attr = p;
- if (stream == STREAM_UNIX_ATTRIBUTES) {
+ if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) {
jcr->JobFiles++;
jcr->FileIndex = file_index;
ar.attr = attr;
jcr->jr.JobFiles = jcr->JobFiles = file_index;
jcr->jr.LastIndex = file_index;
}
- if (n < 0) {
+ if (is_bnet_error(fd)) {
Jmsg1(jcr, M_FATAL, 0, _("<filed: Network error getting attributes. ERR=%s\n"),
bnet_strerror(fd));
jcr->JobStatus = JS_ErrorTerminated;
n = bnet_recv(bs);
Dmsg2(120, "bget_msg %d: %s\n", n, bs->msg);
- if (n < 0) {
- return n; /* error return */
+ if (is_bnet_stop(bs)) {
+ return n; /* error or terminate */
}
- if (n == 0) { /* handle signal */
- /* 0 return from bnet_recv() => network signal */
+ if (n == BNET_SIGNAL) { /* handle signal */
+ /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
switch (bs->msglen) {
- case BNET_NONO: /* for compatibility */
case BNET_EOD: /* end of data */
- return 0;
+ return n;
case BNET_EOD_POLL:
bnet_fsend(bs, OK_msg);/* send response */
- return 0; /* end of data */
+ return n; /* end of data */
case BNET_TERMINATE:
bs->terminated = 1;
- return 0;
+ return n;
case BNET_POLL:
bnet_fsend(bs, OK_msg); /* send response */
break;
break;
default:
Emsg1(M_WARNING, 0, _("bget_msg: unknown signal %d\n"), bs->msglen);
- return 0;
+ return n;
}
continue;
}
{
int n;
- if (fd->errors) {
+ if (is_bnet_error(fd)) {
return 0;
}
- if ((n = bget_msg(fd, 0)) > 0) {
+ if ((n = bget_msg(fd, 0)) >= 0) {
Dmsg0(110, fd->msg);
if (strcmp(fd->msg, resp) == 0) {
return 1;
return 0;
}
jcr->jr.ClientId = cr.ClientId;
+ if (cr.Uname[0]) {
+ if (jcr->client_uname) {
+ free_pool_memory(jcr->client_uname);
+ }
+ jcr->client_uname = get_memory(strlen(cr.Uname) + 1);
+ strcpy(jcr->client_uname, cr.Uname);
+ }
Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
jcr->jr.ClientId);
return 1;
STORE *storage;
BSOCK *sd;
char auth_key[100];
- char *device_name, *pool_name, *pool_type, *media_type;
+ POOLMEM *device_name, *pool_name, *pool_type, *media_type;
int device_name_len, pool_name_len, pool_type_len, media_type_len;
storage = jcr->store;
bash_spaces(jcr->job->hdr.name);
bash_spaces(jcr->client->hdr.name);
bash_spaces(jcr->fileset->hdr.name);
+ if (jcr->fileset->MD5[0] == 0) {
+ strcpy(jcr->fileset->MD5, "**Dummy**");
+ }
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->fileset->MD5);
+ Dmsg1(200, "Jobcmd=%s\n", sd->msg);
unbash_spaces(jcr->job->hdr.name);
unbash_spaces(jcr->client->hdr.name);
unbash_spaces(jcr->fileset->hdr.name);
Dmsg1(110, "<stored: %s", sd->msg);
if (sscanf(sd->msg, OKjob, &jcr->VolSessionId,
&jcr->VolSessionTime, &auth_key) != 3) {
+ Dmsg1(100, "BadJob=%s\n", sd->msg);
Jmsg(jcr, M_FATAL, 0, _("Storage daemon rejected Job command: %s\n"), sd->msg);
return 0;
} else {
media_type_len = strlen(storage->media_type) + 1;
pool_type_len = strlen(jcr->pool->pool_type) + 1;
pool_name_len = strlen(jcr->pool->hdr.name) + 1;
- device_name = (char *) get_memory(device_name_len);
- pool_name = (char *) get_memory(pool_name_len);
- pool_type = (char *) get_memory(pool_type_len);
- media_type = (char *) get_memory(media_type_len);
+ device_name = get_memory(device_name_len);
+ pool_name = get_memory(pool_name_len);
+ pool_type = get_memory(pool_type_len);
+ media_type = get_memory(media_type_len);
memcpy(device_name, storage->dev_name, device_name_len);
memcpy(media_type, storage->media_type, media_type_len);
memcpy(pool_type, jcr->pool->pool_type, pool_type_len);
/* Read the Storage daemon's output.
*/
Dmsg0(200, "Start msg_thread loop\n");
- while ((stat=bget_msg(sd, 0)) > 0) {
+ while ((stat=bget_msg(sd, 0)) >= 0) {
Dmsg1(200, "<stored: %s", sd->msg);
if (sscanf(sd->msg, Job_start, &Job) == 1) {
continue;
continue;
}
}
- if (stat < 0) {
+ if (is_bnet_error(sd)) {
jcr->SDJobStatus = JS_ErrorTerminated;
}
pthread_cleanup_pop(1);
#include "dird.h"
/* Commands sent to File daemon */
-static char restorecmd[] = "restore where=%s\n";
+static char restorecmd[] = "restore replace=%c where=%s\n";
static char storaddr[] = "storage address=%s port=%d\n";
static char sessioncmd[] = "session %s %ld %ld %ld %ld %ld %ld\n";
}
/* Send restore command */
+ char replace, *where;
+
+ if (jcr->job->RestoreOptions != 0) {
+ replace = jcr->job->RestoreOptions;
+ } else {
+ replace = 'a'; /* always replace */
+ }
if (jcr->RestoreWhere) {
- bnet_fsend(fd, restorecmd, jcr->RestoreWhere);
+ where = jcr->RestoreWhere; /* override */
+ } else if (jcr->job->RestoreWhere) {
+ where = jcr->job->RestoreWhere; /* no override take from job */
} else {
- bnet_fsend(fd, restorecmd,
- jcr->job->RestoreWhere ? jcr->job->RestoreWhere : "");
+ where = ""; /* None */
}
+ bash_spaces(where);
+ bnet_fsend(fd, restorecmd, replace, where);
+ unbash_spaces(where);
+
if (!response(fd, OKrestore, "Restore")) {
restore_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
/* Wait for Job Termination */
- /*** ****FIXME**** get job termination status */
Dmsg0(20, "wait for job termination\n");
- while (bget_msg(fd, 0) > 0) {
+ while (bget_msg(fd, 0) >= 0) {
Dmsg1(100, "dird<filed: %s\n", fd->msg);
if (sscanf(fd->msg, EndRestore, &jcr->JobStatus, &jcr->JobFiles,
&jcr->JobBytes) == 3) {
Dmsg0(200, "Connected to file daemon\n");
fd = ua->jcr->file_bsock;
bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
- while (bnet_recv(fd) > 0) {
+ while (bnet_recv(fd) >= 0) {
bsendmsg(ua, "%s", fd->msg);
}
bnet_sig(fd, BNET_TERMINATE);
Dmsg0(200, "Connected to storage daemon\n");
sd = ua->jcr->store_bsock;
bnet_fsend(sd, "cancel Job=%s\n", jcr->Job);
- while (bnet_recv(sd) > 0) {
+ while (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
}
bnet_sig(sd, BNET_TERMINATE);
Dmsg0(120, _("Connected to storage daemon\n"));
sd = ua->jcr->store_bsock;
bnet_fsend(sd, "setdebug=%d\n", level);
- if (bnet_recv(sd) > 0) {
+ if (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
}
bnet_sig(sd, BNET_TERMINATE);
Dmsg0(120, "Connected to file daemon\n");
fd = ua->jcr->file_bsock;
bnet_fsend(fd, "setdebug=%d\n", level);
- if (bnet_recv(fd) > 0) {
+ if (bnet_recv(fd) >= 0) {
bsendmsg(ua, "%s", fd->msg);
}
bnet_sig(fd, BNET_TERMINATE);
bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d"),
dev_name, mr.VolumeName, pr.Name, mr.MediaType, mr.Slot);
bsendmsg(ua, "Sending label command ...\n");
- while (bget_msg(sd, 0) > 0) {
+ while (bget_msg(sd, 0) >= 0) {
bsendmsg(ua, "%s", sd->msg);
if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
ok = TRUE;
bash_spaces(dev_name);
bnet_fsend(sd, "mount %s", dev_name);
unbash_spaces(dev_name);
- while (bnet_recv(sd) > 0) {
+ while (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
/* Here we can get
* 3001 OK mount. Device=xxx or
} else {
bnet_fsend(sd, "unmount %s", dev_name);
}
- while (bnet_recv(sd) > 0) {
+ while (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
if (strncmp(sd->msg, "3001 OK mount.", 14) == 0) {
/***** ****FIXME**** fix JobStatus */
int get_cmd(UAContext *ua, char *prompt)
{
BSOCK *sock = ua->UA_sock;
+ int stat;
ua->cmd[0] = 0;
if (!sock) { /* No UA */
bnet_fsend(sock, "%s", prompt);
bnet_sig(sock, BNET_PROMPT); /* request more input */
for ( ;; ) {
- if (bnet_recv(sock) <= 0) {
- return 0;
+ stat = bnet_recv(sock);
+ if (stat == BNET_SIGNAL) {
+ continue; /* ignore signals */
+ }
+ if (is_bnet_stop(sock)) {
+ return 0; /* error or terminate */
}
ua->cmd = check_pool_memory_size(ua->cmd, sock->msglen+1);
bstrncpy(ua->cmd, sock->msg, sock->msglen+1);
char *next_arg(char **s)
{
char *p, *q, *n;
+ int in_quote = 0;
- Dmsg1(400, "Next arg=%s\n", *s);
/* skip past spaces to next arg */
for (p=*s; *p && *p == ' '; ) {
p++;
}
- /* Determine start of argument */
- if (*p == '"') {
- Dmsg0(400, "Start with quote.\n");
- for (n = q = ++p; *p && *p != '"'; ) {
- if (*p == '\\') {
- p++;
+ Dmsg1(400, "Next arg=%s\n", p);
+ for (n = q = p; *p ; ) {
+ if (*p == '\\') {
+ p++;
+ if (*p) {
+ *q++ = *p++;
+ } else {
+ *q++ = *p;
}
- *q++ = *p++;
+ continue;
}
- p++; /* skip terminating quote */
- for ( ; *p && *p != ' '; ) {
- *q++ = *p++;
- }
- *q = 0;
- } else {
- /* Scan argment and terminate it */
- n = p;
- for ( ; *p && *p != ' '; ) {
+ if (*p == '"') { /* start or end of quote */
+ if (in_quote) {
+ p++; /* skip quote */
+ in_quote = 0;
+ continue;
+ }
+ in_quote = 1;
p++;
+ continue;
}
- if (*p == ' ') {
- *p++ = 0;
+ if (!in_quote && *p == ' ') { /* end of field */
+ p++;
+ break;
}
+ *q++ = *p++;
}
+ *q = 0;
*s = p;
Dmsg2(400, "End arg=%s next=%s\n", n, p);
return n;
*p++ = 0; /* terminate keyword and point to value */
/* Unquote quoted values */
if (*p == '"') {
- Dmsg0(400, "Start with quote.\n");
+ Dmsg1(000, "Start with quote: %s\n", p);
for (n = q = ++p; *p && *p != '"'; ) {
if (*p == '\\') {
p++;
}
*q++ = *p++;
}
- p++; /* skip terminating quote */
- for ( ; *p && *p != ' '; ) {
- *q++ = *p++;
- }
- *q = 0;
- p = n;
+ *q = 0; /* terminate string */
+ p = n; /* point to string */
}
if (strlen(p) > MAX_NAME_LENGTH-1) {
p[MAX_NAME_LENGTH-1] = 0; /* truncate to max len */
/* Find Job */
job = (JOB *)GetResWithName(R_JOB, job_name);
if (!job) {
- bsendmsg(ua, _("Job %s: not found\n"), job_name);
+ bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
job = select_job_resource(ua);
} else {
Dmsg1(200, "Found job=%s\n", job_name);
if (store_name) {
store = (STORE *)GetResWithName(R_STORAGE, store_name);
if (!store) {
- bsendmsg(ua, _("Storage %s not found.\n"), store_name);
+ bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
store = select_storage_resource(ua);
}
} else {
if (client_name) {
client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
if (!client) {
- bsendmsg(ua, _("Client %s not found.\n"), client_name);
+ bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
client = select_client_resource(ua);
}
} else {
if (fileset_name) {
fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
if (!fileset) {
- bsendmsg(ua, _("FileSet %s not found.\n"), fileset_name);
+ bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
fileset = select_fileset_resource(ua);
}
} else {
while (!ua.quit) {
stat = bnet_recv(ua.UA_sock);
- if (stat > 0) {
+ if (stat >= 0) {
ua.cmd = check_pool_memory_size(ua.cmd, ua.UA_sock->msglen+1);
bstrncpy(ua.cmd, ua.UA_sock->msg, ua.UA_sock->msglen+1);
parse_command_args(&ua);
}
bnet_sig(ua.UA_sock, BNET_EOD); /* send end of command */
}
- } else if (stat == 0) {
- if (ua.UA_sock->msglen == BNET_TERMINATE) {
- ua.quit = TRUE;
- break;
- }
+ } else if (is_bnet_stop(ua.UA_sock)) {
+ ua.quit = TRUE;
+ break;
+ } else { /* signal */
bnet_sig(ua.UA_sock, BNET_POLL);
- } else {
- break; /* error, exit */
}
}
Dmsg0(20, _("Connected to storage daemon\n"));
sd = ua->jcr->store_bsock;
bnet_fsend(sd, "status");
- while (bnet_recv(sd) > 0) {
+ while (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
}
bnet_sig(sd, BNET_TERMINATE);
Dmsg0(20, _("Connected to file daemon\n"));
fd = ua->jcr->file_bsock;
bnet_fsend(fd, "status");
- while (bnet_recv(fd) > 0) {
+ while (bnet_recv(fd) >= 0) {
bsendmsg(ua, "%s", fd->msg);
}
bnet_sig(fd, BNET_TERMINATE);
* Attributes
* Link name ???
*/
- while ((n=bget_msg(fd, 0)) > 0 && !job_cancelled(jcr)) {
+ while ((n=bget_msg(fd, 0)) >= 0 && !job_cancelled(jcr)) {
int stream;
char *attr, *p, *fn;
char Opts_MD5[MAXSTRING]; /* Verify Opts or MD5 signature */
/*
* Got attributes stream, decode it
*/
- if (stream == STREAM_UNIX_ATTRIBUTES) {
+ if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) {
Dmsg2(400, "file_index=%d attr=%s\n", file_index, attr);
jcr->JobFiles++;
jcr->FileIndex = file_index; /* remember attribute file_index */
}
jcr->JobFiles = file_index;
}
- if (n < 0) {
+ if (is_bnet_error(fd)) {
Jmsg2(jcr, M_FATAL, 0, _("bdird<filed: bad attributes from filed n=%d : %s\n"),
n, strerror(errno));
goto bail_out;
btraceback.gdb
startit
stopit
+host.h
} /* end while read file data */
if (sd->msglen < 0) {
- Jmsg(jcr, M_ERROR, 0, _("Network error. ERR=%s\n"), bnet_strerror(sd));
+ Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"),
+ ff_pkt->fname, strerror(errno));
}
#ifndef NO_FD_SEND_TEST
#include "bacula.h"
#include "filed.h"
+#include "host.h"
extern char my_name[];
extern CLIENT *me; /* our client resource */
static int restore_cmd(JCR *jcr);
static int storage_cmd(JCR *jcr);
static int session_cmd(JCR *jcr);
-static int response(BSOCK *sd, char *resp, char *cmd);
+static int response(JCR *jcr, BSOCK *sd, char *resp, char *cmd);
static void filed_free_jcr(JCR *jcr);
static int open_sd_read_session(JCR *jcr);
static int send_bootstrap_file(JCR *jcr);
static char jobcmd[] = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
static char storaddr[] = "storage address=%s port=%d\n";
static char sessioncmd[] = "session %s %ld %ld %ld %ld %ld %ld\n";
-static char restorecmd[] = "restore where=%s\n";
+static char restorecmd[] = "restore replace=%c where=%s\n";
static char verifycmd[] = "verify level=%20s\n";
/* Responses sent to Director */
static char OKrestore[] = "2000 OK restore\n";
static char OKsession[] = "2000 OK session\n";
static char OKstore[] = "2000 OK storage\n";
-static char OKjob[] = "2000 OK Job\n";
+static char OKjob[] = "2000 OK Job " FDHOST "," DISTNAME "," DISTVER;
static char OKsetdebug[] = "2000 OK setdebug=%d\n";
static char BADjob[] = "2901 Bad Job\n";
static char EndRestore[] = "2800 End Job TermCode=%d JobFiles=%u JobBytes=%" lld "\n";
/* Responses received from Storage Daemon */
static char OK_end[] = "3000 OK end\n";
+static char OK_close[] = "3000 OK close Status = %d\n";
static char OK_open[] = "3000 OK open ticket = %d\n";
static char OK_data[] = "3000 OK data\n";
static char OK_append[] = "3000 OK append data\n";
for (quit=0; !quit;) {
/* Read command */
- if (bnet_recv(dir) <= 0) {
+ if (bnet_recv(dir) < 0) {
break; /* connection terminated */
}
dir->msg[dir->msglen] = 0;
{
BSOCK *dir = jcr->dir_bsock;
- while (bnet_recv(dir) > 0) {
+ while (bnet_recv(dir) >= 0) {
dir->msg[dir->msglen] = 0;
strip_trailing_junk(dir->msg);
Dmsg1(110, "filed<dird: include file %s\n", dir->msg);
BSOCK *dir = jcr->dir_bsock;
char *p;
- while (bnet_recv(dir) > 0) {
+ while (bnet_recv(dir) >= 0) {
dir->msg[dir->msglen] = 0;
strip_trailing_junk(dir->msg);
/* Skip leading options */
return 0;
}
- while (bnet_recv(dir) > 0) {
+ while (bnet_recv(dir) >= 0) {
Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
fputs(dir->msg, bs);
}
{
BSOCK *dir = jcr->dir_bsock;
BSOCK *sd = jcr->store_bsock;
- int len;
+ int ok = 0;
+ int SDJobStatus;
jcr->JobStatus = JS_Blocked;
jcr->JobType = JT_BACKUP;
/*
* Expect to receive back the Ticket number
*/
- if (bnet_recv(sd) > 0) {
+ if (bnet_recv(sd) >= 0) {
Dmsg1(110, "<stored: %s", sd->msg);
if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
* Expect to get OK data
*/
Dmsg1(110, "<stored: %s", sd->msg);
- if (!response(sd, OK_data, "Append Data")) {
+ if (!response(jcr, sd, OK_data, "Append Data")) {
jcr->JobStatus = JS_ErrorTerminated;
goto cleanup;
}
/*
* Expect to get response to append_data from Storage daemon
*/
- if (!response(sd, OK_append, "Append Data")) {
+ if (!response(jcr, sd, OK_append, "Append Data")) {
jcr->JobStatus = JS_ErrorTerminated;
goto cleanup;
}
*/
bnet_fsend(sd, append_end, jcr->Ticket);
/* Get end OK */
- if (!response(sd, OK_end, "Append End")) {
+ if (!response(jcr, sd, OK_end, "Append End")) {
jcr->JobStatus = JS_ErrorTerminated;
goto cleanup;
}
* Send Append Close to Storage daemon
*/
bnet_fsend(sd, append_close, jcr->Ticket);
- while ((len = bnet_recv(sd)) > 0) {
- /* discard anything else returned from SD */
+ while (bnet_recv(sd) >= 0) { /* stop on signal or error */
+ if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
+ ok = 1;
+ Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
+ }
+ }
+ if (!ok) {
+ Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
+ jcr->JobStatus = JS_ErrorTerminated;
+ goto cleanup;
}
- if (len < 0) {
- Jmsg(jcr, M_FATAL, 0, _("<stored: net_recv len=%d: ERR=%s\n"), len, bnet_strerror(sd));
+ if (SDJobStatus != JS_Terminated) {
+ Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
+ SDJobStatus);
jcr->JobStatus = JS_ErrorTerminated;
}
}
BSOCK *dir = jcr->dir_bsock;
BSOCK *sd = jcr->store_bsock;
POOLMEM *where;
+ char replace;
/*
* Scan WHERE (base directory for restore) from command
/* Pickup where string */
where = get_memory(dir->msglen+1);
*where = 0;
- sscanf(dir->msg, restorecmd, where);
- Dmsg1(150, "Got where=%s\n", where);
+
+ if (sscanf(dir->msg, restorecmd, &replace, where) != 2) {
+ Jmsg(jcr, M_FATAL, 0, _("Bad replace command.\n"));
+ return 0;
+ }
+
+ Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
+ unbash_spaces(where);
jcr->where = where;
+ jcr->replace = replace;
bnet_fsend(dir, OKrestore);
Dmsg1(110, "bfiled>dird: %s", dir->msg);
/*
* Get ticket number
*/
- if (bnet_recv(sd) > 0) {
+ if (bnet_recv(sd) >= 0) {
Dmsg1(110, "bfiled<stored: %s", sd->msg);
if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
/*
* Get OK data
*/
- if (!response(sd, OK_data, "Read Data")) {
+ if (!response(jcr, sd, OK_data, "Read Data")) {
return 0;
}
return 1;
* Returns: 0 on failure
* 1 on success
*/
-int response(BSOCK *sd, char *resp, char *cmd)
+int response(JCR *jcr, BSOCK *sd, char *resp, char *cmd)
{
int n;
return 1;
}
}
- /* ********FIXME******** segfault if the following is executed */
- if (n > 0) {
- Emsg3(M_FATAL, 0, _("<stored: bad response to %s: wanted: %s, got: %s\n"),
- cmd, resp, sd->msg);
- } else {
- Emsg2(M_FATAL, 0, _("<stored: bad response to %s command: ERR=%s\n"),
+ if (is_bnet_error(sd)) {
+ Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
cmd, bnet_strerror(sd));
+ } else {
+ Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
+ cmd, resp, sd->msg);
}
return 0;
}
}
bnet_sig(sd, BNET_EOD);
fclose(bs);
- if (!response(sd, OKSDbootstrap, "Bootstrap")) {
+ if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
jcr->JobStatus = JS_ErrorTerminated;
return 0;
}
* or c. Possibly MD5 record
* 3. Repeat step 1
*/
- while (bnet_recv(sd) > 0 && !job_cancelled(jcr)) {
+ while (bnet_recv(sd) >= 0 && !job_cancelled(jcr)) {
/*
* First we expect a Stream Record Header
*/
jcr->JobBytes += n;
}
if (n < 0) {
- Jmsg(jcr, M_WARNING, -1, _(" Error reading file %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno));
+ Jmsg(jcr, M_WARNING, -1, _("Error reading file %s: ERR=%s\n"),
+ ff_pkt->fname, strerror(errno));
}
MD5Final(signature, &md5c);
/*
* Get a record from the Storage daemon
*/
- while (bnet_recv(sd) > 0 && !job_cancelled(jcr)) {
+ while (bnet_recv(sd) >= 0 && !job_cancelled(jcr)) {
/*
* First we expect a Stream Record Header
*/
Dmsg1(30, "Got stream data, len=%d\n", sd->msglen);
/* File Attributes stream */
- if (stream == STREAM_UNIX_ATTRIBUTES) {
+ if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_WIN32_ATTRIBUTES) {
char *ap, *lp, *fp;
Dmsg0(400, "Stream=Unix Attributes.\n");
* Filename
* Attributes
* Link name (if file linked i.e. FT_LNK)
- *
+ * Extended Attributes (if Win32)
*/
if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) {
Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg);
Dmsg1(200, "Attr=%s\n", ap);
/* Skip to Link name */
- if (type == FT_LNK) {
+ if (type == FT_LNK || type == FT_LNKSAVED) {
lp = ap;
while (*lp++ != 0) {
;
*/
/* Send file attributes to Director */
Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname);
- if (type == FT_LNK) {
+ if (type == FT_LNK || type == FT_LNKSAVED) {
stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
STREAM_UNIX_ATTRIBUTES, "pinsug5", fname,
0, ap, 0, lname, 0);
/* Data stream */
- } else if (stream == STREAM_FILE_DATA) {
+ } else if (stream == STREAM_FILE_DATA || stream == STREAM_SPARSE_DATA) {
/* Do nothing */
/* GZIP data stream */
- } else if (stream == STREAM_GZIP_DATA) {
+ } else if (stream == STREAM_GZIP_DATA || stream == STREAM_SPARSE_GZIP_DATA) {
/* Do nothing */
@echo "Installing system binary files ..."
@strip ../bacula-fd.exe
@strip ../../tools/smtp.exe
+ @strip ../../console/console.exe
@cp -f ../bacula-fd.exe bin/
@cp -f ../../tools/smtp.exe bin/
+ @cp -f ../../console/console.exe bin/
@cp -f bin/* $(sbindir)
+ @cp -f ../bacula-fd.conf $(sysconfdir)/bacula-fd.conf.new
+ @cp -f ../../console/console.conf $(sysconfdir)/console.conf.new
# Make a Win32 binary release
binary-release:
@cp bin/* wr/$(sbindir)
@strip ../bacula-fd.exe
@strip ../../tools/smtp.exe
+ @strip ../../console/console.exe
@echo "Copying executables ..."
@cp -f ../bacula-fd.exe wr/$(sbindir)/bacula-fd.exe
@cp -f ../../tools/smtp.exe wr/$(sbindir)/smtp.exe
+ @cp -f ../../console/console.exe wr/$(sbindir)/console.exe
@echo "Copying bacula-fd.conf..."
@cp -f ../bacula-fd.conf wr/$(sysconfdir)/bacula-fd.conf.new
+ @cp -f ../../console/console.conf wr/$(sysconfdir)/console.conf.new
# the two dummy files are necessary to insure that WinZip
# actually creates the directories.
@echo "dummy" >wr/tmp/dummy.txt
--- /dev/null
+
+ Bacula(tm) Win32
+
+
+This is the binary distribution of Bacula for Win32
+systems (Win95, Win98, WinMe, WinNT, and Win2000).
+
+INSTALLATION
+
+1. From TAR Archive
+
+To install it, please UnZip (or detar) the distribution
+file into your root directory on drive c:\ then follow
+the instructions in the online manual viewable by any
+Internet Browser (Netscape, Microsoft Internet Explorer).
+See http://www.bacula.net/htm-manual
+or get the source release
+
+Bacula (tm) is released under the GPL license (given below).
+
+Bacula uses cygwin1.dll, which is also released under the
+GPL license. The source code and other information about
+cygwin can be found at http://www.cygwin.com
+
+/*
+ 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.
+
+ */
+
#define FO_NO_RECURSION 0x04 /* no recursion in directories */
#define FO_MULTIFS 0x08 /* multiple file systems */
#define FO_SPARSE 0x10 /* do sparse file checking */
+#define FO_IF_NEWER 0x20 /* replace if newer */
+#define FO_NOREPLACE 0x40 /* never replace */
/* Options saved in "options" of include list */
/* ****FIXME**** replace OPT_ flags with FO_ */
#define OPT_no_recursion 0x04 /* no recursion in directories */
#define OPT_multifs 0x08 /* multiple file systems */
#define OPT_sparse 0x10 /* do sparse file checking */
+#define OPT_replace_if_newer 0x20 /* replace file if newer */
+#define OPT_never_replace 0x40 /* never replace */
struct s_included_file {
if (prefixed) {
for (p=fname; *p && *p != ' '; p++) {
switch (*p) {
- case '0': /* no option */
+ case 'a': /* alway replace */
+ case '0': /* no option */
break;
- case 'M': /* MD5 */
+ case 'w':
+ inc->options |= OPT_replace_if_newer;
+ break;
+ case 'n':
+ inc->options |= OPT_never_replace;
+ break;
+ case 'M': /* MD5 */
inc->options |= OPT_compute_MD5;
break;
- case 'Z': /* gzip compression */
+ case 'Z': /* gzip compression */
inc->options |= OPT_GZIP_compression;
inc->level = *++p - '0';
Dmsg1(200, "Compression level=%d\n", inc->level);
break;
- case 'h': /* no recursion */
+ case 'h': /* no recursion */
inc->options |= OPT_no_recursion;
break;
case 'f':
JOB_DBR jr; /* Job record in Database */
uint32_t RestoreJobId; /* Id specified by UA */
char *RestoreWhere; /* Where to restore the files */
+ POOLMEM *client_uname; /* client uname */
#endif /* DIRECTOR_DAEMON */
#ifdef FILE_DAEMON
POOLMEM *compress_buf; /* Compression buffer */
int32_t compress_buf_size; /* Length of compression buffer */
POOLMEM *where; /* Root where to restore */
+ int replace; /* Replace options */
int buf_size; /* length of buffer */
FF_PKT *ff; /* Find Files packet */
char stored_addr[MAX_NAME_LENGTH]; /* storage daemon address */
* Receive a message from the other end. Each message consists of
* two packets. The first is a header that contains the size
* of the data that follows in the second packet.
- * Returns number of bytes read
- * Returns 0 on end of file
- * Returns -1 on hard end of file (i.e. network connection close)
- * Returns -2 on error
+ * Returns number of bytes read (may return zero)
+ * Returns -1 on signal (BNET_SIGNAL)
+ * Returns -2 on hard end of file (BNET_HARDEOF)
+ * Returns -3 on error (BNET_ERROR)
+ *
+ * Unfortunately, it is a bit complicated because we have these
+ * four return types:
+ * 1. Normal data
+ * 2. Signal including end of data stream
+ * 3. Hard end of file
+ * 4. Error
+ * Using is_bnet_stop() and is_bnet_error() you can figure this all out.
*/
-/* EXTPROTO */
-int32_t
-bnet_recv(BSOCK *bsock)
+int32_t bnet_recv(BSOCK *bsock)
{
int32_t nbytes;
int32_t pktsiz;
bsock->msg[0] = 0;
if (bsock->errors || bsock->terminated) {
- return -2;
+ return BNET_HARDEOF;
}
bsock->read_seqno++; /* bump sequence number */
bsock->b_errno = errno;
}
bsock->errors++;
- return -1; /* assume hard EOF received */
+ return BNET_HARDEOF; /* assume hard EOF received */
}
bsock->timer_start = 0; /* clear timer */
if (nbytes != sizeof(int32_t)) {
bsock->b_errno = EIO;
Jmsg3(bsock->jcr, M_ERROR, 0, _("Read %d expected %d from %s\n"), nbytes, sizeof(int32_t),
bsock->who);
- return -2;
+ return BNET_ERROR;
}
pktsiz = ntohl(pktsiz); /* decode no. of bytes that follow */
+ if (pktsiz == 0) { /* No data transferred */
+ bsock->timer_start = 0; /* clear timer */
+ bsock->in_msg_no++;
+ bsock->msglen = 0;
+ return 0; /* zero bytes read */
+ }
+
/* If signal or packet size too big */
- if (pktsiz <= 0 || pktsiz > 10000000) {
+ if (pktsiz < 0 || pktsiz > 10000000) {
if (pktsiz == BNET_TERMINATE) {
bsock->terminated = 1;
}
+ bsock->timer_start = 0; /* clear timer */
bsock->b_errno = ENODATA;
- bsock->msglen = pktsiz; /* return size */
- return 0; /* soft EOF */
+ bsock->msglen = pktsiz; /* signal code */
+ return BNET_SIGNAL; /* signal */
}
/* Make sure the buffer is big enough + one byte for EOS */
bsock->errors++;
Jmsg4(bsock->jcr, M_ERROR, 0, _("Read error from %s:%s:%d: ERR=%s\n"),
bsock->who, bsock->host, bsock->port, bnet_strerror(bsock));
- return -2;
+ return BNET_ERROR;
}
bsock->timer_start = 0; /* clear timer */
bsock->in_msg_no++;
bsock->errors++;
Jmsg5(bsock->jcr, M_ERROR, 0, _("Read expected %d got %d from %s:%s:%d\n"), pktsiz, nbytes,
bsock->who, bsock->host, bsock->port);
- return -2;
+ return BNET_ERROR;
}
/* always add a zero by to properly terminate any
* string that was send to us. Note, we ensured above that the
return nbytes; /* return actual length of message */
}
+
+/*
+ * Return 1 if there are errors on this bsock or it is closed,
+ * i.e. stop communicating on this line.
+ */
+int is_bnet_stop(BSOCK *bsock)
+{
+ return bsock->errors || bsock->terminated;
+}
+
+/*
+ * Return number of errors on socket
+ */
+int is_bnet_error(BSOCK *bsock)
+{
+ return bsock->errors;
+}
+
int bnet_despool(BSOCK *bsock)
{
int32_t pktsiz;
return 1;
}
+
/*
* Send a message over the network. The send consists of
* two network packets. The first is sends a 32 bit integer containing
for (i=0; (bsock = bnet_open(jcr, name, host, service, port)) == NULL; i -= retry_interval) {
Dmsg4(100, "Unable to connect to %s on %s:%d. ERR=%s\n",
name, host, port, strerror(errno));
- if (i <= 0) {
+ if (i < 0) {
i = 60 * 5; /* complain again in 5 minutes */
if (verbose)
Jmsg(jcr, M_WARNING, 0, "Could not connect to %s on %s:%d. ERR=%s\n\
*/
char *bnet_strerror(BSOCK *bsock)
{
- /* ***FIXME*** not thread safe */
return strerror(bsock->b_errno);
}
dbuf_size = size;
if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
- Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc 32K BSOCK data buffer\n"));
+ Jmsg0(bs->jcr, M_FATAL, 0, _("Could not malloc BSOCK data buffer\n"));
return 0;
}
if (rw & BNET_SETBUF_READ) {
{
static char buf[30];
switch (bs->msglen) {
- case BNET_NONO: /* for compatibility */
case BNET_EOD:
return "BNET_EOD"; /* end of data stream */
case BNET_EOD_POLL:
} BSOCK;
/* Signal definitions for use in bnet_sig() */
-#define BNET_NONO 0 /* DO NOT USE, remains for compatibility */
#define BNET_EOD -1 /* End of data stream, new data may follow */
#define BNET_EOD_POLL -2 /* End of data and poll all in one */
#define BNET_STATUS -3 /* Send full status */
#define BNET_SETBUF_READ 1 /* Arg for bnet_set_buffer_size */
#define BNET_SETBUF_WRITE 2 /* Arg for bnet_set_buffer_size */
+/* Return status from bnet_recv() */
+#define BNET_SIGNAL -1
+#define BNET_HARDEOF -2
+#define BNET_ERROR -3
+
/*
* This is the structure of the in memory BPKT
*/
*/
/* base64.c */
-void base64_init (void);
-int to_base64 (intmax_t value, char *where);
-int from_base64 (intmax_t *value, char *where);
-int bin_to_base64 (char *buf, char *bin, int len);
+void base64_init (void);
+int to_base64 (intmax_t value, char *where);
+int from_base64 (intmax_t *value, char *where);
+int bin_to_base64 (char *buf, char *bin, int len);
/* bmisc.c */
-char *bstrncpy (char *dest, char *src, int maxlen);
-void *b_malloc (char *file, int line, size_t size);
+char *bstrncpy (char *dest, char *src, int maxlen);
+void *b_malloc (char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-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);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+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);
/* bnet.c */
-int32_t bnet_recv (BSOCK *bsock);
-int bnet_send (BSOCK *bsock);
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-BSOCK * bnet_connect (void *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-int bnet_wait_data (BSOCK *bsock, int sec);
-void bnet_close (BSOCK *bsock);
-BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK * dup_bsock (BSOCK *bsock);
-void term_bsock (BSOCK *bsock);
-char * bnet_strerror (BSOCK *bsock);
-char * bnet_sig_to_ascii (BSOCK *bsock);
-int bnet_wait_data (BSOCK *bsock, int sec);
-int bnet_despool (BSOCK *bsock);
+int32_t bnet_recv (BSOCK *bsock);
+int bnet_send (BSOCK *bsock);
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+BSOCK * bnet_connect (void *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+int bnet_wait_data (BSOCK *bsock, int sec);
+void bnet_close (BSOCK *bsock);
+BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK * dup_bsock (BSOCK *bsock);
+void term_bsock (BSOCK *bsock);
+char * bnet_strerror (BSOCK *bsock);
+char * bnet_sig_to_ascii (BSOCK *bsock);
+int bnet_wait_data (BSOCK *bsock, int sec);
+int bnet_despool (BSOCK *bsock);
+int is_bnet_stop (BSOCK *bsock);
+int is_bnet_error (BSOCK *bsock);
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password);
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);
+ int key_len, uint8_t *hmac);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start ();
+void daemon_start ();
/* lex.c */
-LEX * lex_close_file (LEX *lf);
-LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int lex_get_char (LEX *lf);
-void lex_unget_char (LEX *lf);
-char * lex_tok_to_str (int token);
-int lex_get_token (LEX *lf, int expect);
+LEX * lex_close_file (LEX *lf);
+LEX * lex_open_file (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int lex_get_char (LEX *lf);
+void lex_unget_char (LEX *lf);
+char * lex_tok_to_str (int token);
+int lex_get_token (LEX *lf, int expect);
/* message.c */
-void my_name_is (int argc, char *argv[], char *name);
-void init_msg (void *jcr, MSGS *msg);
-void term_msg (void);
-void close_msg (void *jcr);
-void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
-void Jmsg (void *jcr, int type, int level, char *fmt, ...);
-void dispatch_message (void *jcr, int type, int level, char *buf);
-void init_console_msg (char *wd);
-void free_msgs_res (MSGS *msgs);
-int open_spool_file (void *jcr, BSOCK *bs);
-int close_spool_file (void *vjcr, BSOCK *bs);
+void my_name_is (int argc, char *argv[], char *name);
+void init_msg (void *jcr, MSGS *msg);
+void term_msg (void);
+void close_msg (void *jcr);
+void add_msg_dest (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void rem_msg_dest (MSGS *msg, int dest, int type, char *where);
+void Jmsg (void *jcr, int type, int level, char *fmt, ...);
+void dispatch_message (void *jcr, int type, int level, char *buf);
+void init_console_msg (char *wd);
+void free_msgs_res (MSGS *msgs);
+int open_spool_file (void *jcr, BSOCK *bs);
+int close_spool_file (void *vjcr, BSOCK *bs);
/* bnet_server.c */
-void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
- void handle_client_request(void *bsock));
-void bnet_server (int port, void handle_client_request(BSOCK *bsock));
-int net_connect (int port);
-BSOCK * bnet_bind (int port);
-BSOCK * bnet_accept (BSOCK *bsock, char *who);
+void bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq,
+ void handle_client_request(void *bsock));
+void bnet_server (int port, void handle_client_request(BSOCK *bsock));
+int net_connect (int port);
+BSOCK * bnet_bind (int port);
+BSOCK * bnet_accept (BSOCK *bsock, char *who);
/* signal.c */
-void init_signals (void terminate(int sig));
-void init_stack_dump (void);
+void init_signals (void terminate(int sig));
+void init_stack_dump (void);
/* util.c */
-void lcase (char *str);
-void bash_spaces (char *str);
-void unbash_spaces (char *str);
-void strip_trailing_junk (char *str);
-void strip_trailing_slashes (char *dir);
-int skip_spaces (char **msg);
-int skip_nonspaces (char **msg);
-int fstrsch (char *a, char *b);
-char * encode_time (time_t time, char *buf);
-char * encode_mode (mode_t mode, char *buf);
-char * edit_uint64_with_commas (uint64_t val, char *buf);
-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);
-void pm_strcat (POOLMEM **pm, char *str);
-void pm_strcpy (POOLMEM **pm, char *str);
-int run_program (char *prog, int wait, POOLMEM *results);
-char * job_type_to_str (int type);
-char * job_status_to_str (int stat);
-char * job_level_to_str (int level);
-void makeSessionKey (char *key, char *seed, int mode);
+void lcase (char *str);
+void bash_spaces (char *str);
+void unbash_spaces (char *str);
+void strip_trailing_junk (char *str);
+void strip_trailing_slashes (char *dir);
+int skip_spaces (char **msg);
+int skip_nonspaces (char **msg);
+int fstrsch (char *a, char *b);
+char * encode_time (time_t time, char *buf);
+char * encode_mode (mode_t mode, char *buf);
+char * edit_uint64_with_commas (uint64_t val, char *buf);
+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);
+void pm_strcat (POOLMEM **pm, char *str);
+void pm_strcpy (POOLMEM **pm, char *str);
+int run_program (char *prog, int wait, POOLMEM *results);
+char * job_type_to_str (int type);
+char * job_status_to_str (int stat);
+char * job_level_to_str (int level);
+void makeSessionKey (char *key, char *seed, int mode);
* info (Info for Storage daemon -- compressed, encryped, ...)
* info is not currently used, so is read, but ignored!
*/
- if ((n=bget_msg(ds)) < 0) {
+ if ((n=bget_msg(ds)) <= 0) {
+ if (n == BNET_SIGNAL && ds->msglen == BNET_EOD) {
+ break; /* end of data */
+ }
Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"),
bnet_strerror(ds));
ok = FALSE;
break;
}
- if (n == 0 || job_cancelled(jcr)) {
- break; /* all done */
- }
sm_check(__FILE__, __LINE__, False);
ds->msg[ds->msglen] = 0;
if (sscanf(ds->msg, "%ld %ld %100s", &file_index, &stream, info) != 3) {
}
sm_check(__FILE__, __LINE__, False);
}
- if (n < 0) {
+ if (is_bnet_error(ds)) {
Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
bnet_strerror(ds));
ok = FALSE;
static char NO_open[] = "3901 Error session already open\n";
static char NOT_opened[] = "3902 Error session not opened\n";
static char OK_end[] = "3000 OK end\n";
-static char OK_close[] = "3000 OK close Volumes = %d\n";
+static char OK_close[] = "3000 OK close Status = %d\n";
static char OK_open[] = "3000 OK open ticket = %d\n";
static char OK_append[] = "3000 OK append data\n";
static char ERROR_append[] = "3903 Error append data\n";
dir->jcr = (void *)jcr;
Dmsg1(120, "Start run Job=%s\n", jcr->Job);
bnet_fsend(dir, Job_start, jcr->Job);
- time(&jcr->start_time);
+ jcr->start_time = time(NULL);
jcr->run_time = jcr->start_time;
jcr->JobStatus = JS_Running;
dir_send_job_status(jcr); /* update director */
for (quit=0; !quit;) {
+ int stat;
/* Read command coming from the File daemon */
- if (bnet_recv(fd) <= 0) {
+ stat = bnet_recv(fd);
+ if (is_bnet_stop(fd)) { /* hardeof or error */
break; /* connection terminated */
}
+ if (stat <= 0) {
+ continue; /* ignore signals and zero length msgs */
+ }
Dmsg1(110, "<filed: %s", fd->msg);
found = 0;
for (i=0; fd_cmds[i].cmd; i++) {
break;
}
}
- time(&jcr->end_time);
+ bnet_sig(fd, BNET_TERMINATE); /* signal to FD job is done */
+ jcr->end_time = time(NULL);
if (!job_cancelled(jcr)) {
jcr->JobStatus = JS_Terminated;
}
bnet_fsend(fd, NOT_opened);
return 0;
}
+ if (jcr->JobStatus != JS_ErrorTerminated) {
+ jcr->JobStatus = JS_Terminated;
+ }
/* Send final statistics to File daemon */
- bnet_fsend(fd, OK_close, jcr->NumVolumes);
+ bnet_fsend(fd, OK_close, jcr->JobStatus);
Dmsg1(160, ">filed: %s\n", fd->msg);
bnet_sig(fd, BNET_EOD); /* send EOD to File daemon */
Dmsg1(110, "Append close session: %s\n", dev_name(jcr->device->dev));
- if (jcr->JobStatus != JS_ErrorTerminated) {
- jcr->JobStatus = JS_Terminated;
- }
jcr->session_opened = FALSE;
return 1;
}
jcr->RestoreBootstrap, strerror(errno));
goto bail_out;
}
- while (bnet_recv(fd) > 0) {
+ while (bnet_recv(fd) >= 0) {
Dmsg1(400, "stored<filed: bootstrap file %s\n", fd->msg);
fputs(fd->msg, bs);
}
/* Initialize FD start condition variable */
if ((errstat = pthread_cond_init(&jcr->job_start_wait, NULL)) != 0) {
- Emsg1(M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
+ Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
jcr->JobStatus = JS_ErrorTerminated;
return 0;
}
Dmsg1(110, "Found Job %s\n", job_name);
if (jcr->authenticated) {
- Pmsg2(000, "Hey!!!! JobId %d Job %s already authenticated.\n",
+ Pmsg2(000, "Hey!!!! JobId %u Job %s already authenticated.\n",
jcr->JobId, jcr->Job);
}
DEVRES *device;
if (bnet_recv(dir) <= 0) {
- Emsg0(M_FATAL, 0, "No Device from Director\n");
+ Jmsg0(jcr, M_FATAL, 0, _("No Device from Director\n"));
return 0;
}
mount_next_vol:
if (retry++ > 5) {
- Jmsg(jcr, M_FATAL, 0, _("Too many errors on device %s.\n"), dev_name(dev));
+ Jmsg(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"), dev_name(dev));
return 0;
}
if (job_cancelled(jcr)) {
}
if (ask && !dir_ask_sysop_to_mount_next_volume(jcr, dev)) {
+ Dmsg0(100, "Error return ask_sysop ...\n");
return 0; /* error return */
}
Dmsg1(100, "want vol=%s\n", jcr->VolumeName);
read_volume:
switch (read_dev_volume_label(jcr, dev, block)) {
case VOL_OK:
- Dmsg1(500, "Vol OK name=%s\n", jcr->VolumeName);
+ Dmsg1(100, "Vol OK name=%s\n", jcr->VolumeName);
memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
if (strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0) {
recycle = 1;
}
break; /* got it */
case VOL_NAME_ERROR:
- Dmsg1(500, "Vol NAME Error Name=%s\n", jcr->VolumeName);
+ Dmsg1(100, "Vol NAME Error Name=%s\n", jcr->VolumeName);
+ /*
+ * OK, we got a different volume mounted. First save the
+ * requested Volume info in the dev structure, then query if
+ * this volume is really OK. If not, put back the desired
+ * volume name and continue.
+ */
+ memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
/* Check if this is a valid Volume in the pool */
strcpy(jcr->VolumeName, dev->VolHdr.VolName);
if (!dir_get_volume_info(jcr, 1)) {
- goto mount_next_vol;
+ Mmsg(&jcr->errmsg, _("Wanted Volume \"%s\".\n\
+ Actual Volume \"%s\" not acceptable.\n"),
+ dev->VolCatInfo.VolCatName, dev->VolHdr.VolName);
+ /* Restore desired volume name, note device info out of sync */
+ memcpy(&jcr->VolCatInfo, &dev->VolCatInfo, sizeof(jcr->VolCatInfo));
+ goto mount_error;
}
- Dmsg1(200, "want new name=%s\n", jcr->VolumeName);
+ Dmsg1(100, "want new name=%s\n", jcr->VolumeName);
memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
break;
Dmsg1(500, "Vol NO_LABEL or IO_ERROR name=%s\n", jcr->VolumeName);
/* If permitted, create a label */
if (dev->capabilities & CAP_LABEL) {
- Dmsg0(190, "Create volume label\n");
+ Dmsg0(100, "Create volume label\n");
if (!write_volume_label_to_dev(jcr, (DEVRES *)dev->device, jcr->VolumeName,
jcr->pool_name)) {
+ Dmsg0(100, "!write_vol_label\n");
goto mount_next_vol;
}
Jmsg(jcr, M_INFO, 0, _("Created Volume label %s on device %s.\n"),
}
/* NOTE! Fall-through wanted. */
default:
+mount_error:
/* Send error message */
Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
if (autochanger) {
- Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume %s not found in slot %d.\n\
+ Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n\
Setting slot to zero in catalog.\n"),
- jcr->VolumeName, jcr->VolCatInfo.Slot);
+ jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
jcr->VolCatInfo.Slot = 0; /* invalidate slot */
dir_update_volume_info(jcr, &jcr->VolCatInfo, 1); /* set slot */
}
+ Dmsg0(100, "Default\n");
goto mount_next_vol;
}
break;
}
/* *****FIXME**** we should do some checking for files too */
if (dev_is_tape(dev)) {
- Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume at file=%d.\n"), dev_file(dev));
/*
* Check if we are positioned on the tape at the same place
* that the database says we should be.
*/
- if (dev->VolCatInfo.VolCatFiles != dev_file(dev) + 1) {
- /* ****FIXME**** this should refuse to write on tape */
- Jmsg(jcr, M_ERROR, 0, _("Hey! Num files mismatch! Volume=%d Catalog=%d\n"),
- dev_file(dev)+1, dev->VolCatInfo.VolCatFiles);
+ if (dev->VolCatInfo.VolCatFiles == dev_file(dev) + 1) {
+ Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume at file=%d.\n"),
+ dev_file(dev));
+ } else {
+ Jmsg(jcr, M_ERROR, 0, _("I canot write on this volume because:\n\
+The number of files mismatch! Volume=%d Catalog=%d\n"),
+ dev_file(dev)+1, dev->VolCatInfo.VolCatFiles);
+ strcpy(dev->VolCatInfo.VolCatStatus, "Error");
+ Dmsg0(100, "dir_update_vol_info. Set Error.\n");
+ dir_update_volume_info(jcr, &dev->VolCatInfo, 0);
+ goto mount_next_vol;
}
}
/* Update Volume Info -- will be written at end of Job */
/* */
#define VERSION "1.27"
#define VSTRING "1"
-#define DATE "23 October 2002"
-#define LSMDATE "23Oct02"
+#define DATE "26 October 2002"
+#define LSMDATE "26Oct02"
/* Debug flags */
#define DEBUG 1