From 83cb47a697fd973b3c8a784a2af82eaa3cb9f9c9 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@91ce42f0-d328-0410-95d8-f526ca767f89> Date: Sat, 11 May 2002 07:50:47 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'Release-1.19a'. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/tags/Release-1.19a@21 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 134 +++++ bacula/Makefile.in | 11 +- bacula/autoconf/config.h.in | 6 - bacula/autoconf/configure.in | 19 +- bacula/configure | 692 +++++++++++++------------- bacula/src/Makefile.in | 1 + bacula/src/bc_types.h | 2 + bacula/src/cats/bdb_list.c | 12 +- bacula/src/cats/bdb_update.c | 4 +- bacula/src/cats/cats.h | 27 +- bacula/src/cats/drop_mysql_tables.in | 7 +- bacula/src/cats/drop_sqlite_tables.in | 7 + bacula/src/cats/make_mysql_tables.in | 23 +- bacula/src/cats/make_sqlite_tables.in | 29 +- bacula/src/cats/mysql.c | 6 + bacula/src/cats/protos.h | 1 + bacula/src/cats/sql.c | 40 +- bacula/src/cats/sql_create.c | 67 ++- bacula/src/cats/sql_delete.c | 115 ++++- bacula/src/cats/sql_get.c | 39 +- bacula/src/cats/sql_list.c | 2 +- bacula/src/cats/sql_update.c | 40 +- bacula/src/cats/sqlite.c | 5 + bacula/src/cats/sqlite.in | 3 +- bacula/src/console.glade | 202 +++++++- bacula/src/console/Makefile.in | 2 +- bacula/src/console/console.c | 135 +++-- bacula/src/console/console_conf.c | 28 ++ bacula/src/console/console_conf.h | 38 +- bacula/src/dird/Makefile.in | 18 +- bacula/src/dird/backup.c | 10 +- bacula/src/dird/bacula-dir.conf.in | 14 +- bacula/src/dird/catreq.c | 32 +- bacula/src/dird/dird.c | 6 +- bacula/src/dird/dird_conf.c | 68 +-- bacula/src/dird/dird_conf.h | 158 +++--- bacula/src/dird/job.c | 3 +- bacula/src/dird/newvol.c | 25 +- bacula/src/dird/protos.h | 10 +- bacula/src/dird/restore.c | 3 + bacula/src/dird/run_conf.c | 2 +- bacula/src/dird/ua.h | 29 +- bacula/src/dird/ua_cmds.c | 145 ++++-- bacula/src/dird/ua_dotcmds.c | 1 - bacula/src/dird/ua_input.c | 26 +- bacula/src/dird/ua_output.c | 81 +-- bacula/src/dird/ua_prune.c | 591 ++++++++++++++++++++++ bacula/src/dird/ua_purge.c | 511 +++++++++++++++++++ bacula/src/dird/ua_run.c | 6 +- bacula/src/dird/ua_select.c | 138 ++++- bacula/src/dird/ua_server.c | 18 +- bacula/src/dird/ua_status.c | 4 +- bacula/src/dird/verify.c | 362 +++++++------- bacula/src/filed/backup.c | 13 - bacula/src/filed/filed.c | 6 +- bacula/src/filed/status.c | 12 +- bacula/src/filed/verify.c | 86 ++-- bacula/src/filed/win32/bin/mount.exe | Bin 0 -> 10240 bytes bacula/src/filed/win32/bin/sh.exe | Bin 0 -> 68608 bytes bacula/src/filed/win32/bin/umount.exe | Bin 0 -> 7680 bytes bacula/src/jcr.h | 1 + bacula/src/lib/Makefile.in | 3 +- bacula/src/lib/jcr.c | 4 +- bacula/src/lib/message.c | 66 +-- bacula/src/lib/message.h | 1 + bacula/src/lib/parse_conf.c | 120 ++--- bacula/src/lib/protos.h | 170 ++++--- bacula/src/lib/signal.c | 3 +- bacula/src/lib/util.c | 121 ++++- bacula/src/lib/watchdog.c | 6 +- bacula/src/stored/askdir.c | 12 +- bacula/src/stored/bextract.c | 2 +- bacula/src/stored/bls.c | 2 +- bacula/src/stored/bscan.c | 2 +- bacula/src/stored/btape.c | 2 +- bacula/src/stored/dev.h | 1 + bacula/src/stored/device.c | 33 +- bacula/src/stored/dircmd.c | 30 +- bacula/src/stored/label.c | 14 +- bacula/src/stored/stored.c | 6 +- bacula/src/version.h | 6 +- 81 files changed, 3393 insertions(+), 1287 deletions(-) create mode 100644 bacula/src/cats/drop_sqlite_tables.in create mode 100644 bacula/src/dird/ua_prune.c create mode 100644 bacula/src/dird/ua_purge.c create mode 100755 bacula/src/filed/win32/bin/mount.exe create mode 100755 bacula/src/filed/win32/bin/sh.exe create mode 100755 bacula/src/filed/win32/bin/umount.exe diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 09d01728a..4123a8262 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,3 +1,137 @@ +2002-05-10 Release 1.19 +- Allow the user to select a new period for pruning. +- Lots of additions to the manual -- prune and purge + commands documented. +- Applied Phil's configure.in fix for --prefix, ... +- Fixed bug found by Phil (patch supplied) in updating + MD5 signatures (revert to 32 bit FileId, move "static" + variables into JCR) (catreq.c fd-cmds.c). +- Reverted to using INTEGER for FileId in make_sql_tables + due to a bug in MySQL. +- Change editing code to %d for FileId. +- Remove sqlite in make distclean in cats directory. +- Remove console.conf in console during make distclean. +- Remove gnome-console.conf during make distclean. +- Remove bacula-dir.conf during make distclean. +- Set default level when using Console if none specified. + Bug reported by Phil. +- A simple . command from Console is ignored. +- Change program named from filed to bacual-fd in winmain.cpp +- Change default config file for Win32 in winmain.cpp +- Free namebuf on early return from find_one.c. Bug reported by Phil. +- Modify testfind.c to dump orphaned buffers. +- Removed terabytes from parse_conf.c because of problems with + older gcc compilers. +- Turn off gnome options in gnome-console by constructing empty argv. +- Fixes to Verify when only MD5 differs. +- Insert 0 for MD5 as default rather than space. +- Allow .messages "transparent" command while reading input + in UserAgent server. +- In dird/verify.c ensure that correct filename is printed if only + the MD5 differs. Minor reindenting caused large diff. +- Delete unused code from backup.c +- In filed/verify.c ensure that same algorithm as backup.c is used + to pass back MD5 signatures -- especially for directories and files + that cannot be read. Change dummy filename from X to *MD5-id*. + This dummy value should never be printed. +- Make gnome-console poll Director every 5 seconds for output. + This means that queued up messages are displayed at reasonable + intervals. Delete some unused code hanging around from the tty + console program. +- Begin implementation of prune commands. +- Add command line history to gnome-console. Not yet saved across sessions. +- Fixed some broken URLs in the manual. +- Added JobId type. +- Wrote first cut of "prune files" and "prune jobs". +- Added command line history to gnome-console 2500 lines max. +- Widened store_time() and associated variables to 64 bits using + new btime_t definition. +- Removed GNOME about box and replaced it with + a somewhat crude Gtk+ about box in the gnome-console. +- Widened StartDay in the Job DB record to be 64 bits. +- Changed edit_uint_ to edit_uint64_ everywhere. Much more + descriptive of what is done. +- Removed most llds and replaced them with %s and edit_uint64. + This makes the code a bit easier to read for beginners. +- Added a btime_t typedef which is 64 bits wide. +- Added most of the code needed to do Purge and Prune of + database. Not yet tested. Please do not use. +- Additional config options for Console. +- Started adding code for Automatic Recycling of Volumes. +- Allow arbitrary length filenames in Verify code. +- Fix incorrect filename in Verify code. +- Significant enhancement to number scanning in config parser. +- Requires initializing MySQL tables, or applying cats/alter.sql + to modify Media table. +- Modified Makefile to printer a much more visible + message if the make ends in error. +- Added the Purge value to the VolStatus in the Media table. + This value is set if the Volume is purged. +- Enhanced the db_delete_media_record() routine to delete + all associated records in the database. +- Modified Console to always write to the variable "output" + rather than stdout. This will permit directing output to a file. +- Enhanced the Console configuration file to have a Console + resource. This will allow us to add an rcfile and history file. +- Modified Find_next_vol in catreq.c to search for "Recycle" + volumes if there are none marked Append. Also made Get_Vol_info + return the VolStatus to the Storage daemon. +- Allow upper/lower case match on job level names. +- Added another warning message to the Console "delete media" command. +- Corrected a number of FileId types from uint64_t to FileId_t in + ua_retention.c. +- In ua server close database before freeing JCR (because pointer is + kept in ua and jcr structures). +- parse all numbers as doubles. Do lots of checking for valid number + formats. Allow numbers in scientific form (e.g. 1.5e+10). +- Remove terabyte modifier as it doesn't work in some compilers. +- Fix bug in handling some modifiers. +- Added all necessary code for Recycle to Storage daemon. A Volume + marked Recycle will now be overwritten. +- Filled out the prune command a bit and did some testing. +- Make console accept redirected input. +- Altered the Table definitions to include Recycle, + FileRetention, JobRetention, and AutoPrune. +- Widened StartDay to 64 bits. +- Use JobId_t in more places. +- Added the new table fields to the database record definitions. +- Changed Recycle from string to a binary quantity. +- Added a Version table with a VersionId to detect. + future changes in the database. This should prevent + a Bacula from working with a database that is not in sync. +- Modify Console to accept input from a file. This will permit + the .read command and allow reading a .rc file. +- Added new retention and recycle variables to the Director's configuration. +- The UA subroutines or commands can now be called from core + code because the output routines detect the absence of a + UA socket and direct output to the Job. +- Added a verbose flage to the ua packet to permit reduction of + output while running a UA command (prune) from a Job. +- Did a fair amount of work on the prune command. Prune Volume now works. +- Purge Volume now works. +- Made last changes for integrating prune and purge commands. +- Add -ltermcap to CONS_LIBS when readline is configured. + More work to be done to search for termcap. +- Added cats/drop_sqlite_tables.in, which will delete the SQLite database. +- Got CWEB working so that we can compile filesys.w and immortal.w +- Modified depkgs to include cweb. +- Note, CWEB is not yet used by the core Bacula code. +- Made cats/alter.sql, which alters an old database to bring it + up to the new format. This only works with MySQL since SQLite does + not have the ALTER SQL command. +- Changed the old StartDay field in the db to be JobTDate, which is + the latest time/date in widened Unix time format that the Job ran. + This value is used when doing pruning. +- Added code in cats/sql.c to verify that the database internal version + corresponds to the db version compiled in Bacula. It is set to 1 currently. +- Lots of changes to cats to bring the SQL up to date with the new + retention period changes. +- Added Console command code to permit changing a Volume's retention period. +- Removed old code that used date_encode() and replaced it with widened + Unix time(). +- Started modifying Message resource scanner so that we can have multiple + message resources. Much more work to be done. +- Moved scanning for time into new library routine string_to_btime(). 2002-04-22 Release 1.18 - Applied Phil's configure.in fix for --prefix, ... diff --git a/bacula/Makefile.in b/bacula/Makefile.in index 2796af378..723f1e48e 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -1,4 +1,5 @@ # +# $Id$ # @MCOMMON@ @@ -32,7 +33,10 @@ MKDIR = $(srcdir)/autoconf/mkinstalldirs all: Makefile @for I in ${subdirs}; \ - do (cd $$I; echo "==>Entering directory `pwd`"; $(MAKE) $@ || exit 1); done + do (cd $$I; echo "==>Entering directory `pwd`"; \ + $(MAKE) $@ || (echo ""; echo ""; echo " ====== Error in `pwd` ======"; \ + echo ""; echo "";)); \ + done depend: @for I in ${subdirs}; \ @@ -40,7 +44,10 @@ depend: bacula-fd: Makefile @for I in ${FDsubdirs}; \ - do (cd $$I; echo "==>Entering directory `pwd`"; $(MAKE) all || exit 1); done + do (cd $$I; echo "==>Entering directory `pwd`"; \ + $(MAKE) all || (echo ""; echo ""; echo " ====== Error in `pwd` ======"; \ + echo ""; echo "";)); \ + done #------------------------------------------------------------------------- configure: autoconf/configure.in autoconf/aclocal.m4 autoconf/acconfig.h autoconf/config.h.in diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index cc1892aab..66845723e 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -426,12 +426,6 @@ /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H -/* Define if you have the header file. */ -#undef HAVE_TERMCAP_H - -/* Define if you have the header file. */ -#undef HAVE_TERMIO_H - /* Define if you have the header file. */ #undef HAVE_TERMIOS_H diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index 179c880b6..d49de02a5 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -212,7 +212,7 @@ if test x$support_readline = xyes; then AC_CHECK_HEADER($with_readline/readline.h, [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_READLINE) - CONS_LIBS="-lreadline" + CONS_LIBS="-lreadline -ltermcap" got_readline="yes" ], [ AC_MSG_ERROR([*** readline library missing]) @@ -227,14 +227,14 @@ if test x$support_readline = xyes; then AC_DEFINE(HAVE_READLINE) got_readline="yes" CONS_INC="-I/usr/include/readline" - CONS_LIBS="-lreadline" + CONS_LIBS="-lreadline -ltermcap" ], [ # Did not find starndard library, so user our own AC_MSG_RESULT(yes) AC_DEFINE(HAVE_READLINE) got_readline="yes" CONS_INC="-I${TOP_DIR}/depkgs" - CONS_LIBS="-lreadline -lhistory" + CONS_LIBS="-lreadline -lhistory -ltermcap" CONS_LDFLAGS="-L${TOP_DIR}/depkgs/readline" READLINE_SRC="${TOP_DIR}/depkgs/readline" ]) @@ -265,12 +265,7 @@ AC_CHECK_FUNC(getopt_long, AC_DEFINE(HAVE_GETOPT_LONG)) AC_FUNC_STRCOLL AC_CHECK_HEADERS(varargs.h \ - sys/ptem.h sys/pte.h sys/stream.h \ - termcap.h termio.h ) - -TERMCAP_LIB=-ltermcap -AC_SUBST(TERMCAP_LIB) - + sys/ptem.h sys/pte.h sys/stream.h) # End of readline stuff # ----------------------------------------------------------------------- @@ -339,6 +334,7 @@ AC_SUBST(GMP_SRC) # Check for CWEB support/directory # --------------------------------------------------- CWEB_SRC= +CWEB=/bin local_cweb="no" AC_ARG_WITH(cweb, [ --with-cweb[=DIR] Specify cweb library directory], @@ -378,6 +374,7 @@ AC_ARG_WITH(cweb, AC_DEFINE(HAVE_CWEB) got_cweb="yes" local_cweb="yes" + CWEB=${TOP_DIR}/depkgs/cweb CWEB_INC="-I${TOP_DIR}/depkgs/cweb" CWEB_LIBS="-lcweb" CWEB_LDFLAGS="-L${TOP_DIR}/depkgs/cweb" @@ -385,6 +382,7 @@ AC_ARG_WITH(cweb, ]) ] ) +AC_SUBST(CWEB) AC_SUBST(CWEB_INC) AC_SUBST(CWEB_LIBS) AC_SUBST(CWEB_LDFLAGS) @@ -1183,6 +1181,7 @@ AC_OUTPUT([autoconf/Make.common \ src/cats/create_mysql_database \ src/cats/grant_mysql_privileges \ src/cats/make_sqlite_tables \ + src/cats/drop_sqlite_tables \ src/cats/sqlite \ src/findlib/Makefile \ $PFILES ], @@ -1199,7 +1198,7 @@ chmod 755 src/cats/make_mysql_tables src/cats/drop_mysql_tables chmod 755 src/cats/make_test_tables src/cats/drop_test_tables chmod 755 src/cats/create_mysql_database chmod 755 src/cats/grant_mysql_privileges -chmod 755 src/cats/make_sqlite_tables +chmod 755 src/cats/make_sqlite_tables src/cats/drop_sqlite_tables chmod 755 src/cats/sqlite diff --git a/bacula/configure b/bacula/configure index 2707774c1..5268fbf4f 100755 --- a/bacula/configure +++ b/bacula/configure @@ -2680,7 +2680,7 @@ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then #define HAVE_READLINE 1 EOF - CONS_LIBS="-lreadline" + CONS_LIBS="-lreadline -ltermcap" got_readline="yes" else @@ -2731,7 +2731,7 @@ EOF got_readline="yes" CONS_INC="-I/usr/include/readline" - CONS_LIBS="-lreadline" + CONS_LIBS="-lreadline -ltermcap" else echo "$ac_t""no" 1>&6 @@ -2744,7 +2744,7 @@ EOF got_readline="yes" CONS_INC="-I${TOP_DIR}/depkgs" - CONS_LIBS="-lreadline -lhistory" + CONS_LIBS="-lreadline -lhistory -ltermcap" CONS_LDFLAGS="-L${TOP_DIR}/depkgs/readline" READLINE_SRC="${TOP_DIR}/depkgs/readline" @@ -3102,22 +3102,21 @@ fi for ac_hdr in varargs.h \ - sys/ptem.h sys/pte.h sys/stream.h \ - termcap.h termio.h + sys/ptem.h sys/pte.h sys/stream.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:3111: checking for $ac_hdr" >&5 +echo "configure:3110: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3121: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3120: \"$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* @@ -3142,11 +3141,7 @@ else echo "$ac_t""no" 1>&6 fi done - - -TERMCAP_LIB=-ltermcap - - + # End of readline stuff # ----------------------------------------------------------------------- @@ -3173,17 +3168,17 @@ if test "${with_gmp+set}" = set; then fi ac_safe=`echo "$with_gmp/gmp.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $with_gmp/gmp.h""... $ac_c" 1>&6 -echo "configure:3177: checking for $with_gmp/gmp.h" >&5 +echo "configure:3172: checking for $with_gmp/gmp.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3187: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3182: \"$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* @@ -3222,17 +3217,17 @@ else # check for standard gmp library ac_safe=`echo "/usr/include/gmp.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for /usr/include/gmp.h""... $ac_c" 1>&6 -echo "configure:3226: checking for /usr/include/gmp.h" >&5 +echo "configure:3221: checking for /usr/include/gmp.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3236: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3231: \"$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* @@ -3292,6 +3287,7 @@ fi # Check for CWEB support/directory # --------------------------------------------------- CWEB_SRC= +CWEB=/bin local_cweb="no" # Check whether --with-cweb or --without-cweb was given. if test "${with_cweb+set}" = set; then @@ -3309,17 +3305,17 @@ if test "${with_cweb+set}" = set; then fi ac_safe=`echo "$with_cweb/cweb.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $with_cweb/cweb.h""... $ac_c" 1>&6 -echo "configure:3313: checking for $with_cweb/cweb.h" >&5 +echo "configure:3309: checking for $with_cweb/cweb.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3323: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3319: \"$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* @@ -3358,17 +3354,17 @@ else # check for standard cweb library ac_safe=`echo "/usr/include/cweb.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for /usr/include/cweb.h""... $ac_c" 1>&6 -echo "configure:3362: checking for /usr/include/cweb.h" >&5 +echo "configure:3358: checking for /usr/include/cweb.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3372: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3368: \"$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* @@ -3404,6 +3400,7 @@ EOF got_cweb="yes" local_cweb="yes" + CWEB=${TOP_DIR}/depkgs/cweb CWEB_INC="-I${TOP_DIR}/depkgs/cweb" CWEB_LIBS="-lcweb" CWEB_LDFLAGS="-L${TOP_DIR}/depkgs/cweb" @@ -3420,6 +3417,7 @@ fi + # End of CWEB stuff # ----------------------------------------------------------------------- @@ -3437,9 +3435,9 @@ if test "${with_tcp_wrappers+set}" = set; then saved_LIBS="$LIBS" LIBS="$LIBS -lwrap -lnsl" echo $ac_n "checking for libwrap""... $ac_c" 1>&6 -echo "configure:3441: checking for libwrap" >&5 +echo "configure:3439: checking for libwrap" >&5 cat > conftest.$ac_ext < int deny_severity = 0; @@ -3449,7 +3447,7 @@ int main() { hosts_access(req); ; return 0; } EOF -if { (eval echo configure:3453: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6 @@ -3716,7 +3714,7 @@ fi have_db=no db_name=none echo $ac_n "checking for MySQL support""... $ac_c" 1>&6 -echo "configure:3720: checking for MySQL support" >&5 +echo "configure:3718: checking for MySQL support" >&5 # Check whether --with-mysql or --without-mysql was given. if test "${with_mysql+set}" = set; then withval="$with_mysql" @@ -3798,7 +3796,7 @@ fi have_db=no db_name=none echo $ac_n "checking for SQLite support""... $ac_c" 1>&6 -echo "configure:3802: checking for SQLite support" >&5 +echo "configure:3800: checking for SQLite support" >&5 # Check whether --with-sqlite or --without-sqlite was given. if test "${with_sqlite+set}" = set; then withval="$with_sqlite" @@ -3871,19 +3869,19 @@ fi echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6 -echo "configure:3875: checking for mingw32 environment" >&5 +echo "configure:3873: checking for mingw32 environment" >&5 if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3885: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else @@ -3902,7 +3900,7 @@ test "$ac_cv_mingw32" = yes && MINGW32=yes echo $ac_n "checking for executable suffix""... $ac_c" 1>&6 -echo "configure:3906: checking for executable suffix" >&5 +echo "configure:3904: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3912,7 +3910,7 @@ else rm -f conftest* echo 'int main () { return 0; }' > conftest.$ac_ext ac_cv_exeext= - if { (eval echo configure:3916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + if { (eval echo configure:3914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; @@ -3940,7 +3938,7 @@ ac_exeext=$EXEEXT # Uses ac_ vars as temps to allow command line to override cache and checks. # --without-x overrides everything else, but does not touch the cache. echo $ac_n "checking for X""... $ac_c" 1>&6 -echo "configure:3944: checking for X" >&5 +echo "configure:3942: checking for X" >&5 # Check whether --with-x or --without-x was given. if test "${with_x+set}" = set; then @@ -4002,12 +4000,12 @@ if test "$ac_x_includes" = NO; then # First, try using that file with no special directory specified. cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4011: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4009: \"$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* @@ -4076,14 +4074,14 @@ if test "$ac_x_libraries" = NO; then ac_save_LIBS="$LIBS" LIBS="-l$x_direct_test_library $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4085: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBS="$ac_save_LIBS" # We can link X programs with no special library path. @@ -4189,17 +4187,17 @@ else case "`(uname -sr) 2>/dev/null`" in "SunOS 5"*) echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6 -echo "configure:4193: checking whether -R must be followed by a space" >&5 +echo "configure:4191: checking whether -R must be followed by a space" >&5 ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4201: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_nospace=yes else @@ -4215,14 +4213,14 @@ rm -f conftest* else LIBS="$ac_xsave_LIBS -R $x_libraries" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4224: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_R_space=yes else @@ -4254,7 +4252,7 @@ rm -f conftest* # libraries were built with DECnet support. And karl@cs.umb.edu says # the Alpha needs dnet_stub (dnet does not exist). echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6 -echo "configure:4258: checking for dnet_ntoa in -ldnet" >&5 +echo "configure:4256: checking for dnet_ntoa in -ldnet" >&5 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4262,7 +4260,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4275: \"$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 @@ -4295,7 +4293,7 @@ fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6 -echo "configure:4299: checking for dnet_ntoa in -ldnet_stub" >&5 +echo "configure:4297: checking for dnet_ntoa in -ldnet_stub" >&5 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4303,7 +4301,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldnet_stub $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4316: \"$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 @@ -4343,12 +4341,12 @@ fi # The nsl library prevents programs from opening the X display # on Irix 5.2, according to dickey@clark.net. echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:4347: checking for gethostbyname" >&5 +echo "configure:4345: checking for gethostbyname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else @@ -4392,7 +4390,7 @@ fi if test $ac_cv_func_gethostbyname = no; then echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:4396: checking for gethostbyname in -lnsl" >&5 +echo "configure:4394: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4400,7 +4398,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4413: \"$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 @@ -4441,12 +4439,12 @@ fi # -lsocket must be given before -lnsl if both are needed. # We assume that if connect needs -lnsl, so does gethostbyname. echo $ac_n "checking for connect""... $ac_c" 1>&6 -echo "configure:4445: checking for connect" >&5 +echo "configure:4443: checking for connect" >&5 if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4471: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_connect=yes" else @@ -4490,7 +4488,7 @@ fi if test $ac_cv_func_connect = no; then echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6 -echo "configure:4494: checking for connect in -lsocket" >&5 +echo "configure:4492: checking for connect in -lsocket" >&5 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4498,7 +4496,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4511: \"$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 @@ -4533,12 +4531,12 @@ fi # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX. echo $ac_n "checking for remove""... $ac_c" 1>&6 -echo "configure:4537: checking for remove" >&5 +echo "configure:4535: checking for remove" >&5 if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4563: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_remove=yes" else @@ -4582,7 +4580,7 @@ fi if test $ac_cv_func_remove = no; then echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6 -echo "configure:4586: checking for remove in -lposix" >&5 +echo "configure:4584: checking for remove in -lposix" >&5 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4590,7 +4588,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lposix $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4603: \"$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 @@ -4625,12 +4623,12 @@ fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. echo $ac_n "checking for shmat""... $ac_c" 1>&6 -echo "configure:4629: checking for shmat" >&5 +echo "configure:4627: checking for shmat" >&5 if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4655: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_shmat=yes" else @@ -4674,7 +4672,7 @@ fi if test $ac_cv_func_shmat = no; then echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6 -echo "configure:4678: checking for shmat in -lipc" >&5 +echo "configure:4676: checking for shmat in -lipc" >&5 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4682,7 +4680,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lipc $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4695: \"$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 @@ -4726,7 +4724,7 @@ fi # libraries we check for below, so use a different variable. # --interran@uluru.Stanford.EDU, kb@cs.umb.edu. echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6 -echo "configure:4730: checking for IceConnectionNumber in -lICE" >&5 +echo "configure:4728: checking for IceConnectionNumber in -lICE" >&5 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -4734,7 +4732,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4747: \"$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 @@ -4790,17 +4788,17 @@ for ac_hdr in \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4794: checking for $ac_hdr" >&5 +echo "configure:4792: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4804: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4802: \"$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* @@ -4827,12 +4825,12 @@ fi done echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:4831: checking for ANSI C header files" >&5 +echo "configure:4829: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -4840,7 +4838,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4844: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4842: \"$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* @@ -4857,7 +4855,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -4875,7 +4873,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -4896,7 +4894,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -4907,7 +4905,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:4911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -4931,19 +4929,19 @@ EOF fi echo $ac_n "checking whether sys/types.h defines makedev""... $ac_c" 1>&6 -echo "configure:4935: checking whether sys/types.h defines makedev" >&5 +echo "configure:4933: checking whether sys/types.h defines makedev" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_types_h_makedev'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { return makedev(0, 0); ; return 0; } EOF -if { (eval echo configure:4947: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:4945: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_sys_types_h_makedev=yes else @@ -4961,17 +4959,17 @@ echo "$ac_t""$ac_cv_header_sys_types_h_makedev" 1>&6 if test $ac_cv_header_sys_types_h_makedev = no; then ac_safe=`echo "sys/mkdev.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/mkdev.h""... $ac_c" 1>&6 -echo "configure:4965: checking for sys/mkdev.h" >&5 +echo "configure:4963: checking for sys/mkdev.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4975: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4973: \"$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* @@ -4999,17 +4997,17 @@ fi if test $ac_cv_header_sys_mkdev_h = no; then ac_safe=`echo "sys/sysmacros.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for sys/sysmacros.h""... $ac_c" 1>&6 -echo "configure:5003: checking for sys/sysmacros.h" >&5 +echo "configure:5001: checking for sys/sysmacros.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5013: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5011: \"$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* @@ -5041,12 +5039,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 -echo "configure:5045: checking for $ac_hdr that defines DIR" >&5 +echo "configure:5043: checking for $ac_hdr that defines DIR" >&5 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_hdr> @@ -5054,7 +5052,7 @@ int main() { DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:5058: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5056: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -5079,7 +5077,7 @@ done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 -echo "configure:5083: checking for opendir in -ldir" >&5 +echo "configure:5081: checking for opendir in -ldir" >&5 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5087,7 +5085,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldir $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5100: \"$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 @@ -5120,7 +5118,7 @@ fi else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:5124: checking for opendir in -lx" >&5 +echo "configure:5122: checking for opendir in -lx" >&5 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -5128,7 +5126,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5141: \"$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 @@ -5162,12 +5160,12 @@ fi fi echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:5166: checking whether stat file-mode macros are broken" >&5 +echo "configure:5164: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5218,12 +5216,12 @@ EOF fi echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 -echo "configure:5222: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo "configure:5220: checking for sys/wait.h that is POSIX.1 compatible" >&5 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5239,7 +5237,7 @@ wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } EOF -if { (eval echo configure:5243: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5241: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -5260,12 +5258,12 @@ EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:5264: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:5262: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5274,7 +5272,7 @@ int main() { struct tm *tp; ; return 0; } EOF -if { (eval echo configure:5278: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -5295,12 +5293,12 @@ EOF fi echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6 -echo "configure:5299: checking for st_blksize in struct stat" >&5 +echo "configure:5297: checking for st_blksize in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5308,7 +5306,7 @@ int main() { struct stat s; s.st_blksize; ; return 0; } EOF -if { (eval echo configure:5312: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5310: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blksize=yes else @@ -5329,12 +5327,12 @@ EOF fi echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6 -echo "configure:5333: checking for st_blocks in struct stat" >&5 +echo "configure:5331: checking for st_blocks in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5342,7 +5340,7 @@ int main() { struct stat s; s.st_blocks; ; return 0; } EOF -if { (eval echo configure:5346: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5344: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blocks=yes else @@ -5365,12 +5363,12 @@ else fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:5369: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:5367: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5378,7 +5376,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:5382: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5380: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -5399,12 +5397,12 @@ EOF fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 -echo "configure:5403: checking for tm_zone in struct tm" >&5 +echo "configure:5401: checking for tm_zone in struct tm" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include <$ac_cv_struct_tm> @@ -5412,7 +5410,7 @@ int main() { struct tm tm; tm.tm_zone; ; return 0; } EOF -if { (eval echo configure:5416: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5414: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else @@ -5432,12 +5430,12 @@ EOF else echo $ac_n "checking for tzname""... $ac_c" 1>&6 -echo "configure:5436: checking for tzname" >&5 +echo "configure:5434: checking for tzname" >&5 if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #ifndef tzname /* For SGI. */ @@ -5447,7 +5445,7 @@ int main() { atoi(*tzname); ; return 0; } EOF -if { (eval echo configure:5451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5449: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_var_tzname=yes else @@ -5474,12 +5472,12 @@ fi # be POSIX, POSIX_C, ALL, HPUX or whatever, depending on the machine. echo $ac_n "checking for utime.h""... $ac_c" 1>&6 -echo "configure:5478: checking for utime.h" >&5 +echo "configure:5476: checking for utime.h" >&5 if eval "test \"`echo '$''{'tar_cv_header_utime_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -5488,7 +5486,7 @@ int main() { struct utimbuf foo ; return 0; } EOF -if { (eval echo configure:5492: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5490: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* tar_cv_header_utime_h=yes else @@ -5507,12 +5505,12 @@ EOF echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:5511: checking for working const" >&5 +echo "configure:5509: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5563: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -5584,17 +5582,17 @@ fi echo $ac_n "checking how to get filesystem type""... $ac_c" 1>&6 -echo "configure:5588: checking how to get filesystem type" >&5 +echo "configure:5586: checking how to get filesystem type" >&5 fstype=no # The order of these tests is important. cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5598: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5596: \"$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* @@ -5610,13 +5608,13 @@ fi rm -f conftest* if test $fstype = no; then cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5620: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5618: \"$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* @@ -5633,13 +5631,13 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5643: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5641: \"$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* @@ -5656,12 +5654,12 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5665: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5663: \"$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* @@ -5678,7 +5676,7 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < EOF @@ -5695,13 +5693,13 @@ rm -f conftest* fi if test $fstype = no; then cat > conftest.$ac_ext < #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5705: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5703: \"$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* @@ -5719,12 +5717,12 @@ fi echo "$ac_t""$fstype" 1>&6 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:5723: checking return type of signal handlers" >&5 +echo "configure:5721: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5741,7 +5739,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:5745: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5743: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -5761,13 +5759,13 @@ EOF echo $ac_n "checking for type of signal functions""... $ac_c" 1>&6 -echo "configure:5765: checking for type of signal functions" >&5 +echo "configure:5763: checking for type of signal functions" >&5 if eval "test \"`echo '$''{'bash_cv_signal_vintage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -5780,7 +5778,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:5784: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* bash_cv_signal_vintage=posix else @@ -5789,7 +5787,7 @@ else rm -rf conftest* cat > conftest.$ac_ext < int main() { @@ -5799,7 +5797,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:5803: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* bash_cv_signal_vintage=4.2bsd else @@ -5808,7 +5806,7 @@ else rm -rf conftest* cat > conftest.$ac_ext < @@ -5821,7 +5819,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:5825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5823: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* bash_cv_signal_vintage=svr3 else @@ -5860,12 +5858,12 @@ EOF fi echo $ac_n "checking for mode_t""... $ac_c" 1>&6 -echo "configure:5864: checking for mode_t" >&5 +echo "configure:5862: checking for mode_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -5893,12 +5891,12 @@ EOF fi echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:5897: checking for uid_t in sys/types.h" >&5 +echo "configure:5895: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -5927,12 +5925,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:5931: checking for size_t" >&5 +echo "configure:5929: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -5960,12 +5958,12 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:5964: checking for pid_t" >&5 +echo "configure:5962: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -5993,12 +5991,12 @@ EOF fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 -echo "configure:5997: checking for off_t" >&5 +echo "configure:5995: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6026,12 +6024,12 @@ EOF fi echo $ac_n "checking for ino_t""... $ac_c" 1>&6 -echo "configure:6030: checking for ino_t" >&5 +echo "configure:6028: checking for ino_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_ino_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6059,12 +6057,12 @@ EOF fi echo $ac_n "checking for dev_t""... $ac_c" 1>&6 -echo "configure:6063: checking for dev_t" >&5 +echo "configure:6061: checking for dev_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_dev_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6092,12 +6090,12 @@ EOF fi echo $ac_n "checking for daddr_t""... $ac_c" 1>&6 -echo "configure:6096: checking for daddr_t" >&5 +echo "configure:6094: checking for daddr_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_daddr_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6125,12 +6123,12 @@ EOF fi echo $ac_n "checking for major_t""... $ac_c" 1>&6 -echo "configure:6129: checking for major_t" >&5 +echo "configure:6127: checking for major_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_major_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6158,12 +6156,12 @@ EOF fi echo $ac_n "checking for minor_t""... $ac_c" 1>&6 -echo "configure:6162: checking for minor_t" >&5 +echo "configure:6160: checking for minor_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_minor_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6191,12 +6189,12 @@ EOF fi echo $ac_n "checking for ssize_t""... $ac_c" 1>&6 -echo "configure:6195: checking for ssize_t" >&5 +echo "configure:6193: checking for ssize_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -6224,12 +6222,12 @@ EOF fi echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6 -echo "configure:6228: checking for st_blocks in struct stat" >&5 +echo "configure:6226: checking for st_blocks in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6237,7 +6235,7 @@ int main() { struct stat s; s.st_blocks; ; return 0; } EOF -if { (eval echo configure:6241: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6239: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blocks=yes else @@ -6260,12 +6258,12 @@ else fi echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6 -echo "configure:6264: checking for st_rdev in struct stat" >&5 +echo "configure:6262: checking for st_rdev in struct stat" >&5 if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6273,7 +6271,7 @@ int main() { struct stat s; s.st_rdev; ; return 0; } EOF -if { (eval echo configure:6277: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6275: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_rdev=yes else @@ -6294,12 +6292,12 @@ EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:6298: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:6296: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6307,7 +6305,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:6311: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6309: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -6328,12 +6326,12 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:6332: checking for working const" >&5 +echo "configure:6330: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6384: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -6405,7 +6403,7 @@ fi echo $ac_n "checking size of char""... $ac_c" 1>&6 -echo "configure:6409: checking size of char" >&5 +echo "configure:6407: checking size of char" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_char'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6413,7 +6411,7 @@ else ac_cv_sizeof_char=1 else cat > conftest.$ac_ext < main() @@ -6424,7 +6422,7 @@ main() exit(0); } EOF -if { (eval echo configure:6428: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6426: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_char=`cat conftestval` else @@ -6444,7 +6442,7 @@ EOF echo $ac_n "checking size of short int""... $ac_c" 1>&6 -echo "configure:6448: checking size of short int" >&5 +echo "configure:6446: checking size of short int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6452,7 +6450,7 @@ else ac_cv_sizeof_short_int=2 else cat > conftest.$ac_ext < main() @@ -6463,7 +6461,7 @@ main() exit(0); } EOF -if { (eval echo configure:6467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_short_int=`cat conftestval` else @@ -6483,7 +6481,7 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:6487: checking size of int" >&5 +echo "configure:6485: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6491,7 +6489,7 @@ else ac_cv_sizeof_int=4 else cat > conftest.$ac_ext < main() @@ -6502,7 +6500,7 @@ main() exit(0); } EOF -if { (eval echo configure:6506: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int=`cat conftestval` else @@ -6522,7 +6520,7 @@ EOF echo $ac_n "checking size of long int""... $ac_c" 1>&6 -echo "configure:6526: checking size of long int" >&5 +echo "configure:6524: checking size of long int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6530,7 +6528,7 @@ else ac_cv_sizeof_long_int=4 else cat > conftest.$ac_ext < main() @@ -6541,7 +6539,7 @@ main() exit(0); } EOF -if { (eval echo configure:6545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_int=`cat conftestval` else @@ -6561,7 +6559,7 @@ EOF echo $ac_n "checking size of long long int""... $ac_c" 1>&6 -echo "configure:6565: checking size of long long int" >&5 +echo "configure:6563: checking size of long long int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6569,7 +6567,7 @@ else ac_cv_sizeof_long_long_int=8 else cat > conftest.$ac_ext < main() @@ -6580,7 +6578,7 @@ main() exit(0); } EOF -if { (eval echo configure:6584: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_long_int=`cat conftestval` else @@ -6600,7 +6598,7 @@ EOF echo $ac_n "checking size of int *""... $ac_c" 1>&6 -echo "configure:6604: checking size of int *" >&5 +echo "configure:6602: checking size of int *" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int_p'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6608,7 +6606,7 @@ else ac_cv_sizeof_int_p=4 else cat > conftest.$ac_ext < main() @@ -6619,7 +6617,7 @@ main() exit(0); } EOF -if { (eval echo configure:6623: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int_p=`cat conftestval` else @@ -6641,20 +6639,20 @@ EOF # Check for sys/types.h types echo $ac_n "checking for u_int type""... $ac_c" 1>&6 -echo "configure:6645: checking for u_int type" >&5 +echo "configure:6643: checking for u_int type" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_int a; a = 1; ; return 0; } EOF -if { (eval echo configure:6658: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6656: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_int="yes" else @@ -6678,20 +6676,20 @@ EOF fi echo $ac_n "checking for intmax_t type""... $ac_c" 1>&6 -echo "configure:6682: checking for intmax_t type" >&5 +echo "configure:6680: checking for intmax_t type" >&5 if eval "test \"`echo '$''{'ac_cv_have_intmax_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:6695: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6693: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_intmax_t="yes" else @@ -6700,14 +6698,14 @@ else rm -rf conftest* cat > conftest.$ac_ext < int main() { intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:6711: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6709: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_intmax_t="yes" else @@ -6737,20 +6735,20 @@ fi echo $ac_n "checking for u_intmax_t type""... $ac_c" 1>&6 -echo "configure:6741: checking for u_intmax_t type" >&5 +echo "configure:6739: checking for u_intmax_t type" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_intmax_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:6754: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6752: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_intmax_t="yes" else @@ -6759,14 +6757,14 @@ else rm -rf conftest* cat > conftest.$ac_ext < int main() { u_intmax_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:6770: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6768: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_intmax_t="yes" else @@ -6795,20 +6793,20 @@ fi echo $ac_n "checking for intXX_t types""... $ac_c" 1>&6 -echo "configure:6799: checking for intXX_t types" >&5 +echo "configure:6797: checking for intXX_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_intxx_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int8_t a; int16_t b; int32_t c; a = b = c = 1; ; return 0; } EOF -if { (eval echo configure:6812: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6810: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_intxx_t="yes" else @@ -6832,20 +6830,20 @@ EOF fi echo $ac_n "checking for int64_t type""... $ac_c" 1>&6 -echo "configure:6836: checking for int64_t type" >&5 +echo "configure:6834: checking for int64_t type" >&5 if eval "test \"`echo '$''{'ac_cv_have_int64_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { int64_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:6849: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6847: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_int64_t="yes" else @@ -6869,20 +6867,20 @@ EOF fi echo $ac_n "checking for u_intXX_t types""... $ac_c" 1>&6 -echo "configure:6873: checking for u_intXX_t types" >&5 +echo "configure:6871: checking for u_intXX_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_intxx_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1; ; return 0; } EOF -if { (eval echo configure:6886: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6884: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_intxx_t="yes" else @@ -6906,20 +6904,20 @@ EOF fi echo $ac_n "checking for u_int64_t types""... $ac_c" 1>&6 -echo "configure:6910: checking for u_int64_t types" >&5 +echo "configure:6908: checking for u_int64_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_u_int64_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { u_int64_t a; a = 1; ; return 0; } EOF -if { (eval echo configure:6923: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6921: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_u_int64_t="yes" else @@ -6946,9 +6944,9 @@ if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then echo $ac_n "checking for intXX_t and u_intXX_t types in sys/bitypes.h""... $ac_c" 1>&6 -echo "configure:6950: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 +echo "configure:6948: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5 cat > conftest.$ac_ext < int main() { @@ -6957,7 +6955,7 @@ int main() { a = b = c = e = f = g = 1; ; return 0; } EOF -if { (eval echo configure:6961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6959: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_U_INTXX_T 1 @@ -6984,13 +6982,13 @@ fi if test -z "$have_u_intxx_t" ; then echo $ac_n "checking for uintXX_t types""... $ac_c" 1>&6 -echo "configure:6988: checking for uintXX_t types" >&5 +echo "configure:6986: checking for uintXX_t types" >&5 if eval "test \"`echo '$''{'ac_cv_have_uintxx_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { @@ -6998,7 +6996,7 @@ int main() { uint32_t c; a = b = c = 1; ; return 0; } EOF -if { (eval echo configure:7002: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:7000: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_have_uintxx_t="yes" else @@ -7038,12 +7036,12 @@ for ac_func in \ do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7042: checking for $ac_func" >&5 +echo "configure:7040: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7068: \"$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 @@ -7096,12 +7094,12 @@ done for ac_func in fchdir do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7100: checking for $ac_func" >&5 +echo "configure:7098: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7126: \"$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 @@ -7155,12 +7153,12 @@ done for ac_func in snprintf vsnprintf do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7159: checking for $ac_func" >&5 +echo "configure:7157: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7185: \"$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 @@ -7211,12 +7209,12 @@ done for ac_func in localtime_r do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7215: checking for $ac_func" >&5 +echo "configure:7213: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7241: \"$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 @@ -7270,12 +7268,12 @@ done for ac_func in readdir_r do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7274: checking for $ac_func" >&5 +echo "configure:7272: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7300: \"$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 @@ -7328,12 +7326,12 @@ done # Find where sockets are (especially for Solaris) echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:7332: checking for socket" >&5 +echo "configure:7330: checking for socket" >&5 if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7358: \"$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 @@ -7374,7 +7372,7 @@ if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for socket in -lxnet""... $ac_c" 1>&6 -echo "configure:7378: checking for socket in -lxnet" >&5 +echo "configure:7376: 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 @@ -7382,7 +7380,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lxnet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7395: \"$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 @@ -7421,7 +7419,7 @@ else fi echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:7425: checking for socket in -lsocket" >&5 +echo "configure:7423: 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 @@ -7429,7 +7427,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7442: \"$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 @@ -7468,7 +7466,7 @@ else fi echo $ac_n "checking for socket in -linet""... $ac_c" 1>&6 -echo "configure:7472: checking for socket in -linet" >&5 +echo "configure:7470: 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 @@ -7476,7 +7474,7 @@ else ac_save_LIBS="$LIBS" LIBS="-linet $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7489: \"$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 @@ -7519,12 +7517,12 @@ fi # If resolver functions are not in libc check for -lnsl or -lresolv. echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:7523: checking for gethostbyname" >&5 +echo "configure:7521: checking for gethostbyname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else @@ -7565,7 +7563,7 @@ if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:7569: checking for gethostbyname in -lnsl" >&5 +echo "configure:7567: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -7573,7 +7571,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7586: \"$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 @@ -7612,7 +7610,7 @@ else fi echo $ac_n "checking for gethostbyname in -lresolv""... $ac_c" 1>&6 -echo "configure:7616: checking for gethostbyname in -lresolv" >&5 +echo "configure:7614: checking for gethostbyname in -lresolv" >&5 ac_lib_var=`echo resolv'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -7620,7 +7618,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7633: \"$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 @@ -7663,12 +7661,12 @@ fi echo $ac_n "checking for strftime""... $ac_c" 1>&6 -echo "configure:7667: checking for strftime" >&5 +echo "configure:7665: checking for strftime" >&5 if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7693: \"$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 @@ -7713,7 +7711,7 @@ else echo "$ac_t""no" 1>&6 # strftime is in -lintl on SCO UNIX. echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 -echo "configure:7717: checking for strftime in -lintl" >&5 +echo "configure:7715: 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 @@ -7721,7 +7719,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7734: \"$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 @@ -7759,12 +7757,12 @@ fi fi echo $ac_n "checking for vprintf""... $ac_c" 1>&6 -echo "configure:7763: checking for vprintf" >&5 +echo "configure:7761: checking for vprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7789: \"$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 @@ -7811,12 +7809,12 @@ fi if test "$ac_cv_func_vprintf" != yes; then echo $ac_n "checking for _doprnt""... $ac_c" 1>&6 -echo "configure:7815: checking for _doprnt" >&5 +echo "configure:7813: checking for _doprnt" >&5 if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7841: \"$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 @@ -7866,19 +7864,19 @@ fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:7870: checking for working alloca.h" >&5 +echo "configure:7868: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:7882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7880: \"$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 @@ -7899,12 +7897,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:7903: checking for alloca" >&5 +echo "configure:7901: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7934: \"$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 @@ -7964,12 +7962,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:7968: checking whether alloca needs Cray hooks" >&5 +echo "configure:7966: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7998: checking for $ac_func" >&5 +echo "configure:7996: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8024: \"$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 @@ -8049,7 +8047,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:8053: checking stack direction for C alloca" >&5 +echo "configure:8051: 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 @@ -8057,7 +8055,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8078: \"$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 @@ -8099,7 +8097,7 @@ fi # getmntent is in -lsun on Irix 4, -lseq on Dynix/PTX, -lgen on Unixware. echo $ac_n "checking for getmntent in -lsun""... $ac_c" 1>&6 -echo "configure:8103: checking for getmntent in -lsun" >&5 +echo "configure:8101: 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 @@ -8107,7 +8105,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsun $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8120: \"$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 @@ -8137,7 +8135,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for getmntent in -lseq""... $ac_c" 1>&6 -echo "configure:8141: checking for getmntent in -lseq" >&5 +echo "configure:8139: 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 @@ -8145,7 +8143,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lseq $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8158: \"$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 @@ -8175,7 +8173,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for getmntent in -lgen""... $ac_c" 1>&6 -echo "configure:8179: checking for getmntent in -lgen" >&5 +echo "configure:8177: 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 @@ -8183,7 +8181,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lgen $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8196: \"$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 @@ -8219,12 +8217,12 @@ fi fi echo $ac_n "checking for getmntent""... $ac_c" 1>&6 -echo "configure:8223: checking for getmntent" >&5 +echo "configure:8221: checking for getmntent" >&5 if eval "test \"`echo '$''{'ac_cv_func_getmntent'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8249: \"$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 @@ -8270,7 +8268,7 @@ else fi echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6 -echo "configure:8274: checking whether closedir returns void" >&5 +echo "configure:8272: 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 @@ -8278,13 +8276,13 @@ else ac_cv_func_closedir_void=yes else cat > conftest.$ac_ext < #include <$ac_header_dirent> int closedir(); main() { exit(closedir(opendir(".")) != 0); } EOF -if { (eval echo configure:8288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8286: \"$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 @@ -8307,7 +8305,7 @@ EOF fi echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:8311: checking whether setpgrp takes no argument" >&5 +echo "configure:8309: 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 @@ -8315,7 +8313,7 @@ else { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8337: \"$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 @@ -8358,7 +8356,7 @@ EOF fi echo $ac_n "checking for working fnmatch""... $ac_c" 1>&6 -echo "configure:8362: checking for working fnmatch" >&5 +echo "configure:8360: 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 @@ -8369,11 +8367,11 @@ if test "$cross_compiling" = yes; then ac_cv_func_fnmatch_works=no else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:8375: \"$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 @@ -8398,7 +8396,7 @@ fi echo $ac_n "checking for setlocale in -lxpg4""... $ac_c" 1>&6 -echo "configure:8402: checking for setlocale in -lxpg4" >&5 +echo "configure:8400: 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 @@ -8406,7 +8404,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lxpg4 $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8419: \"$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 @@ -8440,7 +8438,7 @@ fi echo $ac_n "checking for getpwnam in -lsun""... $ac_c" 1>&6 -echo "configure:8444: checking for getpwnam in -lsun" >&5 +echo "configure:8442: 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 @@ -8448,7 +8446,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsun $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8461: \"$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 @@ -8487,7 +8485,7 @@ else fi echo $ac_n "checking for deflate in -lz""... $ac_c" 1>&6 -echo "configure:8491: checking for deflate in -lz" >&5 +echo "configure:8489: 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 @@ -8495,7 +8493,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lz $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8508: \"$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 @@ -8533,7 +8531,7 @@ fi PTHREAD_LIB="" echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6 -echo "configure:8537: checking for pthread_create in -lpthread" >&5 +echo "configure:8535: 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 @@ -8541,7 +8539,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthread $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8554: \"$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 @@ -8571,7 +8569,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lpthreads""... $ac_c" 1>&6 -echo "configure:8575: checking for pthread_create in -lpthreads" >&5 +echo "configure:8573: 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 @@ -8579,7 +8577,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthreads $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8592: \"$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 @@ -8609,7 +8607,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6 -echo "configure:8613: checking for pthread_create in -lc_r" >&5 +echo "configure:8611: 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 @@ -8617,7 +8615,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lc_r $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8630: \"$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 @@ -8647,12 +8645,12 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create""... $ac_c" 1>&6 -echo "configure:8651: checking for pthread_create" >&5 +echo "configure:8649: checking for pthread_create" >&5 if eval "test \"`echo '$''{'ac_cv_func_pthread_create'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:8677: \"$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 @@ -9015,6 +9013,7 @@ trap 'rm -fr `echo "autoconf/Make.common \ src/cats/create_mysql_database \ src/cats/grant_mysql_privileges \ src/cats/make_sqlite_tables \ + src/cats/drop_sqlite_tables \ src/cats/sqlite \ src/findlib/Makefile \ $PFILES src/config.h:autoconf/config.h.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 @@ -9132,11 +9131,11 @@ s%@CONS_INC@%$CONS_INC%g s%@CONS_LIBS@%$CONS_LIBS%g s%@CONS_LDFLAGS@%$CONS_LDFLAGS%g s%@READLINE_SRC@%$READLINE_SRC%g -s%@TERMCAP_LIB@%$TERMCAP_LIB%g s%@GMP_INC@%$GMP_INC%g s%@GMP_LIBS@%$GMP_LIBS%g s%@GMP_LDFLAGS@%$GMP_LDFLAGS%g s%@GMP_SRC@%$GMP_SRC%g +s%@CWEB@%$CWEB%g s%@CWEB_INC@%$CWEB_INC%g s%@CWEB_LIBS@%$CWEB_LIBS%g s%@CWEB_LDFLAGS@%$CWEB_LDFLAGS%g @@ -9248,6 +9247,7 @@ CONFIG_FILES=\${CONFIG_FILES-"autoconf/Make.common \ src/cats/create_mysql_database \ src/cats/grant_mysql_privileges \ src/cats/make_sqlite_tables \ + src/cats/drop_sqlite_tables \ src/cats/sqlite \ src/findlib/Makefile \ $PFILES "} @@ -9440,7 +9440,7 @@ chmod 755 src/cats/make_mysql_tables src/cats/drop_mysql_tables chmod 755 src/cats/make_test_tables src/cats/drop_test_tables chmod 755 src/cats/create_mysql_database chmod 755 src/cats/grant_mysql_privileges -chmod 755 src/cats/make_sqlite_tables +chmod 755 src/cats/make_sqlite_tables src/cats/drop_sqlite_tables chmod 755 src/cats/sqlite diff --git a/bacula/src/Makefile.in b/bacula/src/Makefile.in index 00e075d1b..ee55b709d 100644 --- a/bacula/src/Makefile.in +++ b/bacula/src/Makefile.in @@ -1,4 +1,5 @@ # +# $Id$ # @MCOMMON@ diff --git a/bacula/src/bc_types.h b/bacula/src/bc_types.h index 2ab537fd6..52af67ddc 100644 --- a/bacula/src/bc_types.h +++ b/bacula/src/bc_types.h @@ -168,6 +168,8 @@ typedef float float32_t; #define uint64_t u_int64_t #define uintmax_t u_intmax_t +#define btime_t uint64_t + #ifdef HAVE_CYGWIN #define socklen_t int #endif diff --git a/bacula/src/cats/bdb_list.c b/bacula/src/cats/bdb_list.c index 6cf951211..36d22e73b 100644 --- a/bacula/src/cats/bdb_list.c +++ b/bacula/src/cats/bdb_list.c @@ -112,7 +112,7 @@ void db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, len = sizeof(mr); while (fread(&mr, len, 1, mdb->mediafd) > 0) { Mmsg(&mdb->cmd, " %-10s %17s %-15s %s\n", - mr.VolStatus, edit_uint_with_commas(mr.VolBytes, ewc), + mr.VolStatus, edit_uint64_with_commas(mr.VolBytes, ewc), mr.MediaType, mr.VolumeName); sendit(ctx, mdb->cmd); } @@ -212,8 +212,8 @@ void db_list_job_records(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void * strftime(dt, sizeof(dt), "%m-%d %H:%M", &tm); Mmsg(&mdb->cmd, " %7d %-10s %c %c %14s %10s %c %s\n", ojr.JobId, dt, (char)ojr.Type, (char)ojr.Level, - edit_uint_with_commas(ojr.JobBytes, ewc1), - edit_uint_with_commas(ojr.JobFiles, ewc2), + edit_uint64_with_commas(ojr.JobBytes, ewc1), + edit_uint64_with_commas(ojr.JobFiles, ewc2), (char)ojr.JobStatus, ojr.Name); sendit(ctx, mdb->cmd); } @@ -253,9 +253,9 @@ void db_list_job_totals(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *c total_jobs++; } Mmsg(&mdb->cmd, " %7s %10s %15s\n", - edit_uint_with_commas(total_jobs, ewc1), - edit_uint_with_commas(total_files, ewc2), - edit_uint_with_commas(total_bytes, ewc3)); + edit_uint64_with_commas(total_jobs, ewc1), + edit_uint64_with_commas(total_files, ewc2), + edit_uint64_with_commas(total_bytes, ewc3)); sendit(ctx, mdb->cmd); sendit(ctx, "=======================================\n"); V(mdb->mutex); diff --git a/bacula/src/cats/bdb_update.c b/bacula/src/cats/bdb_update.c index e0eba7524..d75187dcd 100755 --- a/bacula/src/cats/bdb_update.c +++ b/bacula/src/cats/bdb_update.c @@ -9,6 +9,8 @@ * system. * * Kern Sibbald, January MMI + * + * $Id: */ /* @@ -139,7 +141,7 @@ int db_update_media_record(B_DB *mdb, MEDIA_DBR *mr) mr->PoolId = omr.PoolId; mr->VolMaxBytes = omr.VolMaxBytes; mr->VolCapacityBytes = omr.VolCapacityBytes; - strcpy(mr->Recycle, omr.Recycle); + mr->Recycle = omr.Recycle; fseek(mdb->mediafd, omr.rec_addr, SEEK_SET); if (fwrite(mr, len, 1, mdb->mediafd) != 1) { diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 55bfe8554..4570d4b27 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -41,6 +41,8 @@ typedef int (DB_RESULT_HANDLER)(void *, int, char **); #ifdef HAVE_SQLITE +#define BDB_VERSION 1 + #include /* Define opaque structure for sqlite */ @@ -120,6 +122,8 @@ extern void my_sqlite_free_table(B_DB *mdb); #ifdef HAVE_MYSQL +#define BDB_VERSION 1 + #include /* @@ -171,7 +175,7 @@ typedef struct s_db { /* Change this each time there is some incompatible * file format change!!!! */ -#define BDB_VERSION 7 /* file version number */ +#define BDB_VERSION 8 /* file version number */ struct s_control { int bdb_version; /* Version number */ @@ -228,6 +232,7 @@ typedef struct s_db { /* ***FIXME*** FileId_t should be uint64_t */ typedef uint32_t FileId_t; typedef uint32_t DBId_t; /* general DB id type */ +typedef uint32_t JobId_t; /* Job information passed to create job record and update @@ -237,7 +242,7 @@ typedef uint32_t DBId_t; /* general DB id type */ */ /* Job record */ typedef struct { - uint32_t JobId; + JobId_t JobId; char Job[MAX_NAME_LENGTH]; /* Job unique name */ char Name[MAX_NAME_LENGTH]; /* Job base name */ int Type; /* actually char(1) */ @@ -249,6 +254,7 @@ typedef struct { time_t SchedTime; /* Time job scheduled */ time_t StartTime; /* Job start time */ time_t EndTime; /* Job termination time */ + btime_t JobTDate; /* Backup time/date in seconds */ uint32_t VolSessionId; uint32_t VolSessionTime; uint32_t JobFiles; @@ -279,7 +285,7 @@ typedef struct { /* JobMedia record */ typedef struct { uint32_t JobMediaId; /* record id */ - uint32_t JobId; /* JobId */ + JobId_t JobId; /* JobId */ uint32_t MediaId; /* MediaId */ uint32_t FirstIndex; /* First index this Volume */ uint32_t LastIndex; /* Last index this Volume */ @@ -290,8 +296,6 @@ typedef struct { } JOBMEDIA_DBR; - - /* Attributes record -- NOT same as in database because * in general, this "record" creates multiple database * records (e.g. pathname, filename, fileattributes). @@ -302,7 +306,7 @@ typedef struct { char *attr; /* attributes statp */ uint32_t FileIndex; uint32_t Stream; - uint32_t JobId; + JobId_t JobId; uint32_t ClientId; uint32_t PathId; uint32_t FilenameId; @@ -314,7 +318,7 @@ typedef struct { typedef struct { FileId_t FileId; uint32_t FileIndex; - uint32_t JobId; + JobId_t JobId; uint32_t FilenameId; uint32_t PathId; char LStat[256]; @@ -331,6 +335,9 @@ typedef struct { int UseOnce; /* set to use once only */ int UseCatalog; /* set to use catalog */ int AcceptAnyVolume; /* set to accept any volume sequence */ + int AutoPrune; /* set to prune automatically */ + int Recycle; /* default Vol recycle flag */ + btime_t VolRetention; /* retention period in seconds */ char PoolType[MAX_NAME_LENGTH]; char LabelFormat[MAX_NAME_LENGTH]; /* Extra stuff not in DB */ @@ -356,8 +363,9 @@ typedef struct { uint64_t VolBytes; /* Number of bytes written */ uint64_t VolMaxBytes; /* max bytes to write */ uint64_t VolCapacityBytes; /* capacity estimate */ + btime_t VolRetention; /* Volume retention in seconds */ + int Recycle; /* recycle yes/no */ char VolStatus[20]; /* Volume status */ - char Recycle[20]; /* Recycle yes/no */ /* Extra stuff not in DB */ faddr_t rec_addr; /* found record address */ } MEDIA_DBR; @@ -365,6 +373,9 @@ typedef struct { /* Client record -- same as the database */ typedef struct { uint32_t ClientId; /* Unique Client id */ + int AutoPrune; + btime_t FileRetention; + btime_t JobRetention; char Name[MAX_NAME_LENGTH]; /* Client name */ char Uname[256]; /* Uname for client */ } CLIENT_DBR; diff --git a/bacula/src/cats/drop_mysql_tables.in b/bacula/src/cats/drop_mysql_tables.in index 0dfaefb2d..14f2ea0d9 100644 --- a/bacula/src/cats/drop_mysql_tables.in +++ b/bacula/src/cats/drop_mysql_tables.in @@ -1,6 +1,6 @@ #!/bin/sh # -# shell script to delete Bacula tables +# shell script to delete Bacula tables for MySQL bindir=@SQL_BINDIR@ @@ -18,10 +18,11 @@ DROP TABLE IF EXISTS Pool; DROP TABLE IF EXISTS MultiVolume; DROP TABLE IF EXISTS FileSave; DROP TABLE IF EXISTS FileSet; +DROP TABLE IF EXISTS Version; END-OF-DATA then - echo "Deletion of Bacula tables succeeded." + echo "Deletion of Bacula MySQL tables succeeded." else - echo "Deletion of Bacula tables failed." + echo "Deletion of Bacula MySQL tables failed." fi exit 0 diff --git a/bacula/src/cats/drop_sqlite_tables.in b/bacula/src/cats/drop_sqlite_tables.in new file mode 100644 index 000000000..1365db6f5 --- /dev/null +++ b/bacula/src/cats/drop_sqlite_tables.in @@ -0,0 +1,7 @@ +#!/bin/sh +# +# shell script to Delete the SQLite Bacula database (same as deleting +# the tables) +# + +rm -f @working_dir@/bacula.db diff --git a/bacula/src/cats/make_mysql_tables.in b/bacula/src/cats/make_mysql_tables.in index 0ffb178ac..c5acf7a08 100644 --- a/bacula/src/cats/make_mysql_tables.in +++ b/bacula/src/cats/make_mysql_tables.in @@ -49,7 +49,7 @@ CREATE TABLE Job ( SchedTime DATETIME NOT NULL, StartTime DATETIME NOT NULL, EndTime DATETIME NOT NULL, - StartDay INTEGER UNSIGNED NOT NULL, + JobTDate BIGINT UNSIGNED NOT NULL, VolSessionId INTEGER UNSIGNED NOT NULL, VolSessionTime INTEGER UNSIGNED NOT NULL, JobFiles INTEGER UNSIGNED NOT NULL, @@ -102,9 +102,10 @@ CREATE TABLE Media ( VolWrites INTEGER UNSIGNED NOT NULL, VolMaxBytes BIGINT UNSIGNED NOT NULL, VolCapacityBytes BIGINT UNSIGNED NOT NULL, - VolStatus ENUM('Full', 'Archive', 'Append', 'Recycle', + VolStatus ENUM('Full', 'Archive', 'Append', 'Recycle', 'Purged', 'Read-Only', 'Disabled', 'Error', 'Busy') NOT NULL, - Recycle ENUM('No', 'Yes') NOT NULL, + Recycle TINYINT NOT NULL, + VolRetention BIGINT UNSIGNED NOT NULL, PRIMARY KEY(MediaId), INDEX (PoolId) ); @@ -116,7 +117,10 @@ CREATE TABLE Pool ( MaxVols INTEGER UNSIGNED NOT NULL, UseOnce TINYINT NOT NULL, UseCatalog TINYINT NOT NULL, - AcceptAnyVolume TINYINT NOT NULL, + AcceptAnyVolume TINYINT DEFAULT 0, + VolRetention BIGINT UNSIGNED NOT NULL, + AutoPrune TINYINT DEFAULT 0, + Recycle TINYINT DEFAULT 0, PoolType ENUM('Backup', 'Copy', 'Cloned', 'Archive', 'Migration') NOT NULL, LabelFormat TINYBLOB, UNIQUE (Name(128)), @@ -128,10 +132,21 @@ CREATE TABLE Client ( ClientId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, Name TINYBLOB NOT NULL, Uname TINYBLOB NOT NULL, /* full uname -a of client */ + AutoPrune TINYINT DEFAULT 0, + FileRetention BIGINT UNSIGNED NOT NULL, + JobRetention BIGINT UNSIGNED NOT NULL, UNIQUE (Name(128)), PRIMARY KEY(ClientId) ); +CREATE TABLE Version ( + VersionId INTEGER UNSIGNED NOT NULL + ); + +-- Initialize Version +INSERT INTO Version (VersionId) VALUES (1); + + ## Experimental #CREATE TABLE FileSave ( # FileSaveId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, diff --git a/bacula/src/cats/make_sqlite_tables.in b/bacula/src/cats/make_sqlite_tables.in index f811e6987..31b29ec9f 100644 --- a/bacula/src/cats/make_sqlite_tables.in +++ b/bacula/src/cats/make_sqlite_tables.in @@ -42,7 +42,7 @@ CREATE TABLE Job ( SchedTime DATETIME NOT NULL, StartTime DATETIME DEFAULT 0, EndTime DATETIME DEFAULT 0, - StartDay INTEGER UNSIGNED DEFAULT 0, + JobTDate BIGINT UNSIGNED DEFAULT 0, VolSessionId INTEGER UNSIGNED DEFAULT 0, VolSessionTime INTEGER UNSIGNED DEFAULT 0, JobFiles INTEGER UNSIGNED DEFAULT 0, @@ -93,18 +93,22 @@ CREATE TABLE Media ( VolMaxBytes BIGINT UNSIGNED DEFAULT 0, VolCapacityBytes BIGINT UNSIGNED DEFAULT 0, VolStatus VARCHAR(20) NOT NULL, - Recycle VARCHAR(20) NOT NULL, + Recycle TINYINT DEFAULT 0, + VolRetention BIGINT UNSIGNED DEFAULT 0, PRIMARY KEY(MediaId) ); CREATE TABLE Pool ( PoolId INTEGER UNSIGNED AUTOINCREMENT, Name VARCHAR(128) NOT NULL, - NumVols INTEGER UNSIGNED NOT NULL, - MaxVols INTEGER UNSIGNED NOT NULL, - UseOnce TINYINT NOT NULL, - UseCatalog TINYINT NOT NULL, - AcceptAnyVolume TINYINT NOT NULL, + NumVols INTEGER UNSIGNED DEFAULT 0, + MaxVols INTEGER UNSIGNED DEFAULT 0, + UseOnce TINYINT DEFAULT 0, + UseCatalog TINYINT DEFAULT 1, + AcceptAnyVolume TINYINT DEFAULT 0, + VolRetention BIGINT UNSIGNED DEFAULT 0, + AutoPrune TINYINT DEFAULT 0, + Recycle TINYINT DEFAULT 0, PoolType VARCHAR(20) NOT NULL, LabelFormat VARCHAR(128) NOT NULL, UNIQUE (Name), @@ -116,6 +120,9 @@ CREATE TABLE Client ( ClientId INTEGER UNSIGNED AUTOINCREMENT, Name VARCHAR(128) NOT NULL, Uname VARCHAR(255) NOT NULL, -- uname -a field + AutoPrune TINYINT DEFAULT 0, + FileRetention BIGINT UNSIGNED DEFAULT 0, + JobRetention BIGINT UNSIGNED DEFAULT 0, UNIQUE (Name), PRIMARY KEY(ClientId) ); @@ -129,6 +136,14 @@ CREATE TABLE NextId ( -- Initialize JobId to start at 1 INSERT INTO NextId (id, TableName) VALUES (1, "Job"); +CREATE TABLE Version ( + VersionId INTEGER UNSIGNED NOT NULL + ); + +-- Initialize Version +INSERT INTO Version (VersionId) VALUES (1); + + -- Experimental stuff below. Not used. -- Invariant part of File CREATE TABLE BaseFile ( diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index f420b21f5..e251ae94b 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -141,6 +141,12 @@ It is probably not running or your password is incorrect.\n"), V(mutex); return 0; } + + if (!check_tables_version(mdb)) { + V(mutex); + return 0; + } + mdb->connected = TRUE; V(mutex); return 1; diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 59335b2ed..68b931fe3 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -34,6 +34,7 @@ char *db_strerror(B_DB *mdb); int get_sql_record_max(B_DB *mdb); char *db_next_index(B_DB *mdb, char *table); int db_sql_query(B_DB *mdb, char *cmd, DB_RESULT_HANDLER *result_handler, void *ctx); +int check_tables_version(B_DB *mdb); /* create.c */ int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar); diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index c8436fa2d..647d4115c 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -41,11 +41,43 @@ void print_dashes(B_DB *mdb); void print_result(B_DB *mdb); +/* + * Called here to retrieve an integer from the database + */ +static int int_handler(void *ctx, int num_fields, char **row) +{ + uint32_t *val = (uint32_t *)ctx; + + if (row[0]) { + *val = atoi(row[0]); + } else { + *val = 0; + } + return 0; +} + + /* NOTE!!! The following routines expect that the * calling subroutine sets and clears the mutex */ +/* Check that the tables conrrespond to the version we want */ +int check_tables_version(B_DB *mdb) +{ + uint32_t version; + char *query = "SELECT VersionId FROM Version"; + + version = 0; + db_sql_query(mdb, query, int_handler, (void *)&version); + if (version != BDB_VERSION) { + Mmsg(&mdb->errmsg, "Database version mismatch. Wanted %d, got %d\n", + BDB_VERSION, version); + return 0; + } + return 1; +} + /* Utility routine for queries */ int QueryDB(char *file, int line, B_DB *mdb, char *cmd) @@ -79,7 +111,9 @@ InsertDB(char *file, int line, B_DB *mdb, char *cmd) mdb->num_rows = 1; } if (mdb->num_rows != 1) { - m_msg(file, line, &mdb->errmsg, _("Insertion problem: affect_rows=%" lld "\n"), mdb->num_rows); + char ed1[30]; + m_msg(file, line, &mdb->errmsg, _("Insertion problem: affect_rows=%s\n"), + edit_uint64(mdb->num_rows, ed1)); e_msg(file, line, M_FATAL, 0, mdb->errmsg); /* ***FIXME*** remove me */ return 0; } @@ -102,7 +136,9 @@ UpdateDB(char *file, int line, B_DB *mdb, char *cmd) } mdb->num_rows = sql_affected_rows(mdb); if (mdb->num_rows != 1) { - m_msg(file, line, &mdb->errmsg, _("Update problem: affect_rows=%" lld "\n"), mdb->num_rows); + char ed1[30]; + m_msg(file, line, &mdb->errmsg, _("Update problem: affect_rows=%s\n"), + edit_uint64(mdb->num_rows, ed1)); e_msg(file, line, M_ERROR, 0, mdb->errmsg); e_msg(file, line, M_ERROR, 0, "%s\n", cmd); return 0; diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 7ad6497ce..479f97fea 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -68,14 +68,14 @@ db_create_job_record(B_DB *mdb, JOB_DBR *jr) struct tm tm; int stat; char *JobId; - int32_t StartDay; + btime_t JobTDate; + char ed1[30]; stime = jr->SchedTime; localtime_r(&stime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); - StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) - - date_encode(2000, 1, 1)); + JobTDate = (btime_t)stime; P(mdb->mutex); JobId = db_next_index(mdb, "Job"); @@ -86,10 +86,10 @@ db_create_job_record(B_DB *mdb, JOB_DBR *jr) } /* Must create it */ Mmsg(&mdb->cmd, -"INSERT INTO Job (JobId, Job, Name, Type, Level, SchedTime, StartDay) VALUES \ -(%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %d)", +"INSERT INTO Job (JobId, Job, Name, Type, Level, SchedTime, JobTDate) VALUES \ +(%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %s)", JobId, jr->Job, jr->Name, (char)(jr->Type), (char)(jr->Level), dt, - StartDay); + edit_uint64(JobTDate, ed1)); if (!INSERT_DB(mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"), @@ -156,12 +156,13 @@ VALUES (%d, %d, %u, %u)", * 1 on success */ int -db_create_pool_record(B_DB *mdb, POOL_DBR *pool_dbr) +db_create_pool_record(B_DB *mdb, POOL_DBR *pr) { int stat; + char ed1[30]; P(mdb->mutex); - Mmsg(&mdb->cmd, "SELECT PoolId,Name FROM Pool WHERE Name=\"%s\"", pool_dbr->Name); + Mmsg(&mdb->cmd, "SELECT PoolId,Name FROM Pool WHERE Name=\"%s\"", pr->Name); Dmsg1(20, "selectpool: %s\n", mdb->cmd); if (QUERY_DB(mdb, mdb->cmd)) { @@ -169,7 +170,7 @@ db_create_pool_record(B_DB *mdb, POOL_DBR *pool_dbr) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 0) { - Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pool_dbr->Name); + Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pr->Name); sql_free_result(mdb); V(mdb->mutex); return 0; @@ -180,21 +181,23 @@ db_create_pool_record(B_DB *mdb, POOL_DBR *pool_dbr) /* Must create it */ Mmsg(&mdb->cmd, "INSERT INTO Pool (Name, NumVols, MaxVols, UseOnce, UseCatalog, \ -AcceptAnyVolume, PoolType, LabelFormat) \ -VALUES (\"%s\", %d, %d, %d, %d, %d, \"%s\", \"%s\")", - pool_dbr->Name, - pool_dbr->NumVols, pool_dbr->MaxVols, - pool_dbr->UseOnce, pool_dbr->UseCatalog, - pool_dbr->AcceptAnyVolume, - pool_dbr->PoolType, pool_dbr->LabelFormat); - +AcceptAnyVolume, AutoPrune, Recycle, VolRetention, PoolType, LabelFormat) \ +VALUES (\"%s\", %d, %d, %d, %d, %d, %d, %d, %s, \"%s\", \"%s\")", + pr->Name, + pr->NumVols, pr->MaxVols, + pr->UseOnce, pr->UseCatalog, + pr->AcceptAnyVolume, + pr->AutoPrune, pr->Recycle, + edit_uint64(pr->VolRetention, ed1), + pr->PoolType, pr->LabelFormat); + Dmsg1(500, "Create Pool: %s\n", mdb->cmd); if (!INSERT_DB(mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); - pool_dbr->PoolId = 0; + pr->PoolId = 0; stat = 0; } else { - pool_dbr->PoolId = sql_insert_id(mdb); + pr->PoolId = sql_insert_id(mdb); stat = 1; } V(mdb->mutex); @@ -212,6 +215,7 @@ int db_create_media_record(B_DB *mdb, MEDIA_DBR *mr) { int stat; + char ed1[30], ed2[30], ed3[30]; P(mdb->mutex); Mmsg(&mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName=\"%s\"", @@ -232,12 +236,16 @@ db_create_media_record(B_DB *mdb, MEDIA_DBR *mr) /* Must create it */ Mmsg(&mdb->cmd, "INSERT INTO Media (VolumeName, MediaType, PoolId, VolMaxBytes, VolCapacityBytes, \ -VolStatus, Recycle) VALUES (\"%s\", \"%s\", %d, %" lld ", %" lld ", \"%s\", \"%s\")", +Recycle, VolRetention, VolStatus) VALUES (\"%s\", \"%s\", %d, %s, %s, %d, %s, \"%s\")", mr->VolumeName, mr->MediaType, mr->PoolId, - mr->VolMaxBytes, mr->VolCapacityBytes, - mr->VolStatus, mr->Recycle); + edit_uint64(mr->VolMaxBytes,ed1), + edit_uint64(mr->VolCapacityBytes, ed2), + mr->Recycle, + edit_uint64(mr->VolRetention, ed3), + mr->VolStatus); + Dmsg1(500, "Create Volume: %s\n", mdb->cmd); if (!INSERT_DB(mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create DB Media record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); @@ -261,6 +269,7 @@ int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr) { SQL_ROW row; int stat; + char ed1[30], ed2[30]; P(mdb->mutex); Mmsg(&mdb->cmd, "SELECT ClientId FROM Client WHERE Name=\"%s\"", cr->Name); @@ -292,8 +301,11 @@ int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr) } /* Must create it */ - Mmsg(&mdb->cmd, "INSERT INTO Client (Name, Uname) VALUES \ -(\"%s\", \"%s\")", cr->Name, cr->Uname); + Mmsg(&mdb->cmd, "INSERT INTO Client (Name, Uname, AutoPrune, \ +FileRetention, JobRetention) VALUES \ +(\"%s\", \"%s\", %d, %s, %s)", cr->Name, cr->Uname, cr->AutoPrune, + edit_uint64(cr->FileRetention, ed1), + edit_uint64(cr->JobRetention, ed2)); if (!INSERT_DB(mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create DB Client record %s failed. ERR=%s\n"), @@ -502,7 +514,7 @@ static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar) /* Must create it */ Mmsg(&mdb->cmd, "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \ -LStat, MD5) VALUES (%d, %d, %d, %d, \"%s\", \" \")", +LStat, MD5) VALUES (%d, %d, %d, %d, \"%s\", \"0\")", (int)ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, ar->attr); @@ -550,8 +562,9 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg2(&mdb->errmsg, _("More than one Path!: %" lld " for Path=%s\n"), - mdb->num_rows, path); + char ed1[30]; + Mmsg2(&mdb->errmsg, _("More than one Path!: %s for Path=%s\n"), + edit_uint64(mdb->num_rows, ed1), path); Emsg1(M_ERROR, 0, "%s", mdb->errmsg); Emsg1(M_ERROR, 0, "%s\n", mdb->cmd); } diff --git a/bacula/src/cats/sql_delete.c b/bacula/src/cats/sql_delete.c index 5fd896af9..a022f8490 100644 --- a/bacula/src/cats/sql_delete.c +++ b/bacula/src/cats/sql_delete.c @@ -109,24 +109,117 @@ db_delete_pool_record(B_DB *mdb, POOL_DBR *pr) return 1; } +#define MAX_DEL_LIST_LEN 1000000 -/* Delete Media record */ -int db_delete_media_record(B_DB *mdb, MEDIA_DBR *mr) +struct s_del_ctx { + JobId_t *JobId; + int num_ids; /* ids stored */ + int max_ids; /* size of array */ + int num_del; /* number deleted */ + int tot_ids; /* total to process */ +}; + +/* + * Called here to make in memory list of JobIds to be + * deleted. The in memory list will then be transversed + * to issue the SQL DELETE commands. Note, the list + * is allowed to get to MAX_DEL_LIST_LEN to limit the + * maximum malloc'ed memory. + */ +static int delete_handler(void *ctx, int num_fields, char **row) { + struct s_del_ctx *del = (struct s_del_ctx *)ctx; - P(mdb->mutex); - if (mr->MediaId == 0) { - Mmsg(&mdb->cmd, "DELETE FROM Media WHERE VolumeName=\"%s\"", - mr->VolumeName); - } else { - Mmsg(&mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", - mr->MediaId); + if (del->num_ids == MAX_DEL_LIST_LEN) { + return 1; + } + if (del->num_ids == del->max_ids) { + del->max_ids = (del->max_ids * 3) / 2; + del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * + del->max_ids); } + del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL); + return 0; +} - mr->MediaId = DELETE_DB(mdb, mdb->cmd); - V(mdb->mutex); +/* + * This routine will purge (delete) all records + * associated with a particular Volume. It will + * not delete the media record itself. + */ +static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr) +{ + char *query = (char *)get_pool_memory(PM_MESSAGE); + struct s_del_ctx del; + int i; + + del.num_ids = 0; + del.tot_ids = 0; + del.num_del = 0; + del.max_ids = 0; + Mmsg(&mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId); + del.max_ids = mr->VolJobs; + if (del.max_ids < 100) { + del.max_ids = 100; + } else if (del.max_ids > MAX_DEL_LIST_LEN) { + del.max_ids = MAX_DEL_LIST_LEN; + } + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del); + + for (i=0; i < del.num_ids; i++) { + Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]); + Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]); + db_sql_query(mdb, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(mdb, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]); + db_sql_query(mdb, query, NULL, (void *)NULL); + } + free(del.JobId); + free_pool_memory(query); return 1; } +/* Delete Media record and all records that + * are associated with it. + */ +int db_delete_media_record(B_DB *mdb, MEDIA_DBR *mr) +{ + if (mr->MediaId == 0 && !db_get_media_record(mdb, mr)) { + return 0; + } + /* Delete associated records */ + do_media_purge(mdb, mr); + + Mmsg(&mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId); + db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL); + return 1; +} + +/* + * Purge all records associated with a + * media record. This does not delete the + * media record itself. But the media status + * is changed to "Purged". + */ +int db_purge_media_record(B_DB *mdb, MEDIA_DBR *mr) +{ + if (mr->MediaId == 0 && !db_get_media_record(mdb, mr)) { + return 0; + } + /* Delete associated records */ + do_media_purge(mdb, mr); + + /* Mark Volume as purged */ + strcpy(mr->VolStatus, "Purged"); + if (!db_update_media_record(mdb, mr)) { + return 0; + } + + return 1; +} + + #endif /* HAVE_MYSQL || HAVE_SQLITE */ diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index a50a17925..5c154917f 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -232,11 +232,12 @@ static int db_get_path_record(B_DB *mdb, char *path) Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path=\"%s\"", path); if (QUERY_DB(mdb, mdb->cmd)) { - + char ed1[30]; mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("More than one Path!: %" lld "\n"), mdb->num_rows); + Mmsg1(&mdb->errmsg, _("More than one Path!: %s\n"), + edit_uint64(mdb->num_rows, ed1)); Emsg0(M_FATAL, 0, mdb->errmsg); } else if (mdb->num_rows == 1) { if ((row = sql_fetch_row(mdb)) == NULL) { @@ -272,11 +273,11 @@ int db_get_job_record(B_DB *mdb, JOB_DBR *jr) P(mdb->mutex); if (jr->JobId == 0) { Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \ -PoolId, StartTime, EndTime, JobFiles, JobBytes, Job \ +PoolId, StartTime, EndTime, JobFiles, JobBytes, JobTDate, Job \ FROM Job WHERE Job=\"%s\"", jr->Job); } else { Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \ -PoolId, StartTime, EndTime, JobFiles, JobBytes, Job \ +PoolId, StartTime, EndTime, JobFiles, JobBytes, JobTDate, Job \ FROM Job WHERE JobId=%d", jr->JobId); } @@ -298,7 +299,8 @@ FROM Job WHERE JobId=%d", jr->JobId); strcpy(jr->cEndTime, row[4]); jr->JobFiles = atol(row[5]); jr->JobBytes = (uint64_t)strtod(row[6], NULL); - strcpy(jr->Job, row[7]); + jr->JobTDate = (btime_t)strtod(row[7], NULL); + strcpy(jr->Job, row[8]); sql_free_result(mdb); V(mdb->mutex); @@ -423,17 +425,21 @@ int db_get_pool_record(B_DB *mdb, POOL_DBR *pdbr) if (pdbr->PoolId != 0) { /* find by id */ Mmsg(&mdb->cmd, "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \ +AutoPrune, Recycle, VolRetention, \ PoolType, LabelFormat FROM Pool WHERE Pool.PoolId=%d", pdbr->PoolId); } else { /* find by name */ Mmsg(&mdb->cmd, "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \ +AutoPrune, Recycle, VolRetention, \ PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name); } if (QUERY_DB(mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("More than one Pool!: %" lld "\n"), mdb->num_rows); + char ed1[30]; + Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), + edit_uint64(mdb->num_rows, ed1)); Emsg0(M_ERROR, 0, mdb->errmsg); } else if (mdb->num_rows == 1) { if ((row = sql_fetch_row(mdb)) == NULL) { @@ -447,9 +453,12 @@ PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name); pdbr->UseOnce = atoi(row[4]); pdbr->UseCatalog = atoi(row[5]); pdbr->AcceptAnyVolume = atoi(row[6]); - strcpy(pdbr->PoolType, row[7]); - if (row[8]) { - strcpy(pdbr->LabelFormat, row[8]); + pdbr->AutoPrune = atoi(row[7]); + pdbr->Recycle = atoi(row[8]); + pdbr->VolRetention = (btime_t)strtod(row[9], NULL); + strcpy(pdbr->PoolType, row[10]); + if (row[11]) { + strcpy(pdbr->LabelFormat, row[11]); } else { pdbr->LabelFormat[0] = 0; } @@ -538,19 +547,21 @@ int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr) if (mr->MediaId != 0) { /* find by id */ Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\ VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\ -MediaType,VolStatus,PoolId \ +MediaType,VolStatus,PoolId,VoRetention,Recycle \ FROM Media WHERE MediaId=%d", mr->MediaId); } else { /* find by name */ Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\ VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\ -MediaType,VolStatus,PoolId \ +MediaType,VolStatus,PoolId,VolRetention,Recycle \ FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName); } if (QUERY_DB(mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("More than one Volume!: %" lld "\n"), mdb->num_rows); + char ed1[30]; + Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"), + edit_uint64(mdb->num_rows, ed1)); Emsg0(M_ERROR, 0, mdb->errmsg); } else if (mdb->num_rows == 1) { if ((row = sql_fetch_row(mdb)) == NULL) { @@ -572,8 +583,12 @@ FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName); strcpy(mr->MediaType, row[11]); strcpy(mr->VolStatus, row[12]); mr->PoolId = atoi(row[13]); + mr->VolRetention = (btime_t)strtod(row[14], NULL); + mr->Recycle = atoi(row[15]); stat = mr->MediaId; } + } else { + Mmsg0(&mdb->errmsg, _("Media record not found.\n")); } sql_free_result(mdb); } diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index a6757a83b..2fdef3f19 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -92,7 +92,7 @@ db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, void { Mmsg(&mdb->cmd, "SELECT VolumeName,MediaType,VolStatus,\ -VolBytes,LastWritten \ +VolBytes,LastWritten,VolRetention,Recycle \ FROM Media WHERE Media.PoolId=%d ORDER BY MediaId", mdbr->PoolId); P(mdb->mutex); diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index 4a2183a63..eef77585c 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -100,19 +100,19 @@ db_update_job_start_record(B_DB *mdb, JOB_DBR *jr) char dt[MAX_TIME_LENGTH]; time_t stime; struct tm tm; - int32_t StartDay; + btime_t JobTDate; int stat; + char ed1[30]; stime = jr->StartTime; localtime_r(&stime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); - StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) - - date_encode(2000, 1, 1)); + JobTDate = (btime_t)stime; P(mdb->mutex); Mmsg(&mdb->cmd, "UPDATE Job SET Level='%c', StartTime=\"%s\", \ -ClientId=%d, StartDay=%d WHERE JobId=%d", - (char)(jr->Level), dt, jr->ClientId, StartDay, jr->JobId); +ClientId=%d, JobTDate=%s WHERE JobId=%d", + (char)(jr->Level), dt, jr->ClientId, edit_uint64(JobTDate, ed1), jr->JobId); stat = UPDATE_DB(mdb, mdb->cmd); V(mdb->mutex); return stat; @@ -133,19 +133,22 @@ db_update_job_end_record(B_DB *mdb, JOB_DBR *jr) time_t ttime; struct tm tm; int stat; + char ed1[30], ed2[30]; + btime_t JobTDate; ttime = jr->EndTime; localtime_r(&ttime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); + JobTDate = ttime; P(mdb->mutex); Mmsg(&mdb->cmd, "UPDATE Job SET JobStatus='%c', EndTime='%s', \ -ClientId=%d, JobBytes=%" lld ", JobFiles=%d, JobErrors=%d, VolSessionId=%d, \ -VolSessionTime=%d, PoolId=%d, FileSetId=%d WHERE JobId=%d", - (char)(jr->JobStatus), dt, jr->ClientId, jr->JobBytes, jr->JobFiles, - jr->JobErrors, jr->VolSessionId, jr->VolSessionTime, - jr->PoolId, jr->FileSetId, jr->JobId); +ClientId=%d, JobBytes=%s, JobFiles=%d, JobErrors=%d, VolSessionId=%d, \ +VolSessionTime=%d, PoolId=%d, FileSetId=%d, JobTDate=%s WHERE JobId=%d", + (char)(jr->JobStatus), dt, jr->ClientId, edit_uint64(jr->JobBytes, ed1), + jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime, + jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), jr->JobId); stat = UPDATE_DB(mdb, mdb->cmd); V(mdb->mutex); @@ -183,15 +186,17 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr) time_t ttime; struct tm tm; int stat; + char ed1[30], ed2[30]; ttime = mr->LastWritten; localtime_r(&ttime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); + Dmsg1(000, "update_media: FirstWritte=%d\n", mr->FirstWritten); P(mdb->mutex); if (mr->VolMounts == 1) { - Mmsg(&mdb->cmd, "UPDATE Media SET FirstWritten=\"%s\" WHERE \ - VolumeName=\"%s\"", dt, mr->VolumeName); + Mmsg(&mdb->cmd, "UPDATE Media SET FirstWritten=\"%s\"\ + WHERE VolumeName=\"%s\"", dt, mr->VolumeName); if (do_update(mdb, mdb->cmd) == 0) { V(mdb->mutex); return 0; @@ -199,12 +204,13 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr) } Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%d,\ - VolFiles=%d, VolBlocks=%d, VolBytes=%" lld ", VolMounts=%d, VolErrors=%d,\ - VolWrites=%d, VolMaxBytes=%" lld ", LastWritten=\"%s\", VolStatus=\"%s\" \ + VolFiles=%d, VolBlocks=%d, VolBytes=%s, VolMounts=%d, VolErrors=%d,\ + VolWrites=%d, VolMaxBytes=%s, LastWritten=\"%s\", VolStatus=\"%s\" \ WHERE VolumeName=\"%s\"", - mr->VolJobs, mr->VolFiles, mr->VolBlocks, mr->VolBytes, mr->VolMounts, - mr->VolErrors, mr->VolWrites, mr->VolMaxBytes, dt, mr->VolStatus, - mr->VolumeName); + mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), + mr->VolMounts, mr->VolErrors, mr->VolWrites, + edit_uint64(mr->VolMaxBytes, ed2), dt, + mr->VolStatus, mr->VolumeName); stat = UPDATE_DB(mdb, mdb->cmd); V(mdb->mutex); diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index b9a43ce64..bbe0d09f1 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -137,6 +137,11 @@ db_open_database(B_DB *mdb) return 0; } free(db_name); + if (!check_tables_version(mdb)) { + V(mutex); + return 0; + } + mdb->connected = TRUE; V(mutex); return 1; diff --git a/bacula/src/cats/sqlite.in b/bacula/src/cats/sqlite.in index 63c2ba27d..89160b5e9 100644 --- a/bacula/src/cats/sqlite.in +++ b/bacula/src/cats/sqlite.in @@ -2,4 +2,5 @@ # # shell script to invoke SQLite on Bacula database -@bindir@/sqlite @working_dir@/bacula.db +bindir=@SQL_BINDIR@ +$bindir/sqlite @working_dir@/bacula.db diff --git a/bacula/src/console.glade b/bacula/src/console.glade index e0ba07119..5a7fa1c3e 100644 --- a/bacula/src/console.glade +++ b/bacula/src/console.glade @@ -15,17 +15,6 @@ False - - GnomeAbout - about - False - True - Copyright (c) 1999 - 2002, Kern Sibbald and John Walker - Kern Sibbald and John Walker - - It comes by night and sucks the essence from your computers. - - GnomeMessageBox messagebox1 @@ -1268,4 +1257,195 @@ + + GtkDialog + about1 + 382 + 242 + About Bacula Console + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + True + False + False + False + + + GtkVBox + Dialog:vbox + dialog-vbox5 + False + 0 + + + GtkHBox + Dialog:action_area + dialog-action_area5 + 10 + True + 5 + + 0 + False + True + GTK_PACK_END + + + + GtkHBox + hbox20 + False + 0 + + 0 + True + True + + + + GtkLabel + label44 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + True + False + + + + + GtkButton + about_button + 1 + 80 + True + True + + clicked + on_about_button_clicked + Sun, 28 Apr 2002 15:55:15 GMT + + GNOME_STOCK_BUTTON_OK + GTK_RELIEF_NORMAL + + 0 + False + False + + + + + + + GtkVBox + vbox8 + False + 0 + + 0 + True + True + + + + GtkVBox + vbox9 + False + 0 + + 0 + True + True + + + + GtkLabel + about_head + 102 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHSeparator + hseparator1 + + 0 + False + False + + + + + GtkLabel + copyright + + GTK_JUSTIFY_LEFT + False + 0.1 + 0.5 + 0 + 0 + + 0 + True + False + + + + + GtkLabel + authors + + GTK_JUSTIFY_LEFT + False + 0.0400001 + 0.5 + 0 + 0 + + 0 + True + False + + + + + GtkLabel + theme + + GTK_JUSTIFY_LEFT + False + 0.15 + 0.5 + 0 + 0 + + 0 + True + False + + + + + + + diff --git a/bacula/src/console/Makefile.in b/bacula/src/console/Makefile.in index f061bcd5a..2cafd53e6 100644 --- a/bacula/src/console/Makefile.in +++ b/bacula/src/console/Makefile.in @@ -42,7 +42,7 @@ all: Makefile console console: $(CONSOBJS) ../lib/libbac.a ../cats/libsql.a $(CXX) $(LDFLAGS) $(CONS_LDFLAGS) -L../lib -L../cats -o $@ $(CONSOBJS) \ - $(LIBS) $(DLIB) $(CONS_LIBS) -lbac -lsql -lm -ltermcap + $(LIBS) $(DLIB) $(CONS_LIBS) -lbac -lsql -lm Makefile: $(srcdir)/Makefile.in $(topdir)/config.status cd $(topdir) \ diff --git a/bacula/src/console/console.c b/bacula/src/console/console.c index 8929df66b..24c6e7a8a 100644 --- a/bacula/src/console/console.c +++ b/bacula/src/console/console.c @@ -43,12 +43,14 @@ extern int rl_catch_signals; /* Forward referenced functions */ static void terminate_console(int sig); -int get_cmd(char *prompt, BSOCK *sock, int sec); +int get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec); /* Static variables */ static char *configfile = NULL; static BSOCK *UA_sock = NULL; static DIRRES *dir; +static FILE *output = stdout; + #define CONFIG_FILE "./console.conf" /* default configuration file */ @@ -67,6 +69,64 @@ static void usage() exit(1); } +static void read_and_process_input(FILE *input, BSOCK *UA_sock) +{ + char *prompt = "*"; + int at_prompt = FALSE; + int tty_input = isatty(fileno(input)); + int stat; + + for ( ;; ) { + if (at_prompt) { /* don't prompt multiple times */ + prompt = ""; + } else { + prompt = "*"; + at_prompt = TRUE; + } + if (tty_input) { + stat = get_cmd(input, prompt, UA_sock, 30); + } else { + int len = sizeof_pool_memory(UA_sock->msg) - 1; + if (fgets(UA_sock->msg, len, input) == NULL) { + stat = -1; + } else { + strip_trailing_junk(UA_sock->msg); + UA_sock->msglen = strlen(UA_sock->msg); + stat = 1; + } + } + if (stat < 0) { + break; /* error */ + } else if (stat == 0) { /* timeout */ + bnet_fsend(UA_sock, ".messages"); + } else { + at_prompt = FALSE; + if (!bnet_send(UA_sock)) { /* send command */ + break; /* error */ + } + } + if (strcmp(UA_sock->msg, "quit") == 0 || strcmp(UA_sock->msg, "exit") == 0) { + break; + } + while ((stat = bnet_recv(UA_sock)) > 0) { + if (at_prompt) { + fprintf(output, "\n"); + at_prompt = FALSE; + } + printf("%s", UA_sock->msg); + } + fflush(output); + if (stat < 0) { + break; /* error */ + } else if (stat == 0) { + if (UA_sock->msglen == BNET_PROMPT) { + at_prompt = TRUE; + } + Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock)); + } + } +} + /********************************************************************* * @@ -75,12 +135,10 @@ static void usage() */ int main(int argc, char *argv[]) { - int ch, stat, i, ndir, item; + int ch, i, ndir, item; int no_signals = FALSE; int test_config = FALSE; JCR jcr; - char *prompt = "*"; - int at_prompt = FALSE; init_stack_dump(); my_name_is(argc, argv, "console"); @@ -90,7 +148,7 @@ int main(int argc, char *argv[]) * Ensure that every message is always printed */ for (i=1; i<=M_MAX; i++) { - add_msg_dest(MD_STDOUT, i, NULL, NULL); + add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL); } @@ -147,7 +205,7 @@ int main(int argc, char *argv[]) } UnlockRes(); if (ndir == 0) { - Emsg1(M_ABORT, 0, "No director resource defined in %s\n\ + Emsg1(M_ABORT, 0, "No Director resource defined in %s\n\ Without that I don't how to speak to the Director :-(\n", configfile); } @@ -161,20 +219,20 @@ Without that I don't how to speak to the Director :-(\n", configfile); if (ndir > 1) { UA_sock = init_bsock(0, "", "", 0); try_again: - printf("Available Directors:\n"); + fprintf(output, "Available Directors:\n"); LockRes(); ndir = 0; for (dir = NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) { - printf("%d %s at %s:%d\n", 1+ndir++, dir->hdr.name, dir->address, + fprintf(output, "%d %s at %s:%d\n", 1+ndir++, dir->hdr.name, dir->address, dir->DIRport); } UnlockRes(); - if (get_cmd("Select Director: ", UA_sock, 600) < 0) { + if (get_cmd(stdin, "Select Director: ", UA_sock, 600) < 0) { return 1; } item = atoi(UA_sock->msg); if (item < 0 || item > ndir) { - printf("You must enter a number between 1 and %d\n", ndir); + fprintf(output, "You must enter a number between 1 and %d\n", ndir); goto try_again; } LockRes(); @@ -200,51 +258,15 @@ try_again: } jcr.dir_bsock = UA_sock; if (!authenticate_director(&jcr, dir)) { - printf("ERR: %s", UA_sock->msg); + fprintf(stderr, "ERR: %s", UA_sock->msg); terminate_console(0); return 1; } Dmsg0(40, "Opened connection with Director daemon\n"); - for ( ;; ) { - if (at_prompt) { /* don't prompt multiple times */ - prompt = ""; - } else { - prompt = "*"; - at_prompt = TRUE; - } - stat = get_cmd(prompt, UA_sock, 30); - if (stat < 0) { - break; /* error */ - } else if (stat == 0) { /* timeout */ - bnet_fsend(UA_sock, ".messages"); - } else { - at_prompt = FALSE; - if (!bnet_send(UA_sock)) { /* send command */ - break; /* error */ - } - } - if (strcmp(UA_sock->msg, "quit") == 0 || strcmp(UA_sock->msg, "exit") == 0) { - break; - } - while ((stat = bnet_recv(UA_sock)) > 0) { - if (at_prompt) { - printf("\n"); - at_prompt = FALSE; - } - printf("%s", UA_sock->msg); - } - fflush(stdout); - if (stat < 0) { - break; /* error */ - } else if (stat == 0) { - if (UA_sock->msglen == BNET_PROMPT) { - at_prompt = TRUE; - } - Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock)); - } - } + read_and_process_input(stdin, UA_sock); + if (UA_sock) { bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */ bnet_close(UA_sock); @@ -271,8 +293,9 @@ static void terminate_console(int sig) #include "readline/readline.h" #include "readline/history.h" + int -get_cmd(char *prompt, BSOCK *sock, int sec) +get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec) { char *line; @@ -332,17 +355,19 @@ wait_for_data(int fd, int sec) * -1 if EOF or error */ int -get_cmd(char *prompt, BSOCK *sock, int sec) +get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec) { - fprintf(stdout, prompt); - fflush(stdout); - switch (wait_for_data(fileno(stdin), sec)) { + int len; + fprintf(output, prompt); + fflush(output); + switch (wait_for_data(fileno(input), sec)) { case 0: return 0; /* timeout */ case -1: return -1; /* error */ default: - if (fgets(sock->msg, 200, stdin) == NULL) { + len = sizeof_pool_memory(sock->msg) - 1; + if (fgets(sock->msg, len, input) == NULL) { return -1; } break; diff --git a/bacula/src/console/console_conf.c b/bacula/src/console/console_conf.c index fc5284ce7..555a08bfb 100644 --- a/bacula/src/console/console_conf.c +++ b/bacula/src/console/console_conf.c @@ -64,6 +64,18 @@ int res_all_size = sizeof(res_all); * resource with the routine to process the record * information. */ + +/* Console "globals" */ +static struct res_items cons_items[] = { + {"name", store_name, ITEM(res_cons.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(res_cons.hdr.desc), 0, 0, 0}, + {"rcfile", store_dir, ITEM(res_cons.rc_file), 0, 0, 0}, + {"historyfile", store_dir, ITEM(res_cons.hist_file), 0, 0, 0}, + {NULL, NULL, NULL, 0, 0, 0} +}; + + +/* Director's that we can contact */ static struct res_items dir_items[] = { {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0}, {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0}, @@ -78,6 +90,7 @@ static struct res_items dir_items[] = { * It must have one item for each of the resources. */ struct s_res resources[] = { + {"console", cons_items, R_CONSOLE, NULL}, {"director", dir_items, R_DIRECTOR, NULL}, {NULL, NULL, 0, NULL} }; @@ -98,6 +111,10 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... recurse = 0; } switch (type) { + case R_CONSOLE: + printf("Console: name=%s rcfile=%s histfile=%s\n", reshdr->name, + res->res_cons.rc_file, res->res_cons.hist_file); + break; case R_DIRECTOR: printf("Director: name=%s address=%s DIRport=%d\n", reshdr->name, res->res_dir.address, res->res_dir.DIRport); @@ -136,6 +153,13 @@ void free_resource(int type) free(res->res_dir.hdr.desc); switch (type) { + case R_CONSOLE: + if (res->res_cons.rc_file) { + free(res->res_cons.rc_file); + } + if (res->res_cons.hist_file) { + free(res->res_cons.hist_file); + } case R_DIRECTOR: if (res->res_dir.address) free(res->res_dir.address); @@ -181,6 +205,7 @@ void save_resource(int type, struct res_items *items, int pass) if (pass == 2) { switch (type) { /* Resources not containing a resource */ + case R_CONSOLE: case R_DIRECTOR: break; @@ -204,6 +229,9 @@ void save_resource(int type, struct res_items *items, int pass) } switch (type) { + case R_CONSOLE: + size = sizeof(CONSRES); + break; case R_DIRECTOR: size = sizeof(DIRRES); break; diff --git a/bacula/src/console/console_conf.h b/bacula/src/console/console_conf.h index 04fdc7b85..89b345b80 100644 --- a/bacula/src/console/console_conf.h +++ b/bacula/src/console/console_conf.h @@ -7,28 +7,39 @@ /* * Resource codes -- they must be sequential for indexing */ -#define R_FIRST 1001 +#define R_FIRST 1001 -#define R_DIRECTOR 1001 +#define R_CONSOLE 1001 +#define R_DIRECTOR 1002 -#define R_LAST R_DIRECTOR +#define R_LAST R_DIRECTOR /* * Some resource attributes */ -#define R_NAME 1020 -#define R_ADDRESS 1021 -#define R_PASSWORD 1022 -#define R_TYPE 1023 -#define R_BACKUP 1024 +#define R_NAME 1020 +#define R_ADDRESS 1021 +#define R_PASSWORD 1022 +#define R_TYPE 1023 +#define R_BACKUP 1024 /* Definition of the contents of each Resource */ + +/* Console "globals" */ +struct s_res_cons { + RES hdr; + char *rc_file; /* startup file */ + char *hist_file; /* command history file */ +}; +typedef struct s_res_cons CONSRES; + +/* Director */ struct s_res_dir { - RES hdr; - int DIRport; /* UA server port */ - char *address; /* UA server address */ - char *password; /* UA server password */ + RES hdr; + int DIRport; /* UA server port */ + char *address; /* UA server address */ + char *password; /* UA server password */ }; typedef struct s_res_dir DIRRES; @@ -37,7 +48,8 @@ typedef struct s_res_dir DIRRES; * resource structure definitions. */ union u_res { - struct s_res_dir res_dir; + struct s_res_dir res_dir; + struct s_res_cons res_cons; RES hdr; }; diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index 699d0a8e0..a7aeaf24b 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -20,22 +20,28 @@ first_rule: all dummy: # -SVRSRCS = dird.c authenticate.c backup.c catreq.c dird_conf.c \ +SVRSRCS = dird.c authenticate.c backup.c \ + catreq.c dird_conf.c \ fd_cmds.c getmsg.c job.c \ - mountreq.c msgchan.c newvol.c run_conf.c restore.c \ + mountreq.c msgchan.c newvol.c \ + run_conf.c restore.c \ scheduler.c ua_cmds.c \ ua_dotcmds.c \ ua_db_query.c ua_retention.c \ - ua_input.c ua_output.c ua_run.c \ + ua_input.c ua_output.c ua_prune.c \ + ua_purge.c ua_run.c \ ua_select.c ua_server.c \ ua_status.c verify.c -SVROBJS = dird.o authenticate.o backup.o catreq.o dird_conf.o \ +SVROBJS = dird.o authenticate.o backup.o \ + catreq.o dird_conf.o \ fd_cmds.o getmsg.o job.o \ - mountreq.o msgchan.o newvol.o run_conf.o restore.o \ + mountreq.o msgchan.o newvol.o \ + run_conf.o restore.o \ scheduler.o ua_cmds.o \ ua_dotcmds.o \ ua_db_query.o ua_retention.o \ - ua_input.o ua_output.o ua_run.o \ + ua_input.o ua_output.o ua_prune.o \ + ua_purge.o ua_run.o \ ua_select.o ua_server.o \ ua_status.o verify.o diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 3d5c4c239..92c1f6e20 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -38,6 +38,7 @@ #include "bacula.h" #include "dird.h" +#include "ua.h" /* Commands sent to File daemon */ static char backupcmd[] = "backup\n"; @@ -79,6 +80,9 @@ int do_backup(JCR *jcr) */ memset(&cr, 0, sizeof(cr)); strcpy(cr.Name, jcr->client->hdr.name); + cr.AutoPrune = jcr->client->AutoPrune; + cr.FileRetention = jcr->client->FileRetention; + cr.JobRetention = jcr->client->JobRetention; if (jcr->client_name) { free(jcr->client_name); } @@ -432,12 +436,12 @@ Termination: %s\n"), jcr->client->hdr.name, sdt, edt, - edit_uint_with_commas(jcr->jr.JobBytes, ec1), - edit_uint_with_commas(jcr->jr.JobFiles, ec2), + edit_uint64_with_commas(jcr->jr.JobBytes, ec1), + edit_uint64_with_commas(jcr->jr.JobFiles, ec2), jcr->VolumeName, jcr->VolSessionId, jcr->VolSessionTime, - edit_uint_with_commas(mr.VolBytes, ec3), + edit_uint64_with_commas(mr.VolBytes, ec3), term_msg); Dmsg0(100, "Leave backup_cleanup()\n"); diff --git a/bacula/src/dird/bacula-dir.conf.in b/bacula/src/dird/bacula-dir.conf.in index ee60d0d15..3087e87fe 100644 --- a/bacula/src/dird/bacula-dir.conf.in +++ b/bacula/src/dird/bacula-dir.conf.in @@ -65,13 +65,16 @@ Client { FDPort = @fd_port@ Catalog = MyCatalog Password = "@fd_password@" # password for FileDaemon + File Retention = 180d # six months + Job Retention = 365d # one year + AutoPrune = yes # Prune expired Jobs/Files } # Definition of DLT tape storage device Storage { Name = DLTDrive - Address = @hostname@ + Address = @hostname@ # N.B. Use a fully qualified name here SDPort = @sd_port@ Password = "@sd_password@" # password for Storage daemon Device = "HP DLT 80" # must be same as Device in Storage daemon @@ -81,7 +84,7 @@ Storage { # Definition of DDS tape storage device Storage { Name = SDT-10000 - Address = @hostname@ + Address = @hostname@ # N.B. Use a fully qualified name here SDPort = @sd_port@ Password = "@sd_password@" # password for Storage daemon Device = SDT-10000 # must be same as Device in Storage daemon @@ -91,7 +94,7 @@ Storage { # Definition of 8mm tape storage device Storage { Name = "8mmDrive" - Address = @hostname@ + Address = @hostname@ # N.B. Use a fully qualified name here SDPort = @sd_port@ Password = "@sd_password@" Device = "Exabyte 8mm" @@ -101,7 +104,7 @@ Storage { # Definiton of file storage device Storage { Name = File - Address = @hostname@ + Address = @hostname@ # N.B. Use a fully qualified name here SDPort = @sd_port@ Password = "@sd_password@" Device = FileStorage @@ -130,4 +133,7 @@ Messages { Pool { Name = Default Pool Type = Backup + Recycle = yes # Bacula can automatically recycle Volumes + AutoPrune = yes # Prune expired volumes + Volume Retention = 365d # one year } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index f4e82ce0f..d13d23c44 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -41,7 +41,7 @@ /* Requests from the Storage daemon */ static char Find_media[] = "CatReq Job=%127s FindMedia=%d\n"; -static char Find_Vol_Info[] = "CatReq Job=%127s GetVolInfo VolName=%127s\n"; +static char Get_Vol_Info[] = "CatReq Job=%127s GetVolInfo VolName=%127s\n"; static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s\ VolJobs=%d VolFiles=%d VolBlocks=%d VolBytes=%" lld " VolMounts=%d\ @@ -52,7 +52,7 @@ static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s\ /* Responses sent to Storage daemon */ static char OK_media[] = "1000 OK VolName=%s VolJobs=%d VolFiles=%d\ VolBlocks=%d VolBytes=%" lld " VolMounts=%d VolErrors=%d VolWrites=%d\ - VolMaxBytes=%" lld " VolCapacityBytes=%" lld "\n"; + VolMaxBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%s\n"; static char OK_update[] = "1000 OK UpdateMedia\n"; @@ -88,11 +88,19 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) jcr->MediaId = mr.MediaId; Dmsg1(20, "Find_next_vol MediaId=%d\n", jcr->MediaId); strcpy(jcr->VolumeName, mr.VolumeName); - ok = TRUE; } else { - /* See if we can create a new Volume */ - ok = newVolume(jcr); + /* Well, try finding recycled tapes */ + strcpy(mr.VolStatus, "Recycle"); + if (db_find_next_volume(jcr->db, index, &mr)) { + jcr->MediaId = mr.MediaId; + Dmsg1(20, "Find_next_vol MediaId=%d\n", jcr->MediaId); + strcpy(jcr->VolumeName, mr.VolumeName); + ok = TRUE; + } else { + /* See if we can create a new Volume */ + ok = newVolume(jcr); + } } /* * Send Find Media response to Storage daemon @@ -101,7 +109,8 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) bash_spaces(mr.VolumeName); bnet_fsend(bs, OK_media, mr.VolumeName, mr.VolJobs, mr.VolFiles, mr.VolBlocks, mr.VolBytes, mr.VolMounts, mr.VolErrors, - mr.VolWrites, mr.VolMaxBytes, mr.VolCapacityBytes); + mr.VolWrites, mr.VolMaxBytes, mr.VolCapacityBytes, + mr.VolStatus); } else { bnet_fsend(bs, "1999 No Media\n"); } @@ -109,7 +118,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) /* * Request to find specific volume information */ - } else if (sscanf(bs->msg, Find_Vol_Info, &Job, &mr.VolumeName) == 2) { + } else if (sscanf(bs->msg, Get_Vol_Info, &Job, &mr.VolumeName) == 2) { Dmsg1(120, "CatReq GetVolInfo Vol=%s\n", mr.VolumeName); /* * Find the Volume @@ -120,10 +129,12 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) Dmsg1(20, "VolumeInfo MediaId=%d\n", jcr->MediaId); strcpy(jcr->VolumeName, mr.VolumeName); /* - * Make sure this volume is suitable for this job + * Make sure this volume is suitable for this job, i.e. + * it is either Append or Recycle and Media Type matches. */ if (mr.PoolId == jcr->PoolId && - strcmp(mr.VolStatus, "Append") == 0 && + (strcmp(mr.VolStatus, "Append") == 0 || + strcmp(mr.VolStatus, "Recycle") == 0) && strcmp(mr.MediaType, jcr->store->media_type) == 0) { /* * Send Find Media response to Storage daemon @@ -131,7 +142,8 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) bash_spaces(mr.VolumeName); bnet_fsend(bs, OK_media, mr.VolumeName, mr.VolJobs, mr.VolFiles, mr.VolBlocks, mr.VolBytes, mr.VolMounts, mr.VolErrors, - mr.VolWrites, mr.VolMaxBytes, mr.VolCapacityBytes); + mr.VolWrites, mr.VolMaxBytes, mr.VolCapacityBytes, + mr.VolStatus); } else { Dmsg4(000, "get_media_record PoolId=%d wanted %d, Status=%s, \ MediaType=%s\n", mr.PoolId, jcr->PoolId, mr.VolStatus, mr.MediaType); diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index bc1607d36..a9a49da78 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -160,7 +160,7 @@ int main (int argc, char *argv[]) configfile = bstrdup(CONFIG_FILE); } - init_msg(NULL); /* initialize message handler */ + init_msg(NULL, NULL); /* initialize message handler */ parse_config(configfile); if (!check_resources()) { @@ -190,7 +190,7 @@ int main (int argc, char *argv[]) Dmsg0(200, "Start UA server\n"); start_UA_server(director->DIRport); - init_watchdog(); /* start network watchdog thread */ + start_watchdog(); /* start network watchdog thread */ init_job_server(director->MaxConcurrentJobs); @@ -215,7 +215,7 @@ static void terminate_dird(int sig) exit(1); } already_here = TRUE; - term_watchdog(); + stop_watchdog(); signal(SIGCHLD, SIG_IGN); /* don't worry about children now */ term_scheduler(); if (runjob) { diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index aea47de80..7d327814e 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -18,6 +18,8 @@ * for the resource records. * * Kern Sibbald, January MM + * + * $Id: */ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker @@ -92,7 +94,6 @@ static struct res_items dir_items[] = { {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0}, {"fdconnecttimeout", store_time,ITEM(res_dir.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30}, {"sdconnecttimeout", store_time,ITEM(res_dir.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30}, - {NULL, NULL, NULL, 0, 0, 0} }; @@ -109,10 +110,9 @@ static struct res_items cli_items[] = { {"fdport", store_pint, ITEM(res_client.FDport), 0, ITEM_REQUIRED, 0}, {"password", store_password, ITEM(res_client.password), 0, ITEM_REQUIRED, 0}, {"catalog", store_res, ITEM(res_client.catalog), R_CATALOG, 0, 0}, - {"catalogretentionperiod", store_time, - ITEM(res_client.cat_ret_period), 0, ITEM_DEFAULT, 60}, - {"mediaretentionperiod", store_time, - ITEM(res_client.media_ret_period), 0, ITEM_DEFAULT, 60}, + {"fileretention", store_time, ITEM(res_client.FileRetention), 0, ITEM_DEFAULT, 60*60*24*60}, + {"jobretention", store_time, ITEM(res_client.JobRetention), 0, ITEM_DEFAULT, 60*60*24*180}, + {"autoprune", store_yesno, ITEM(res_client.AutoPrune), 1, ITEM_DEFAULT, 1}, {NULL, NULL, NULL, 0, 0, 0} }; @@ -209,14 +209,17 @@ static struct res_items group_items[] = { */ static struct res_items pool_items[] = { {"name", store_name, ITEM(res_pool.hdr.name), 0, ITEM_REQUIRED, 0}, - {"description", store_str, ITEM(res_pool.hdr.desc), 0, 0, 0}, + {"description", store_str, ITEM(res_pool.hdr.desc), 0, 0, 0}, {"pooltype", store_strname, ITEM(res_pool.pool_type), 0, ITEM_REQUIRED, 0}, - {"labelformat", store_strname, ITEM(res_pool.label_format), 0, 0, 0}, + {"labelformat", store_strname, ITEM(res_pool.label_format), 0, 0, 0}, {"usecatalog", store_yesno, ITEM(res_pool.use_catalog), 1, ITEM_DEFAULT, 1}, - {"usevolumeonce", store_yesno, ITEM(res_pool.use_volume_once), 1, 0, 0}, + {"usevolumeonce", store_yesno, ITEM(res_pool.use_volume_once), 1, 0, 0}, {"maximumvolumes", store_pint, ITEM(res_pool.max_volumes), 0, 0, 0}, - {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, 0, 0}, + {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, 0, 0}, {"catalogfiles", store_yesno, ITEM(res_pool.catalog_files), 1, ITEM_DEFAULT, 1}, + {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, + {"autoprune", store_yesno, ITEM(res_pool.AutoPrune), 1, ITEM_DEFAULT, 1}, + {"recycle", store_yesno, ITEM(res_pool.Recycle), 1, ITEM_DEFAULT, 1}, {NULL, NULL, NULL, 0, 0, 0} }; @@ -249,15 +252,15 @@ struct s_res resources[] = { * level_name level level_class */ struct s_jl joblevels[] = { - {"full", L_FULL, JT_BACKUP}, - {"incremental", L_INCREMENTAL, JT_BACKUP}, - {"differential", L_DIFFERENTIAL, JT_BACKUP}, - {"level", L_LEVEL, JT_BACKUP}, - {"since", L_SINCE, JT_BACKUP}, - {"catalog", L_VERIFY_CATALOG, JT_VERIFY}, - {"initcatalog", L_VERIFY_INIT, JT_VERIFY}, - {"volume", L_VERIFY_VOLUME, JT_VERIFY}, - {"data", L_VERIFY_DATA, JT_VERIFY}, + {"Full", L_FULL, JT_BACKUP}, + {"Incremental", L_INCREMENTAL, JT_BACKUP}, + {"Differential", L_DIFFERENTIAL, JT_BACKUP}, + {"Level", L_LEVEL, JT_BACKUP}, + {"Since", L_SINCE, JT_BACKUP}, + {"Catalog", L_VERIFY_CATALOG, JT_VERIFY}, + {"Initcatalog", L_VERIFY_INIT, JT_VERIFY}, + {"Volume", L_VERIFY_VOLUME, JT_VERIFY}, + {"Data", L_VERIFY_DATA, JT_VERIFY}, {NULL, 0} }; @@ -358,10 +361,11 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... } switch (type) { case R_DIRECTOR: - sendit(sock, "Director: name=%s maxjobs=%d FDtimeout=%d SDtimeout=%d\n", + char ed1[30], ed2[30]; + sendit(sock, "Director: name=%s maxjobs=%d FDtimeout=%s SDtimeout=%s\n", reshdr->name, res->res_dir.MaxConcurrentJobs, - res->res_dir.FDConnectTimeout, - res->res_dir.SDConnectTimeout); + edit_uint64(res->res_dir.FDConnectTimeout, ed1), + edit_uint64(res->res_dir.SDConnectTimeout, ed2)); if (res->res_dir.query_file) { sendit(sock, " query_file=%s\n", res->res_dir.query_file); } @@ -373,8 +377,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... case R_CLIENT: sendit(sock, "Client: name=%s address=%s FDport=%d\n", res->res_client.hdr.name, res->res_client.address, res->res_client.FDport); - sendit(sock, "CatRetPeriod=%d MediaRetPeriod=%d\n", - res->res_client.cat_ret_period, res->res_client.media_ret_period); + sendit(sock, "JobRetention=%" lld " FileRetention=%" lld " AutoPrune=%d\n", + res->res_client.JobRetention, res->res_client.FileRetention, + res->res_client.AutoPrune); if (res->res_client.catalog) { sendit(sock, " --> "); dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock); @@ -445,11 +450,15 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... case R_POOL: sendit(sock, "Pool: name=%s PoolType=%s\n", res->res_pool.hdr.name, res->res_pool.pool_type); - sendit(sock, " use_cat=%d use_once=%d acpt_any=%d\n", + sendit(sock, " use_cat=%d use_once=%d acpt_any=%d cat_files=%d\n", res->res_pool.use_catalog, res->res_pool.use_volume_once, - res->res_pool.accept_any_volume); - sendit(sock, " cat_files=%d max_vols=%d\n", - res->res_pool.catalog_files, res->res_pool.max_volumes); + res->res_pool.accept_any_volume, res->res_pool.catalog_files); + sendit(sock, " max_vols=%d auto_prune=%d VolRetention=%" lld "\n", + res->res_pool.max_volumes, res->res_pool.AutoPrune, + res->res_pool.VolRetention); + sendit(sock, " recycle=%d\n", res->res_pool.Recycle); + + sendit(sock, " LabelFormat=%s\n", res->res_pool.label_format? res->res_pool.label_format:"NONE"); break; @@ -577,7 +586,6 @@ void free_resource(int type) free(res->res_msgs.mail_cmd); if (res->res_msgs.operator_cmd) free(res->res_msgs.operator_cmd); - break; case R_GROUP: break; @@ -749,7 +757,7 @@ static void store_backup(LEX *lc, struct res_items *item, int index, int pass) Dmsg1(190, "Got keyword: %s\n", lc->str); found = FALSE; for (i=0; BakVerFields[i].name; i++) { - if (strcmp(lc->str, BakVerFields[i].name) == 0) { + if (strcasecmp(lc->str, BakVerFields[i].name) == 0) { found = TRUE; if (lex_get_token(lc) != T_EQUALS) { scan_err1(lc, "Expected an equals, got: %s", lc->str); @@ -787,7 +795,7 @@ static void store_backup(LEX *lc, struct res_items *item, int index, int pass) lcase(lc->str); for (i=0; joblevels[i].level_name; i++) { if (joblevels[i].job_class == item->code && - strcmp(lc->str, joblevels[i].level_name) == 0) { + strcasecmp(lc->str, joblevels[i].level_name) == 0) { ((JOB *)(item->value))->level = joblevels[i].level; i = 0; break; diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 161ac4f67..f70441d52 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -28,63 +28,63 @@ /* * Resource codes -- they must be sequential for indexing */ -#define R_FIRST 1001 +#define R_FIRST 1001 -#define R_DIRECTOR 1001 -#define R_CLIENT 1002 -#define R_JOB 1003 -#define R_STORAGE 1004 -#define R_CATALOG 1005 -#define R_SCHEDULE 1006 -#define R_FILESET 1007 -#define R_GROUP 1008 -#define R_POOL 1009 -#define R_MSGS 1010 +#define R_DIRECTOR 1001 +#define R_CLIENT 1002 +#define R_JOB 1003 +#define R_STORAGE 1004 +#define R_CATALOG 1005 +#define R_SCHEDULE 1006 +#define R_FILESET 1007 +#define R_GROUP 1008 +#define R_POOL 1009 +#define R_MSGS 1010 -#define R_LAST R_MSGS +#define R_LAST R_MSGS /* * Some resource attributes */ -#define R_NAME 1020 -#define R_ADDRESS 1021 -#define R_PASSWORD 1022 -#define R_TYPE 1023 -#define R_BACKUP 1024 +#define R_NAME 1020 +#define R_ADDRESS 1021 +#define R_PASSWORD 1022 +#define R_TYPE 1023 +#define R_BACKUP 1024 /* Used for certain KeyWord tables */ -struct s_kw { +struct s_kw { char *name; - int token; + int token; }; /* Job Level keyword structure */ struct s_jl { char *level_name; - int level; - int job_class; + int level; + int job_class; }; /* Definition of the contents of each Resource */ /* - * Director Resource + * Director Resource * */ struct s_res_dir { - RES hdr; - int DIRport; /* where we listen -- UA port server port */ - char *password; /* Password for UA access */ - char *query_file; /* SQL query file */ - char *working_directory; /* WorkingDirectory */ - char *pid_directory; /* PidDirectory */ - char *subsys_directory; /* SubsysDirectory */ + RES hdr; + int DIRport; /* where we listen -- UA port server port */ + char *password; /* Password for UA access */ + char *query_file; /* SQL query file */ + char *working_directory; /* WorkingDirectory */ + char *pid_directory; /* PidDirectory */ + char *subsys_directory; /* SubsysDirectory */ struct s_res_msgs *messages; - int MaxConcurrentJobs; - int FDConnectTimeout; /* timeout for connect in seconds */ - int SDConnectTimeout; /* timeout in seconds */ + int MaxConcurrentJobs; + btime_t FDConnectTimeout; /* timeout for connect in seconds */ + btime_t SDConnectTimeout; /* timeout in seconds */ }; typedef struct s_res_dir DIRRES; @@ -93,11 +93,12 @@ typedef struct s_res_dir DIRRES; * */ struct s_res_client { - RES hdr; + RES hdr; - int FDport; /* Where File daemon listens */ - int32_t cat_ret_period; /* Catalog retention period */ - int32_t media_ret_period; /* Media retention period */ + int FDport; /* Where File daemon listens */ + int AutoPrune; /* Do automatic pruning? */ + btime_t FileRetention; /* file retention period in seconds */ + btime_t JobRetention; /* job retention period in seconds */ char *address; char *password; struct s_res_cat *catalog; /* Catalog resource */ @@ -109,10 +110,10 @@ typedef struct s_res_client CLIENT; * */ struct s_res_store { - RES hdr; + RES hdr; - int SDport; /* port where Directors connect */ - int SDDport; /* data port for File daemon */ + int SDport; /* port where Directors connect */ + int SDDport; /* data port for File daemon */ char *address; char *password; char *media_type; @@ -125,9 +126,9 @@ typedef struct s_res_store STORE; * */ struct s_res_cat { - RES hdr; + RES hdr; - int DBport; /* Port -- not yet implemented */ + int DBport; /* Port -- not yet implemented */ char *address; char *db_password; char *db_user; @@ -140,22 +141,22 @@ typedef struct s_res_cat CAT; * */ struct s_res_job { - RES hdr; + RES hdr; - int JobType; /* job type (backup, verify, restore */ - int level; /* default backup/verify level */ - int RestoreJobId; /* What -- JobId to restore */ - char *RestoreWhere; /* Where on disk to restore -- directory */ - int RestoreOptions; /* How (overwrite, ..) */ - int MaxRunTime; /* max run time in seconds */ - int MaxStartDelay; /* max start delay in seconds */ + int JobType; /* job type (backup, verify, restore */ + int level; /* default backup/verify level */ + int RestoreJobId; /* What -- JobId to restore */ + char *RestoreWhere; /* Where on disk to restore -- directory */ + int RestoreOptions; /* How (overwrite, ..) */ + btime_t MaxRunTime; /* max run time in seconds */ + btime_t MaxStartDelay; /* max start delay in seconds */ struct s_res_msgs *messages; /* How and where to send messages */ struct s_res_sch *schedule; /* When -- Automatic schedule */ struct s_res_client *client; /* Who to backup */ - struct s_res_fs *fs; /* What to backup -- Fileset */ + struct s_res_fs *fs; /* What to backup -- Fileset */ struct s_res_store *storage; /* Where is device -- Storage daemon */ - struct s_res_pool *pool; /* Where is media -- Media Pool */ + struct s_res_pool *pool; /* Where is media -- Media Pool */ }; typedef struct s_res_job JOB; @@ -164,7 +165,7 @@ typedef struct s_res_job JOB; * */ struct s_res_fs { - RES hdr; + RES hdr; char **include_array; int num_includes; @@ -172,8 +173,8 @@ struct s_res_fs { char **exclude_array; int num_excludes; int exclude_size; - int have_MD5; /* set if MD5 initialized */ - struct MD5Context md5c; /* MD5 of include/exclude */ + int have_MD5; /* set if MD5 initialized */ + struct MD5Context md5c; /* MD5 of include/exclude */ }; typedef struct s_res_fs FILESET; @@ -183,7 +184,7 @@ typedef struct s_res_fs FILESET; * */ struct s_res_sch { - RES hdr; + RES hdr; struct s_run *run; }; @@ -194,7 +195,7 @@ typedef struct s_res_sch SCHED; * */ struct s_res_group { - RES hdr; + RES hdr; }; typedef struct s_res_group GROUP; @@ -203,15 +204,18 @@ typedef struct s_res_group GROUP; * */ struct s_res_pool { - RES hdr; + RES hdr; char *pool_type; - char *label_format; /* Label format string */ - int use_catalog; /* maintain catalog for media */ - int catalog_files; /* maintain file entries in catalog */ - int use_volume_once; /* write on volume only once */ - int accept_any_volume; /* accept any volume */ - int max_volumes; /* max number of volumes */ + char *label_format; /* Label format string */ + int use_catalog; /* maintain catalog for media */ + int catalog_files; /* maintain file entries in catalog */ + int use_volume_once; /* write on volume only once */ + int accept_any_volume; /* accept any volume */ + int max_volumes; /* max number of volumes */ + btime_t VolRetention; /* volume retention period in seconds */ + int AutoPrune; /* default for pool auto prune */ + int Recycle; /* default for media recycle yes/no */ }; typedef struct s_res_pool POOL; @@ -220,16 +224,16 @@ typedef struct s_res_pool POOL; * resource structure definitions. */ union u_res { - struct s_res_dir res_dir; - struct s_res_client res_client; - struct s_res_store res_store; - struct s_res_cat res_cat; - struct s_res_job res_job; - struct s_res_fs res_fs; - struct s_res_sch res_sch; - struct s_res_group res_group; - struct s_res_pool res_pool; - struct s_res_msgs res_msgs; + struct s_res_dir res_dir; + struct s_res_client res_client; + struct s_res_store res_store; + struct s_res_cat res_cat; + struct s_res_job res_job; + struct s_res_fs res_fs; + struct s_res_sch res_sch; + struct s_res_group res_group; + struct s_res_pool res_pool; + struct s_res_msgs res_msgs; RES hdr; }; @@ -238,14 +242,14 @@ typedef union u_res URES; /* Run structure contained in Schedule Resource */ struct s_run { - struct s_run *next; /* points to next run record */ + struct s_run *next; /* points to next run record */ int level; int job_class; char *since; int level_no; - int minute; /* minute to run job */ - time_t last_run; /* last time run */ - time_t next_run; /* next time to run */ + int minute; /* minute to run job */ + time_t last_run; /* last time run */ + time_t next_run; /* next time to run */ char hour[nbytes_for_bits(24)]; /* bit set for each hour */ char mday[nbytes_for_bits(31)]; /* bit set for each day of month */ char month[nbytes_for_bits(12)]; /* bit set for each month */ diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 9200ccadd..539b73cae 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -135,7 +135,7 @@ static void job_thread(void *arg) Dmsg0(100, "=====Start Job=========\n"); jcr->start_time = now; /* set the real start time */ if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay < - (jcr->start_time - jcr->sched_time)) { + (btime_t)(jcr->start_time - jcr->sched_time)) { Jmsg(jcr, M_FATAL, 0, _("Job cancelled because max delay time exceeded.\n")); free_jcr(jcr); } @@ -259,6 +259,7 @@ void set_jcr_defaults(JCR *jcr, JOB *job) jcr->pool = job->pool; jcr->catalog = job->client->catalog; jcr->fileset = job->fs; + init_msg(jcr, job->messages); /* If no default level given, set one */ if (jcr->level == 0) { switch (jcr->JobType) { diff --git a/bacula/src/dird/newvol.c b/bacula/src/dird/newvol.c index 1f7dda171..bf698a382 100644 --- a/bacula/src/dird/newvol.c +++ b/bacula/src/dird/newvol.c @@ -8,7 +8,7 @@ * This routine runs as a thread and must be thread reentrant. * * Basic tasks done here: - * If possible create a new Media entry + * If possible create a new Media entry * */ /* @@ -52,21 +52,22 @@ int newVolume(JCR *jcr) if (db_get_pool_record(jcr->db, &pr) && pr.LabelFormat[0] && pr.LabelFormat[0] != '*') { if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) { - memset(&mr, 0, sizeof(mr)); - mr.PoolId = jcr->PoolId; - strcpy(mr.MediaType, jcr->store->media_type); - strcpy(name, pr.LabelFormat); + memset(&mr, 0, sizeof(mr)); + mr.PoolId = jcr->PoolId; + strcpy(mr.MediaType, jcr->store->media_type); + strcpy(name, pr.LabelFormat); strcat(name, "%04d"); - sprintf(mr.VolumeName, name, ++pr.NumVols); + sprintf(mr.VolumeName, name, ++pr.NumVols); strcpy(mr.VolStatus, "Append"); - strcpy(mr.Recycle, "No"); - if (db_create_media_record(jcr->db, &mr) && - db_update_pool_record(jcr->db, &pr) == 1) { + mr.Recycle = pr.Recycle; + mr.VolRetention = pr.VolRetention; + if (db_create_media_record(jcr->db, &mr) && + db_update_pool_record(jcr->db, &pr) == 1) { Dmsg1(90, "Created new Volume=%s\n", mr.VolumeName); - return 1; - } else { + return 1; + } else { Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); - } + } } } return 0; diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 0c693d8b9..8cd2a22ba 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -1,5 +1,7 @@ /* * Director external function prototypes + * + * $Id: */ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker @@ -35,13 +37,13 @@ extern char *level_to_str(int level); /* fd_cmds.c */ extern int connect_to_file_daemon(JCR *jcr, int retry_interval, - int max_retry_time, int verbose); + int max_retry_time, int verbose); extern int send_include_list(JCR *jcr); extern int send_exclude_list(JCR *jcr); extern int get_attributes_and_put_in_catalog(JCR *jcr); extern int get_attributes_and_compare_to_catalog(JCR *jcr, int last_full_id); extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname, - char *link, char *attr, int stream); + char *link, char *attr, int stream); /* job.c */ extern void free_jcr(JCR *jcr); @@ -53,7 +55,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf); /* msgchan.c */ extern int connect_to_storage_daemon(JCR *jcr, int retry_interval, - int max_retry_time, int verbose); + int max_retry_time, int verbose); extern int start_storage_daemon_job(JCR *jcr); extern int start_storage_daemon_message_thread(JCR *jcr); extern int32_t bget_msg(BSOCK *bs, int type); @@ -62,5 +64,5 @@ extern int response(BSOCK *fd, char *resp, char *cmd); /* newvol.c */ extern int newVolume(JCR *jcr); -/* ua_cmds.c */ +/* ua_cmd.c */ extern int create_pool(B_DB *db, POOL *pool); diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index 35accb51c..51581b34a 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -75,6 +75,9 @@ int do_restore(JCR *jcr) */ memset(&cr, 0, sizeof(cr)); strcpy(cr.Name, jcr->client->hdr.name); + cr.AutoPrune = jcr->client->AutoPrune; + cr.FileRetention = jcr->client->FileRetention; + cr.JobRetention = jcr->client->JobRetention; if (jcr->client_name) { free(jcr->client_name); } diff --git a/bacula/src/dird/run_conf.c b/bacula/src/dird/run_conf.c index c58a713f5..21b69f894 100644 --- a/bacula/src/dird/run_conf.c +++ b/bacula/src/dird/run_conf.c @@ -176,7 +176,7 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass) } else { lcase(lc->str); for (i=0; joblevels[i].level_name; i++) { - if (strcmp(lc->str, joblevels[i].level_name) == 0) { + if (strcasecmp(lc->str, joblevels[i].level_name) == 0) { lrun.level = joblevels[i].level; lrun.job_class = joblevels[i].job_class; i = 0; diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index d9f41204d..2336a4b2b 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -2,6 +2,8 @@ * Includes specific to the Director User Agent Server * * Kern Sibbald, August MMI + * + * $Id: */ /* Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker @@ -31,17 +33,19 @@ typedef struct s_ua_context { JCR *jcr; B_DB *db; CAT *catalog; - char *cmd; /* return command/name buffer */ - char *args; /* command line arguments */ - char *argk[MAX_ARGS]; /* argument keywords */ - char *argv[MAX_ARGS]; /* argument values */ - int argc; /* number of arguments */ - char **prompt; /* list of prompts */ - int max_prompts; /* max size of list */ - int num_prompts; /* current number in list */ - int auto_display_messages; /* if set, display messages */ + char *cmd; /* return command/name buffer */ + char *args; /* command line arguments */ + char *argk[MAX_ARGS]; /* argument keywords */ + char *argv[MAX_ARGS]; /* argument values */ + int argc; /* number of arguments */ + char **prompt; /* list of prompts */ + int max_prompts; /* max size of list */ + int num_prompts; /* current number in list */ + int auto_display_messages; /* if set, display messages */ int user_notified_msg_pending; /* set when user notified */ - int automount; /* if set, mount after label */ + int automount; /* if set, mount after label */ + int quit; /* if set, quit */ + int verbose; /* set for normal UA verbosity */ } UAContext; /* ua_cmds.c */ @@ -68,16 +72,19 @@ JOB *select_job_resource(UAContext *ua); int select_pool_dbr(UAContext *ua, POOL_DBR *pr); CLIENT *select_client_resource(UAContext *ua); FILESET *select_fs_resource(UAContext *ua); +int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); void start_prompt(UAContext *ua, char *msg); void add_prompt(UAContext *ua, char *prompt); int do_prompt(UAContext *ua, char *msg, char *prompt); -CAT *get_catalog_resource(UAContext *ua); +CAT *get_catalog_resource(UAContext *ua); STORE *get_storage_resource(UAContext *ua, char *cmd); int get_media_type(UAContext *ua, char *MediaType); int get_pool_dbr(UAContext *ua, POOL_DBR *pr); POOL *get_pool_resource(UAContext *ua); CLIENT *get_client_resource(UAContext *ua); +int get_job_dbr(UAContext *ua, JOB_DBR *jr); int find_arg_keyword(UAContext *ua, char **list); int do_keyword_prompt(UAContext *ua, char *msg, char **list); +int confirm_retention(UAContext *ua, btime_t *ret, char *msg); diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 791ca47f0..b3eb5b278 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -33,7 +33,6 @@ extern void run_job(JCR *jcr); /* Imported variables */ -extern struct s_jl joblevels[]; extern int r_first; extern int r_last; extern struct s_res resources[]; @@ -51,6 +50,8 @@ extern int sqlquerycmd(UAContext *ua, char *cmd); extern int querycmd(UAContext *ua, char *cmd); extern int runcmd(UAContext *ua, char *cmd); extern int retentioncmd(UAContext *ua, char *cmd); +extern int prunecmd(UAContext *ua, char *cmd); +extern int purgecmd(UAContext *ua, char *cmd); /* Forward referenced functions */ static int addcmd(UAContext *ua, char *cmd), createcmd(UAContext *ua, char *cmd), cancelcmd(UAContext *ua, char *cmd); @@ -60,9 +61,9 @@ static int deletecmd(UAContext *ua, char *cmd); static int usecmd(UAContext *ua, char *cmd), unmountcmd(UAContext *ua, char *cmd); static int labelcmd(UAContext *ua, char *cmd), mountcmd(UAContext *ua, char *cmd), updatecmd(UAContext *ua, char *cmd); static int versioncmd(UAContext *ua, char *cmd), automountcmd(UAContext *ua, char *cmd); -static int update_media(UAContext *ua); +static int update_volume(UAContext *ua); static int update_pool(UAContext *ua); -static int delete_media(UAContext *ua); +static int delete_volume(UAContext *ua); static int delete_pool(UAContext *ua); int quitcmd(UAContext *ua, char *cmd); @@ -81,7 +82,8 @@ static struct cmdstruct commands[] = { { N_("list"), listcmd, _("list [pools | jobs | jobtotals | media | files job=]; from catalog")}, { N_("messages"), messagescmd, _("messages")}, { N_("mount"), mountcmd, _("mount ")}, - { N_("retention"), retentioncmd, _("retention")}, + { N_("prune"), prunecmd, _("prune expired records from catalog")}, + { N_("purge"), purgecmd, _("purge records from catalog")}, { N_("run"), runcmd, _("run ")}, { N_("setdebug"), setdebugcmd, _("sets debug level")}, { N_("show"), showcmd, _("show (resource records) [jobs | pools | ... | all]")}, @@ -239,7 +241,8 @@ getVolName: mr.PoolId = pr.PoolId; strcpy(mr.VolStatus, "Append"); - strcpy(mr.Recycle, "No"); + mr.Recycle = pr.Recycle; + mr.VolRetention = pr.VolRetention; for (i=startnum; i < num+startnum; i++) { sprintf(mr.VolumeName, name, i); Dmsg1(200, "Create Volume %s\n", mr.VolumeName); @@ -455,6 +458,10 @@ int create_pool(B_DB *db, POOL *pool) pr.UseOnce = pool->use_volume_once; pr.UseCatalog = pool->use_catalog; pr.AcceptAnyVolume = pool->accept_any_volume; + pr.Recycle = pool->Recycle; + pr.VolRetention = pool->VolRetention; +Dmsg1(000, "Retention=%d\n", (uint32_t)pr.VolRetention); + pr.AutoPrune = pool->AutoPrune; if (pool->label_format) { strcpy(pr.LabelFormat, pool->label_format); } else { @@ -529,7 +536,7 @@ static int updatecmd(UAContext *ua, char *cmd) switch (find_arg_keyword(ua, kw)) { case 0: case 1: - update_media(ua); + update_volume(ua); return 1; case 2: update_pool(ua); @@ -540,13 +547,13 @@ static int updatecmd(UAContext *ua, char *cmd) start_prompt(ua, _("Update choice:\n")); add_prompt(ua, _("pool")); - add_prompt(ua, _("media")); + add_prompt(ua, _("volume")); switch (do_prompt(ua, _("Choose catalog item to update"), NULL)) { case 0: update_pool(ua); break; case 1: - update_media(ua); + update_volume(ua); break; default: break; @@ -560,7 +567,7 @@ static int updatecmd(UAContext *ua, char *cmd) * writing on the volume, set it to anything other * than Append. */ -static int update_media(UAContext *ua) +static int update_volume(UAContext *ua) { POOL_DBR pr; MEDIA_DBR mr; @@ -568,11 +575,13 @@ static int update_media(UAContext *ua) static char *kw[] = { "volume", NULL}; + char *query; + char ed1[30]; memset(&pr, 0, sizeof(pr)); memset(&mr, 0, sizeof(mr)); if (!get_pool_dbr(ua, &pr)) { - return 1; + return 0; } mr.PoolId = pr.PoolId; mr.VolumeName[0] = 0; @@ -584,27 +593,68 @@ static int update_media(UAContext *ua) if (mr.VolumeName[0] == 0) { db_list_media_records(ua->db, &mr, prtit, ua); if (!get_cmd(ua, _("Enter Volume name to update: "))) { - return 1; + return 0; } strcpy(mr.VolumeName, ua->cmd); } mr.MediaId = 0; if (!db_get_media_record(ua->db, &mr)) { - bsendmsg(ua, _("Media record for %s not found.\n"), mr.VolumeName); - return 1; + bsendmsg(ua, _("Volume record for %s not found.\n"), mr.VolumeName); + return 0; } - start_prompt(ua, _("Volume Status Values:\n")); - add_prompt(ua, "Append"); - add_prompt(ua, "Archive"); - add_prompt(ua, "Disabled"); - add_prompt(ua, "Full"); - add_prompt(ua, "Recycle"); - add_prompt(ua, "Read-Only"); - if (do_prompt(ua, _("Choose new Volume Status"), ua->cmd) < 0) { - return 1; + + for (int done=0; !done; ) { + start_prompt(ua, _("Parameters to modify:\n")); + add_prompt(ua, _("Volume Status")); + add_prompt(ua, _("Volume Retention")); + add_prompt(ua, _("Done")); + switch (do_prompt(ua, _("Select paramter to modify"), NULL)) { + case 0: /* Volume Status */ + /* Modify Volume */ + bsendmsg(ua, _("Current value is: %s\n"), mr.VolStatus); + start_prompt(ua, _("Possible Values are:\n")); + add_prompt(ua, "Append"); + add_prompt(ua, "Archive"); + add_prompt(ua, "Disabled"); + add_prompt(ua, "Full"); + if (strcmp(mr.VolStatus, "Purged") == 0) { + add_prompt(ua, "Recycle"); + } + add_prompt(ua, "Read-Only"); + if (do_prompt(ua, _("Choose new Volume Status"), ua->cmd) < 0) { + return 1; + } + strcpy(mr.VolStatus, ua->cmd); + query = (char *)get_pool_memory(PM_MESSAGE); + Mmsg(&query, "UPDATE Media SET VolStatus=\"%s\" WHERE MediaId=%d", + mr.VolStatus, mr.MediaId); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + free_pool_memory(query); + break; + case 1: /* Retention */ + bsendmsg(ua, _("Current value is: %s\n"), + edit_btime(mr.VolRetention, ed1)); + if (!get_cmd(ua, _("Enter Volume Retention period: "))) { + return 0; + } + if (!string_to_btime(ua->cmd, &mr.VolRetention)) { + bsendmsg(ua, _("Invalid retention period specified.\n")); + break; + } + query = (char *)get_pool_memory(PM_MESSAGE); + Mmsg(&query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%d", + edit_uint64(mr.VolRetention, ed1), mr.MediaId); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + free_pool_memory(query); + break; + default: /* Done or error */ + return 0; + } } - strcpy(mr.VolStatus, ua->cmd); - db_update_media_record(ua->db, &mr); return 1; } @@ -897,7 +947,7 @@ static int deletecmd(UAContext *ua, char *cmd) switch (find_arg_keyword(ua, keywords)) { case 0: - delete_media(ua); + delete_volume(ua); return 1; case 1: delete_pool(ua); @@ -907,7 +957,7 @@ static int deletecmd(UAContext *ua, char *cmd) } switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) { case 0: - delete_media(ua); + delete_volume(ua); break; case 1: delete_pool(ua); @@ -922,39 +972,18 @@ static int deletecmd(UAContext *ua, char *cmd) /* * Delete media records from database -- dangerous */ -static int delete_media(UAContext *ua) +static int delete_volume(UAContext *ua) { POOL_DBR pr; MEDIA_DBR mr; - int found = FALSE; - int i; - memset(&pr, 0, sizeof(pr)); - memset(&mr, 0, sizeof(mr)); - - /* Get the pool, possibly from pool= */ - if (!get_pool_dbr(ua, &pr)) { + if (!select_pool_and_media_dbr(ua, &pr, &mr)) { return 1; } - mr.PoolId = pr.PoolId; + bsendmsg(ua, _("\nThis command will delete volume %s\n" + "and all Jobs saved on that volume from the Catalog\n"), + mr.VolumeName); - /* See if a volume name is specified as an argument */ - for (i=1; iargc; i++) { - if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) { - found = TRUE; - break; - } - } - if (found) { - strcpy(mr.VolumeName, ua->argv[i]); - } else { - db_list_media_records(ua->db, &mr, prtit, ua); - if (!get_cmd(ua, _("Enter the Volume name to delete: "))) { - return 1; - } - } - mr.MediaId = 0; - strcpy(mr.VolumeName, ua->cmd); if (!get_cmd(ua, _("If you want to continue enter pretty please: "))) { return 1; } @@ -1047,8 +1076,9 @@ gotVol: return 1; } mr.PoolId = pr.PoolId; - strcpy(mr.Recycle, "Yes"); strcpy(mr.VolStatus, "Append"); + mr.Recycle = pr.Recycle; + mr.VolRetention = pr.VolRetention; ua->jcr->store = store; bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), @@ -1066,7 +1096,7 @@ gotVol: bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s"), dev_name, mr.VolumeName, pr.Name, mr.MediaType); bsendmsg(ua, "Sending label command ...\n"); - while (bnet_recv(sd) > 0) { + while (bget_msg(sd, 0) > 0) { bsendmsg(ua, "%s", sd->msg); if (strncmp(sd->msg, "3000 OK label.", 14) == 0) { ok = TRUE; @@ -1083,7 +1113,9 @@ gotVol: mr.VolumeName); if (ua->automount) { bsendmsg(ua, _("Requesting mount %s ...\n"), dev_name); + bash_spaces(dev_name); bnet_fsend(sd, "mount %s", dev_name); + unbash_spaces(dev_name); while (bnet_recv(sd) > 0) { bsendmsg(ua, "%s", sd->msg); /* Here we can get @@ -1200,7 +1232,8 @@ static int usecmd(UAContext *ua, char *cmd) int quitcmd(UAContext *ua, char *cmd) { - return 0; + ua->quit = TRUE; + return 1; } static int helpcmd(UAContext *ua, char *cmd) @@ -1254,6 +1287,7 @@ int open_db(UAContext *ua) close_db(ua); return 0; } + ua->jcr->db = ua->db; Dmsg1(50, "DB %s opened\n", ua->catalog->db_name); return 1; } @@ -1264,4 +1298,5 @@ void close_db(UAContext *ua) db_close_database(ua->db); } ua->db = NULL; + ua->jcr->db = NULL; } diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index 12aa6f714..a466e3e18 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -34,7 +34,6 @@ #include "ua.h" /* Imported variables */ -extern struct s_jl joblevels[]; extern int r_first; extern int r_last; extern struct s_res resources[]; diff --git a/bacula/src/dird/ua_input.c b/bacula/src/dird/ua_input.c index 53250db4a..9a24d052b 100644 --- a/bacula/src/dird/ua_input.c +++ b/bacula/src/dird/ua_input.c @@ -40,15 +40,29 @@ int get_cmd(UAContext *ua, char *prompt) BSOCK *sock = ua->UA_sock; ua->cmd[0] = 0; + if (!sock) { /* No UA */ + return 0; + } bnet_fsend(sock, "%s", prompt); bnet_sig(sock, BNET_PROMPT); /* request more input */ - if (bnet_recv(sock) < 0) { - return 0; + for ( ;; ) { + if (bnet_recv(sock) < 0) { + return 0; + } + ua->cmd = (char *) check_pool_memory_size(ua->cmd, sock->msglen+1); + strcpy(ua->cmd, sock->msg); + ua->cmd[sock->msglen] = 0; + strip_trailing_junk(ua->cmd); + if (strcmp(ua->cmd, ".messages") == 0) { + qmessagescmd(ua, ua->cmd); + } + /* ****FIXME**** if .command, go off and do it. For now ignore it. */ + if (ua->cmd[0] == '.' && ua->cmd[1] != 0) { + continue; /* dot command */ + } + /* Lone dot => break or actual response */ + break; } - ua->cmd = (char *) check_pool_memory_size(ua->cmd, sock->msglen+1); - strcpy(ua->cmd, sock->msg); - ua->cmd[sock->msglen] = 0; - strip_trailing_junk(ua->cmd); return 1; } diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index e77673cfd..ff572affa 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -34,7 +34,6 @@ extern void run_job(JCR *jcr); /* Imported variables */ -extern struct s_jl joblevels[]; extern int r_first; extern int r_last; extern struct s_res resources[]; @@ -169,35 +168,6 @@ int showcmd(UAContext *ua, char *cmd) } -/* - * Callback routine for "printing" database file listing - */ -void prtit(void *ctx, char *msg) -{ - UAContext *ua = (UAContext *)ctx; - - bnet_fsend(ua->UA_sock, "%s", msg); -} - -/* Format message and send to other end */ -void bsendmsg(void *ctx, char *fmt, ...) -{ - va_list arg_ptr; - UAContext *ua = (UAContext *)ctx; - BSOCK *bs = ua->UA_sock; - int maxlen; - -again: - maxlen = sizeof_pool_memory(bs->msg) - 1; - va_start(arg_ptr, fmt); - bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr); - va_end(arg_ptr); - if (bs->msglen < 0 || bs->msglen >= maxlen) { - bs->msg = (char *) realloc_pool_memory(bs->msg, maxlen + 200); - goto again; - } - bnet_send(bs); -} /* @@ -386,3 +356,54 @@ int messagescmd(UAContext *ua, char *cmd) } return 1; } + +/* + * Callback routine for "printing" database file listing + */ +void prtit(void *ctx, char *msg) +{ + UAContext *ua = (UAContext *)ctx; + + bnet_fsend(ua->UA_sock, "%s", msg); +} + +/* + * Format message and send to other end. + + * If the UA_sock is NULL, it means that there is no user + * agent, so we are being called from Bacula core. In + * that case direct the messages to the Job. + */ +void bsendmsg(void *ctx, char *fmt, ...) +{ + va_list arg_ptr; + UAContext *ua = (UAContext *)ctx; + BSOCK *bs = ua->UA_sock; + int maxlen, len; + char *msg; + + if (bs) { + msg = bs->msg; + } else { + msg = (char *)get_pool_memory(PM_EMSG); + } + +again: + maxlen = sizeof_pool_memory(msg) - 1; + va_start(arg_ptr, fmt); + len = bvsnprintf(msg, maxlen, fmt, arg_ptr); + va_end(arg_ptr); + if (len < 0 || len >= maxlen) { + msg = (char *) realloc_pool_memory(msg, maxlen + 200); + goto again; + } + + if (bs) { + bs->msglen = len; + bnet_send(bs); + } else { /* No UA, send to Job */ + Jmsg(ua->jcr, M_INFO, 0, msg); + free_memory(msg); + } + +} diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c new file mode 100644 index 000000000..d790e78c8 --- /dev/null +++ b/bacula/src/dird/ua_prune.c @@ -0,0 +1,591 @@ +/* + * + * Bacula Director -- User Agent Database prune Command + * Applies retention periods + * + * Kern Sibbald, February MMII + * + * $Id: + */ + +/* + Copyright (C) 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "dird.h" +#include "ua.h" + +/* Forward referenced functions */ +int prune_files(UAContext *ua, CLIENT *client); +int prune_jobs(UAContext *ua, CLIENT *client); +int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); +static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr); + + +#define MAX_DEL_LIST_LEN 1000000 + +/* + * Select JobIds for File deletion. + */ +static char *select_job = + "SELECT JobId from Job " + "WHERE JobTDate < %s " + "AND ClientId=%d " + "AND PurgedFiles=0"; + +/* + * List of SQL commands terminated by NULL for deleting + * temporary tables and indicies + */ +static char *drop_deltabs[] = { + "DROP TABLE DelCandidates", + "DROP INDEX DelInx1", + NULL}; + +/* + * List of SQL commands to create temp table and indicies + */ +static char *create_deltabs[] = { + "CREATE TABLE DelCandidates (" + "JobId INTEGER UNSIGNED NOT NULL, " + "PurgedFiles TINYINT, " + "FileSetId INTEGER UNSIGNED)", + "CREATE INDEX DelInx1 ON DelCandidates (JobId)", + NULL}; + + +/* + * Fill candidates table with all Files subject to being deleted + */ +static char *insert_delcand = + "INSERT INTO DelCandidates " + "SELECT JobId, PurgedFiles, FileSetId FROM Job " + "WHERE JobTDate < %s " + "AND ClientId=%d"; + +/* + * Select files from the DelCandidates table that have a + * more recent backup -- i.e. are not the only backup. + * This is the list of files to delete. + */ +static char *select_del = + "SELECT DelCandidates.JobId " + "FROM Job,DelCandidates " + "WHERE Job.JobTDate >= %s " + "AND Job.ClientId=%d " + "AND Job.Level='F' " + "AND Job.JobStatus='T' " + "AND Job.FileSetId=DelCandidates.FileSetId"; + +/* In memory list of JobIds */ +struct s_file_del_ctx { + JobId_t *JobId; + int num_ids; /* ids stored */ + int max_ids; /* size of array */ + int num_del; /* number deleted */ + int tot_ids; /* total to process */ +}; + +struct s_job_del_ctx { + JobId_t *JobId; /* array of JobIds */ + char *PurgedFiles; /* Array of PurgedFile flags */ + int num_ids; /* ids stored */ + int max_ids; /* size of array */ + int num_del; /* number deleted */ + int tot_ids; /* total to process */ +}; + +struct s_count_ctx { + int count; +}; + + +/* + * Called here to count entries to be deleted + */ +static int count_handler(void *ctx, int num_fields, char **row) +{ + struct s_count_ctx *cnt = (struct s_count_ctx *)ctx; + + if (row[0]) { + cnt->count = atoi(row[0]); + } else { + cnt->count = 0; + } + return 0; +} + + +/* + * Called here to count entries to be deleted + */ +static int file_count_handler(void *ctx, int num_fields, char **row) +{ + struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx; + del->tot_ids++; + return 0; +} + + +/* + * Called here to make in memory list of JobIds to be + * deleted and the associated PurgedFiles flag. + * The in memory list will then be transversed + * to issue the SQL DELETE commands. Note, the list + * is allowed to get to MAX_DEL_LIST_LEN to limit the + * maximum malloc'ed memory. + */ +static int job_delete_handler(void *ctx, int num_fields, char **row) +{ + struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx; + + if (del->num_ids == MAX_DEL_LIST_LEN) { + return 1; + } + if (del->num_ids == del->max_ids) { + del->max_ids = (del->max_ids * 3) / 2; + del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); + del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids); + } + del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL); + del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]); + return 0; +} + +static int file_delete_handler(void *ctx, int num_fields, char **row) +{ + struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx; + + if (del->num_ids == MAX_DEL_LIST_LEN) { + return 1; + } + if (del->num_ids == del->max_ids) { + del->max_ids = (del->max_ids * 3) / 2; + del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * + del->max_ids); + } + del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL); + return 0; +} + +/* + * Prune records from database + * + * prune files (from) client=xxx + * prune jobs (from) client=xxx + * prune volume=xxx + */ +int prunecmd(UAContext *ua, char *cmd) +{ + CLIENT *client; + POOL_DBR pr; + MEDIA_DBR mr; + + static char *keywords[] = { + N_("Files"), + N_("Jobs"), + N_("Volume"), + NULL}; + if (!open_db(ua)) { + return 01; + } + switch (find_arg_keyword(ua, keywords)) { + case 0: + client = select_client_resource(ua); + if (!client || !confirm_retention(ua, &client->FileRetention, "File")) { + return 0; + } + prune_files(ua, client); + return 1; + case 1: + client = select_client_resource(ua); + if (!client || !confirm_retention(ua, &client->JobRetention, "Job")) { + return 0; + } + prune_jobs(ua, client); + return 1; + case 2: + if (!select_pool_and_media_dbr(ua, &pr, &mr)) { + return 0; + } + if (!confirm_retention(ua, &mr.VolRetention, "Volume")) { + return 0; + } + prune_volume(ua, &pr, &mr); + return 1; + default: + break; + } + switch (do_keyword_prompt(ua, _("Choose item to prune"), keywords)) { + case 0: + client = select_client_resource(ua); + if (!client || !confirm_retention(ua, &client->FileRetention, "File")) { + return 0; + } + prune_files(ua, client); + break; + case 1: + client = select_client_resource(ua); + if (!client || !confirm_retention(ua, &client->JobRetention, "Job")) { + return 0; + } + prune_jobs(ua, client); + break; + case 2: + if (!select_pool_and_media_dbr(ua, &pr, &mr)) { + return 0; + } + if (!confirm_retention(ua, &mr.VolRetention, "Volume")) { + return 0; + } + prune_volume(ua, &pr, &mr); + return 1; + } + return 1; +} + +/* + * Prune File records from the database. For any Job which + * is older than the retention period, we unconditionally delete + * all File records for that Job. This is simple enough that no + * temporary tables are needed. We simply make an in memory list of + * the JobIds meeting the prune conditions, then delete all File records + * pointing to each of those JobIds. + */ +int prune_files(UAContext *ua, CLIENT *client) +{ + struct s_file_del_ctx del; + char *query = (char *)get_pool_memory(PM_MESSAGE); + int i; + btime_t now, period; + CLIENT_DBR cr; + char ed1[50]; + + memset(&cr, 0, sizeof(cr)); + memset(&del, 0, sizeof(del)); + strcpy(cr.Name, client->hdr.name); + if (!db_create_client_record(ua->db, &cr)) { + return 0; + } + + period = client->FileRetention; + now = (btime_t)time(NULL); + + Mmsg(&query, select_job, edit_uint64(now - period, ed1), cr.ClientId); + + Dmsg1(050, "select sql=%s\n", query); + + if (!db_sql_query(ua->db, query, file_count_handler, (void *)&del)) { + if (ua->verbose) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + if (del.tot_ids == 0) { + if (ua->verbose) { + bsendmsg(ua, _("No Files found for client %s to prune from %s catalog.\n"), + client->hdr.name, client->catalog->hdr.name); + } + goto bail_out; + } + + if (del.tot_ids < MAX_DEL_LIST_LEN) { + del.max_ids = del.tot_ids + 1; + } else { + del.max_ids = MAX_DEL_LIST_LEN; + } + del.tot_ids = 0; + + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + + db_sql_query(ua->db, query, file_delete_handler, (void *)&del); + + for (i=0; i < del.num_ids; i++) { + Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]); + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + /* + * Now mark Job as having files purged. This is necessary to + * avoid having too many Jobs to process in future prunings. If + * we don't do this, the number of JobId's in our in memory list + * will grow very large. + */ + Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + } + bsendmsg(ua, _("Pruned %d Files for client %s from %s catalog.\n"), del.num_ids, + client->hdr.name, client->catalog->hdr.name); + +bail_out: + if (del.JobId) { + free(del.JobId); + } + free_pool_memory(query); + return 1; +} + + +static void drop_temp_tables(UAContext *ua) +{ + int i; + for (i=0; drop_deltabs[i]; i++) { + db_sql_query(ua->db, drop_deltabs[i], NULL, (void *)NULL); + } +} + +static int create_temp_tables(UAContext *ua) +{ + int i; + /* Create temp tables and indicies */ + for (i=0; create_deltabs[i]; i++) { + if (!db_sql_query(ua->db, create_deltabs[i], NULL, (void *)NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "create DelTables table failed\n"); + return 0; + } + } + return 1; +} + + + +/* + * Purging Jobs is a bit more complicated than purging Files + * because we delete Job records only if there is a more current + * backup of the FileSet. Otherwise, we keep the Job record. + * In other words, we never delete the only Job record that + * contains a current backup of a FileSet. This prevents the + * Volume from being recycled and destroying a current backup. + */ +int prune_jobs(UAContext *ua, CLIENT *client) +{ + struct s_job_del_ctx del; + struct s_count_ctx cnt; + char *query = (char *)get_pool_memory(PM_MESSAGE); + int i; + btime_t now, period; + CLIENT_DBR cr; + char ed1[50]; + + memset(&cr, 0, sizeof(cr)); + memset(&del, 0, sizeof(del)); + strcpy(cr.Name, client->hdr.name); + if (!db_create_client_record(ua->db, &cr)) { + return 0; + } + + period = client->JobRetention; + now = (btime_t)time(NULL); + + /* Drop any previous temporary tables still there */ + drop_temp_tables(ua); + + /* Create temp tables and indicies */ + if (!create_temp_tables(ua)) { + goto bail_out; + } + + /* + * Select all files that are older than the JobRetention period + * and stuff them into the "DeletionCandidates" table. + */ + edit_uint64(now - period, ed1); + Mmsg(&query, insert_delcand, ed1, cr.ClientId); + + if (!db_sql_query(ua->db, query, NULL, (void *)NULL)) { + if (ua->verbose) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + Dmsg0(050, "insert delcand failed\n"); + goto bail_out; + } + + strcpy(query, "SELECT count(*) FROM DelCandidates"); + + Dmsg1(100, "select sql=%s\n", query); + + if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) { + if (ua->verbose) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + if (cnt.count == 0) { + if (ua->verbose) { + bsendmsg(ua, _("No Jobs for client %s found to prune from %s catalog.\n"), + client->hdr.name, client->catalog->hdr.name); + } + goto bail_out; + } + + if (cnt.count < MAX_DEL_LIST_LEN) { + del.max_ids = cnt.count + 1; + } else { + del.max_ids = MAX_DEL_LIST_LEN; + } + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + del.PurgedFiles = (char *)malloc(del.max_ids); + + Mmsg(&query, select_del, ed1, cr.ClientId); + db_sql_query(ua->db, query, job_delete_handler, (void *)&del); + + /* + * OK, now we have the list of JobId's to be pruned, first check + * if the Files have been purged, if not, purge (delete) them. + * Then delete the Job entry, and finally and JobMedia records. + */ + for (i=0; i < del.num_ids; i++) { + Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]); + if (!del.PurgedFiles[i]) { + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + } + + Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + } + bsendmsg(ua, _("Pruned %d Jobs for client %s from %s catalog.\n"), del.num_ids, + client->hdr.name, client->catalog->hdr.name); + +bail_out: + drop_temp_tables(ua); + if (del.JobId) { + free(del.JobId); + } + if (del.PurgedFiles) { + free(del.PurgedFiles); + } + free_pool_memory(query); + return 1; +} + +/* + * Prune volumes + */ +int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) +{ + char *query = (char *)get_pool_memory(PM_MESSAGE); + struct s_count_ctx cnt; + struct s_file_del_ctx del; + int i; + JOB_DBR jr; + btime_t now, period; + + memset(&jr, 0, sizeof(jr)); + memset(&del, 0, sizeof(del)); + cnt.count = 0; + Mmsg(&query, "SELECT count(*) FROM JobMedia WHERE MediaId=%d", mr->MediaId); + if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + if (cnt.count == 0) { + if (ua->verbose) { + bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n", + mr->VolumeName); + } + if (!mark_media_purged(ua, mr)) { + goto bail_out; + } + goto bail_out; + } + + if (cnt.count < MAX_DEL_LIST_LEN) { + del.max_ids = cnt.count + 1; + } else { + del.max_ids = MAX_DEL_LIST_LEN; + } + + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + + Mmsg(&query, "SELECT JobId FROM JobMedia WHERE MediaId=%d", mr->MediaId); + if (!db_sql_query(ua->db, query, file_delete_handler, (void *)&del)) { + if (ua->verbose) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + /* Use Volume Retention to purge Jobs and Files */ + period = mr->VolRetention; + now = (btime_t)time(NULL); + + for (i=0; i < del.num_ids; i++) { + jr.JobId = del.JobId[i]; + if (!db_get_job_record(ua->db, &jr)) { + continue; + } + if (jr.JobTDate >= (now - period)) { + continue; + } + Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]); + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + del.num_del++; + } + if (del.JobId) { + free(del.JobId); + } + bsendmsg(ua, _("Pruned %d Jobs on Volume %s from catalog.\n"), del.num_del, + mr->VolumeName); + + /* If purged, mark it so */ + if (del.num_ids == del.num_del) { + mark_media_purged(ua, mr); + } + +bail_out: + free_pool_memory(query); + return 1; +} + +static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr) +{ + if (strcmp(mr->VolStatus, "Append") == 0 || + strcmp(mr->VolStatus, "Full") == 0) { + strcpy(mr->VolStatus, "Purged"); + if (!db_update_media_record(ua->db, mr)) { + if (ua->verbose) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + return 0; + } + } + return 1; +} diff --git a/bacula/src/dird/ua_purge.c b/bacula/src/dird/ua_purge.c new file mode 100644 index 000000000..552d8d909 --- /dev/null +++ b/bacula/src/dird/ua_purge.c @@ -0,0 +1,511 @@ +/* + * + * Bacula Director -- User Agent Database Purge Command + * + * Purges Files from specific JobIds + * or + * Purges Jobs from Volumes + * + * Kern Sibbald, February MMII + * + * $Id: + */ + +/* + Copyright (C) 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + */ + +#include "bacula.h" +#include "dird.h" +#include "ua.h" + +/* Forward referenced functions */ +int purge_files_from_client(UAContext *ua, CLIENT *client); +int purge_jobs_from_client(UAContext *ua, CLIENT *client); +void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr ); +void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); +void purge_files_from_job(UAContext *ua, JOB_DBR *jr); +static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr); + + +#define MAX_DEL_LIST_LEN 1000000 + + +static char *select_jobsfiles_from_client = + "SELECT JobId FROM Job " + "WHERE ClientId=%d " + "AND PurgedFiles=0"; + +static char *select_jobs_from_client = + "SELECT JobId, PurgedFiles FROM Job " + "WHERE ClientId=%d"; + + +/* In memory list of JobIds */ +struct s_file_del_ctx { + JobId_t *JobId; + int num_ids; /* ids stored */ + int max_ids; /* size of array */ + int num_del; /* number deleted */ + int tot_ids; /* total to process */ +}; + +struct s_job_del_ctx { + JobId_t *JobId; /* array of JobIds */ + char *PurgedFiles; /* Array of PurgedFile flags */ + int num_ids; /* ids stored */ + int max_ids; /* size of array */ + int num_del; /* number deleted */ + int tot_ids; /* total to process */ +}; + +struct s_count_ctx { + int count; +}; + +/* + * Called here to count entries to be deleted + */ +static int count_handler(void *ctx, int num_fields, char **row) +{ + struct s_count_ctx *cnt = (struct s_count_ctx *)ctx; + + if (row[0]) { + cnt->count = atoi(row[0]); + } else { + cnt->count = 0; + } + return 0; +} + +/* + * Called here to count entries to be deleted + */ +static int file_count_handler(void *ctx, int num_fields, char **row) +{ + struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx; + del->tot_ids++; + return 0; +} + + +static int job_count_handler(void *ctx, int num_fields, char **row) +{ + struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx; + del->tot_ids++; + return 0; +} + + +/* + * Called here to make in memory list of JobIds to be + * deleted and the associated PurgedFiles flag. + * The in memory list will then be transversed + * to issue the SQL DELETE commands. Note, the list + * is allowed to get to MAX_DEL_LIST_LEN to limit the + * maximum malloc'ed memory. + */ +static int job_delete_handler(void *ctx, int num_fields, char **row) +{ + struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx; + + if (del->num_ids == MAX_DEL_LIST_LEN) { + return 1; + } + if (del->num_ids == del->max_ids) { + del->max_ids = (del->max_ids * 3) / 2; + del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids); + del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids); + } + del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL); + del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]); + return 0; +} + +static int file_delete_handler(void *ctx, int num_fields, char **row) +{ + struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx; + + if (del->num_ids == MAX_DEL_LIST_LEN) { + return 1; + } + if (del->num_ids == del->max_ids) { + del->max_ids = (del->max_ids * 3) / 2; + del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * + del->max_ids); + } + del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL); + return 0; +} + +/* + * Purge records from database + * + * Purge Files (from) [Job|JobId|Client|Volume] + * Purge Jobs (from) [Client|Volume] + * + * N.B. Not all above is implemented yet. + */ +int purgecmd(UAContext *ua, char *cmd) +{ + CLIENT *client; + MEDIA_DBR mr; + POOL_DBR pr; + JOB_DBR jr; + static char *keywords[] = { + N_("files"), + N_("jobs"), + NULL}; + + static char *files_keywords[] = { + N_("Job"), + N_("JobId"), + N_("Client"), + N_("Volume"), + NULL}; + + static char *jobs_keywords[] = { + N_("Client"), + N_("Volume"), + NULL}; + + bsendmsg(ua, _( + "This command is DANGEROUS!!!\n" + "It purges (deletes) all Files from a Job,\n" + "JobId, Client or Volume; or it purges (deletes)\n" + "all Jobs from a Client or Volume. Normally you\n" + "should use the PRUNE command instead.\n")); + + if (!open_db(ua)) { + return 1; + } + switch (find_arg_keyword(ua, keywords)) { + /* Files */ + case 0: + switch(find_arg_keyword(ua, files_keywords)) { + case 0: /* Job */ + case 1: + if (get_job_dbr(ua, &jr)) { + purge_files_from_job(ua, &jr); + } + return 1; + case 2: /* client */ + client = select_client_resource(ua); + purge_files_from_client(ua, client); + return 1; + case 3: + if (select_pool_and_media_dbr(ua, &pr, &mr)) { + purge_files_from_volume(ua, &pr, &mr); + } + return 1; + } + /* Jobs */ + case 1: + switch(find_arg_keyword(ua, jobs_keywords)) { + case 0: /* client */ + client = select_client_resource(ua); + purge_jobs_from_client(ua, client); + return 1; + case 1: + if (select_pool_and_media_dbr(ua, &pr, &mr)) { + purge_jobs_from_volume(ua, &pr, &mr); + } + return 1; + } + default: + break; + } + switch (do_keyword_prompt(ua, _("Choose item to purge"), keywords)) { + case 0: + client = select_client_resource(ua); + if (!client) { + return 1; + } + purge_files_from_client(ua, client); + break; + case 1: + client = select_client_resource(ua); + if (!client) { + return 1; + } + purge_jobs_from_client(ua, client); + break; + } + return 1; +} + +/* + * Prune File records from the database. For any Job which + * is older than the retention period, we unconditionally delete + * all File records for that Job. This is simple enough that no + * temporary tables are needed. We simply make an in memory list of + * the JobIds meeting the prune conditions, then delete all File records + * pointing to each of those JobIds. + */ +int purge_files_from_client(UAContext *ua, CLIENT *client) +{ + struct s_file_del_ctx del; + char *query = (char *)get_pool_memory(PM_MESSAGE); + int i; + CLIENT_DBR cr; + + memset(&cr, 0, sizeof(cr)); + memset(&del, 0, sizeof(del)); + + strcpy(cr.Name, client->hdr.name); + if (!db_create_client_record(ua->db, &cr)) { + return 0; + } + + Mmsg(&query, select_jobsfiles_from_client, cr.ClientId); + + Dmsg1(050, "select sql=%s\n", query); + + if (!db_sql_query(ua->db, query, file_count_handler, (void *)&del)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + if (del.tot_ids == 0) { + bsendmsg(ua, _("No Files found for client %s to purge from %s catalog.\n"), + client->hdr.name, client->catalog->hdr.name); + goto bail_out; + } + + if (del.tot_ids < MAX_DEL_LIST_LEN) { + del.max_ids = del.tot_ids + 1; + } else { + del.max_ids = MAX_DEL_LIST_LEN; + } + del.tot_ids = 0; + + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + + db_sql_query(ua->db, query, file_delete_handler, (void *)&del); + + for (i=0; i < del.num_ids; i++) { + Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]); + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + /* + * Now mark Job as having files purged. This is necessary to + * avoid having too many Jobs to process in future prunings. If + * we don't do this, the number of JobId's in our in memory list + * will grow very large. + */ + Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + } + bsendmsg(ua, _("%d Files for client %s purged from %s catalog.\n"), del.num_ids, + client->hdr.name, client->catalog->hdr.name); + +bail_out: + if (del.JobId) { + free(del.JobId); + } + free_pool_memory(query); + return 1; +} + + + +/* + * Purging Jobs is a bit more complicated than purging Files + * because we delete Job records only if there is a more current + * backup of the FileSet. Otherwise, we keep the Job record. + * In other words, we never delete the only Job record that + * contains a current backup of a FileSet. This prevents the + * Volume from being recycled and destroying a current backup. + */ +int purge_jobs_from_client(UAContext *ua, CLIENT *client) +{ + struct s_job_del_ctx del; + char *query = (char *)get_pool_memory(PM_MESSAGE); + int i; + CLIENT_DBR cr; + + memset(&cr, 0, sizeof(cr)); + memset(&del, 0, sizeof(del)); + + strcpy(cr.Name, client->hdr.name); + if (!db_create_client_record(ua->db, &cr)) { + return 0; + } + + Mmsg(&query, select_jobs_from_client, cr.ClientId); + + Dmsg1(050, "select sql=%s\n", query); + + if (!db_sql_query(ua->db, query, job_count_handler, (void *)&del)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + if (del.tot_ids == 0) { + bsendmsg(ua, _("No Jobs found for client %s to purge from %s catalog.\n"), + client->hdr.name, client->catalog->hdr.name); + goto bail_out; + } + + if (del.tot_ids < MAX_DEL_LIST_LEN) { + del.max_ids = del.tot_ids + 1; + } else { + del.max_ids = MAX_DEL_LIST_LEN; + } + + del.tot_ids = 0; + + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + del.PurgedFiles = (char *)malloc(del.max_ids); + + db_sql_query(ua->db, query, job_delete_handler, (void *)&del); + + /* + * OK, now we have the list of JobId's to be purged, first check + * if the Files have been purged, if not, purge (delete) them. + * Then delete the Job entry, and finally and JobMedia records. + */ + for (i=0; i < del.num_ids; i++) { + Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]); + if (!del.PurgedFiles[i]) { + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + } + + Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + } + bsendmsg(ua, _("%d Jobs for client %s purged from %s catalog.\n"), del.num_ids, + client->hdr.name, client->catalog->hdr.name); + +bail_out: + if (del.JobId) { + free(del.JobId); + } + if (del.PurgedFiles) { + free(del.PurgedFiles); + } + free_pool_memory(query); + return 1; +} + +void purge_files_from_job(UAContext *ua, JOB_DBR *jr) +{ + char *query = (char *)get_pool_memory(PM_MESSAGE); + + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", jr->JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + + Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", jr->JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + + free_pool_memory(query); +} + +void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr ) +{} /* ***FIXME*** implement */ + +void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) +{ + char *query = (char *)get_pool_memory(PM_MESSAGE); + struct s_count_ctx cnt; + struct s_file_del_ctx del; + int i; + JOB_DBR jr; + + memset(&jr, 0, sizeof(jr)); + memset(&del, 0, sizeof(del)); + cnt.count = 0; + Mmsg(&query, "SELECT count(*) FROM JobMedia WHERE MediaId=%d", mr->MediaId); + if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + if (cnt.count == 0) { + bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n", + mr->VolumeName); + if (!mark_media_purged(ua, mr)) { + goto bail_out; + } + goto bail_out; + } + + if (cnt.count < MAX_DEL_LIST_LEN) { + del.max_ids = cnt.count + 1; + } else { + del.max_ids = MAX_DEL_LIST_LEN; + } + + del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); + + Mmsg(&query, "SELECT JobId FROM JobMedia WHERE MediaId=%d", mr->MediaId); + if (!db_sql_query(ua->db, query, file_delete_handler, (void *)&del)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + Dmsg0(050, "Count failed\n"); + goto bail_out; + } + + for (i=0; i < del.num_ids; i++) { + Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]); + Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Dmsg1(050, "Del sql=%s\n", query); + del.num_del++; + } + if (del.JobId) { + free(del.JobId); + } + bsendmsg(ua, _("%d Files for Volume %s purged from catalog.\n"), del.num_del, + mr->VolumeName); + + /* If purged, mark it so */ + if (del.num_ids == del.num_del) { + mark_media_purged(ua, mr); + } + +bail_out: + free_pool_memory(query); +} + +static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr) +{ + if (strcmp(mr->VolStatus, "Append") == 0 || + strcmp(mr->VolStatus, "Full") == 0) { + strcpy(mr->VolStatus, "Purged"); + if (!db_update_media_record(ua->db, mr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + return 0; + } + } + return 1; +} diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 8a5c90b50..a44d73ea0 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -327,16 +327,16 @@ Storage: %s\n"), goto try_again; } else if (jcr->JobType == JT_VERIFY) { start_prompt(ua, _("Levels:\n")); - add_prompt(ua, _("Verify from Catalog")); add_prompt(ua, _("Initialize Catalog")); + add_prompt(ua, _("Verify from Catalog")); add_prompt(ua, _("Verify Volume")); add_prompt(ua, _("Verify Volume Data")); switch (do_prompt(ua, _("Select level"), NULL)) { case 0: - jcr->level = L_VERIFY_CATALOG; + jcr->level = L_VERIFY_INIT; break; case 1: - jcr->level = L_VERIFY_INIT; + jcr->level = L_VERIFY_CATALOG; break; case 2: jcr->level = L_VERIFY_VOLUME; diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index d0ac1a4be..f0329268a 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -3,6 +3,8 @@ * Bacula Director -- User Agent Prompt and Selection code * * Kern Sibbald, October MMI + * + * $Id: */ /* @@ -41,6 +43,36 @@ void start_prompt(UAContext *ua, char *msg); STORE *select_storage_resource(UAContext *ua); JOB *select_job_resource(UAContext *ua); +/* + * Confirm a retention period + */ +int confirm_retention(UAContext *ua, btime_t *ret, char *msg) +{ + char ed1[30]; + + for ( ;; ) { + bsendmsg(ua, _("The current %s retention period is: %s\n"), + msg, edit_btime(*ret, ed1)); + if (!get_cmd(ua, _("Continue? (yes/mod/no): "))) { + return 0; + } + if (strcasecmp(ua->cmd, _("mod")) == 0) { + if (!get_cmd(ua, _("Enter new retention period: "))) { + return 0; + } + if (!string_to_btime(ua->cmd, ret)) { + bsendmsg(ua, _("Invalid period.\n")); + continue; + } + continue; + } + if (strcasecmp(ua->cmd, _("yes")) == 0) { + break; + } + } + return 1; +} + /* * Given a list of keywords, find the first one * that is in the argument list. @@ -208,9 +240,6 @@ CLIENT *get_client_resource(UAContext *ua) return select_client_resource(ua); } - - - /* Scan what the user has entered looking for: * * pool= @@ -260,7 +289,7 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) return 0; } if (num_pools <= 0) { - bsendmsg(ua, _("No pools defined.\n")); + bsendmsg(ua, _("No pools defined. Use the \"create\" command to create one.\n")); return 0; } @@ -287,6 +316,47 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr) return opr.PoolId; } +/* + * Select a Pool and a Media (Volume) record from the database + */ +int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) +{ + int found = FALSE; + int i; + + memset(pr, 0, sizeof(POOL_DBR)); + memset(mr, 0, sizeof(MEDIA_DBR)); + + /* Get the pool, possibly from pool= */ + if (!get_pool_dbr(ua, pr)) { + return 0; + } + mr->PoolId = pr->PoolId; + + /* See if a volume name is specified as an argument */ + for (i=1; iargc; i++) { + if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) { + found = TRUE; + break; + } + } + if (found) { + strcpy(mr->VolumeName, ua->argv[i]); + } else { + db_list_media_records(ua->db, mr, prtit, ua); + if (!get_cmd(ua, _("Enter the Volume name to delete: "))) { + return 01; + } + strcpy(mr->VolumeName, ua->cmd); + } + mr->MediaId = 0; + if (!db_get_media_record(ua->db, mr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + return 0; + } + return 1; +} + /* * This routine is ONLY used in the create command. @@ -321,6 +391,63 @@ POOL *get_pool_resource(UAContext *ua) return pool; } +/* + * List all jobs and ask user to select one + */ +int select_job_dbr(UAContext *ua, JOB_DBR *jr) +{ + db_list_job_records(ua->db, jr, prtit, ua); + if (!get_cmd(ua, _("Enter the JobId to select: "))) { + return 0; + } + jr->JobId = atoi(ua->cmd); + if (!db_get_job_record(ua->db, jr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + return 0; + } + return jr->JobId; + +} + + +/* Scan what the user has entered looking for: + * + * jobid=nn + * + * if error or not found, put up a list of Jobs + * to choose from. + * + * returns: 0 on error + * JobId on success and fills in JOB_DBR + */ +int get_job_dbr(UAContext *ua, JOB_DBR *jr) +{ + int i; + + for (i=1; iargc; i++) { + if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) { + jr->JobId = 0; + strcpy(jr->Job, ua->argv[i]); + } else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) { + jr->JobId = atoi(ua->argv[i]); + } else { + continue; + } + if (!db_get_job_record(ua->db, jr)) { + bsendmsg(ua, _("Could not find Job %s: ERR=%s"), ua->argv[i], + db_strerror(ua->db)); + jr->JobId = 0; + break; + } + return jr->JobId; + } + + if (!select_job_dbr(ua, jr)) { /* try once more */ + return 0; + } + return jr->JobId; +} + @@ -388,7 +515,8 @@ int do_prompt(UAContext *ua, char *msg, char *prompt) } else { sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1); } - if (!get_cmd(ua, pmsg) || *ua->cmd == '.') { + /* Either a . or an @ will get you out of the loop */ + if (!get_cmd(ua, pmsg) || *ua->cmd == '.' || *ua->cmd == '@') { item = -1; /* error */ break; } diff --git a/bacula/src/dird/ua_server.c b/bacula/src/dird/ua_server.c index 1ce726039..8722a028d 100644 --- a/bacula/src/dird/ua_server.c +++ b/bacula/src/dird/ua_server.c @@ -33,7 +33,6 @@ extern void run_job(JCR *jcr); /* Imported variables */ -extern struct s_jl joblevels[]; extern int r_first; extern int r_last; extern struct s_res resources[]; @@ -91,7 +90,7 @@ static void *connect_thread(void *arg) */ static void handle_UA_client_request(void *arg) { - int quit, stat; + int stat; static char cmd[1000]; UAContext ua; BSOCK *UA_sock = (BSOCK *) arg; @@ -100,8 +99,8 @@ static void handle_UA_client_request(void *arg) memset(&ua, 0, sizeof(ua)); ua.automount = TRUE; + ua.verbose = TRUE; ua.jcr = new_jcr(sizeof(JCR), dird_free_jcr); - close_msg(ua.jcr); /* we don't handle messages */ ua.jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */ ua.UA_sock = UA_sock; ua.cmd = (char *) get_pool_memory(PM_FNAME); @@ -116,19 +115,18 @@ static void handle_UA_client_request(void *arg) goto getout; } - quit = FALSE; - while (!quit) { + while (!ua.quit) { stat = bnet_recv(ua.UA_sock); if (stat > 0) { strncpy(cmd, ua.UA_sock->msg, sizeof(cmd)); cmd[sizeof(cmd)-1] = 0; /* ensure it is terminated/trucated */ parse_command_args(&ua); if (ua.argc > 0 && ua.argk[0][0] == '.') { - quit = !do_a_dot_command(&ua, cmd); + do_a_dot_command(&ua, cmd); } else { - quit = !do_a_command(&ua, cmd); + do_a_command(&ua, cmd); } - if (!quit) { + if (!ua.quit) { if (ua.auto_display_messages) { strcpy(cmd, "messages"); qmessagescmd(&ua, cmd); @@ -141,6 +139,7 @@ static void handle_UA_client_request(void *arg) } } else if (stat == 0) { if (ua.UA_sock->msglen == BNET_TERMINATE) { + ua.quit = TRUE; break; } bnet_sig(ua.UA_sock, BNET_POLL); @@ -155,11 +154,12 @@ getout: ua.UA_sock = NULL; } + close_db(&ua); /* do this before freeing JCR */ + if (ua.jcr) { free_jcr(ua.jcr); ua.jcr = NULL; } - close_db(&ua); if (ua.prompt) { free(ua.prompt); } diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index a05ee54b1..eb8b651f7 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -220,8 +220,8 @@ static void do_director_status(UAContext *ua, char *cmd) } bsendmsg(ua, _(" Files=%s Bytes=%s Termination Status=%s\n"), - edit_uint_with_commas(last_job.JobFiles, b1), - edit_uint_with_commas(last_job.JobBytes, b2), + edit_uint64_with_commas(last_job.JobFiles, b1), + edit_uint64_with_commas(last_job.JobBytes, b2), termstat); } lock_jcr_chain(); diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 57d97e4c6..8c3c63d9b 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -73,6 +73,9 @@ int do_verify(JCR *jcr) CLIENT_DBR cr; memset(&cr, 0, sizeof(cr)); + cr.AutoPrune = jcr->client->AutoPrune; + cr.FileRetention = jcr->client->FileRetention; + cr.JobRetention = jcr->client->JobRetention; strcpy(cr.Name, jcr->client->hdr.name); if (jcr->client_name) { free(jcr->client_name); @@ -116,7 +119,9 @@ int do_verify(JCR *jcr) return 0; } - jcr->fname = (char *) get_pool_memory(PM_FNAME); + if (!jcr->fname) { + jcr->fname = (char *) get_pool_memory(PM_FNAME); + } jcr->jr.JobId = last_full_id; /* save last full id */ @@ -304,11 +309,14 @@ Termination: %s\n"), jcr->client->hdr.name, sdt, edt, - edit_uint_with_commas(jcr->jr.JobFiles, ec1), + edit_uint64_with_commas(jcr->jr.JobFiles, ec1), term_msg); Dmsg0(100, "Leave verify_cleanup()\n"); - + if (jcr->fname) { + free_memory(jcr->fname); + jcr->fname = NULL; + } } /* @@ -323,6 +331,8 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, int last_full_id) struct stat statc; /* catalog stat */ int stat = JS_Terminated; char buf[MAXSTRING]; + char *fname = (char *)get_pool_memory(PM_MESSAGE); + int do_MD5 = FALSE; memset(&fdbr, 0, sizeof(FILE_DBR)); fd = jcr->file_bsock; @@ -333,175 +343,181 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, int last_full_id) * Get Attributes and MD5 Signature from File daemon */ while ((n=bget_msg(fd, 0)) > 0) { - long file_index, attr_file_index; - int stream; - char *attr, *p; - char Opts[MAXSTRING]; /* Verify Opts or MD5 signature */ - int do_MD5; - - Dmsg1(50, "Atts+MD5=%s\n", fd->msg); - if ((len = sscanf(fd->msg, "%ld %d %s %s", &file_index, &stream, - Opts, jcr->fname)) != 4) { - Jmsg3(jcr, M_FATAL, 0, _("birdmsglen, fd->msg); - jcr->JobStatus = JS_ErrorTerminated; - return 0; - } - /* - * Got attributes stream, decode it - */ - if (stream == STREAM_UNIX_ATTRIBUTES) { - attr_file_index = file_index; /* remember attribute file_index */ - len = strlen(fd->msg); - attr = &fd->msg[len+1]; - decode_stat(attr, &statf); /* decode file stat packet */ - do_MD5 = FALSE; - jcr->fn_printed = FALSE; - - Dmsg2(11, "dirdfname); - Dmsg1(20, "dirddb, jcr->fname, &fdbr); - - if (fdbr.FileId == 0) { - Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname); - Dmsg1(20, _("File not in catalog: %s\n"), jcr->fname); - stat = JS_Differences; - continue; - } else { - /* - * mark file record as visited by stuffing the - * current JobId, which is unique, into the FileIndex - */ - db_mark_file_record(jcr->db, fdbr.FileId, jcr->JobId); - } - - Dmsg2(20, "Found %s in catalog. Opts=%s\n", jcr->fname, Opts); - decode_stat(fdbr.LStat, &statc); /* decode catalog stat */ - strip_trailing_junk(jcr->fname); - /* - * Loop over options supplied by user and verify the - * fields he requests. - */ - for (p=Opts; *p; p++) { - switch (*p) { - case 'i': /* compare INODEs */ - if (statc.st_ino != statf.st_ino) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_ino differ. Cat: %x File: %x\n"), - statc.st_ino, statf.st_ino); - stat = JS_Differences; - } - break; - case 'p': /* permissions bits */ - if (statc.st_mode != statf.st_mode) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_mode differ. Cat: %x File: %x\n"), - statc.st_mode, statf.st_mode); - stat = JS_Differences; - } - break; - case 'n': /* number of links */ - if (statc.st_nlink != statf.st_nlink) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_nlink differ. Cat: %d File: %d\n"), - statc.st_nlink, statf.st_nlink); - stat = JS_Differences; - } - break; - case 'u': /* user id */ - if (statc.st_uid != statf.st_uid) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_uid differ. Cat: %d File: %d\n"), - statc.st_uid, statf.st_uid); - stat = JS_Differences; - } - break; - case 'g': /* group id */ - if (statc.st_gid != statf.st_gid) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_gid differ. Cat: %d File: %d\n"), - statc.st_gid, statf.st_gid); - stat = JS_Differences; - } - break; - case 's': /* size */ - if (statc.st_size != statf.st_size) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_size differ. Cat: %d File: %d\n"), - statc.st_size, statf.st_size); - stat = JS_Differences; - } - break; - case 'a': /* access time */ - if (statc.st_atime != statf.st_atime) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_atime differs\n")); - stat = JS_Differences; - } - break; - case 'm': - if (statc.st_mtime != statf.st_mtime) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_mtime differs\n")); - stat = JS_Differences; - } - break; - case 'c': /* ctime */ - if (statc.st_ctime != statf.st_ctime) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_ctime differs\n")); - stat = JS_Differences; - } - break; - case 'd': /* file size decrease */ - if (statc.st_size > statf.st_size) { - prt_fname(jcr); - Jmsg(jcr, M_INFO, 0, _(" st_size decrease. Cat: %d File: %d\n"), - statc.st_size, statf.st_size); - stat = JS_Differences; - } - break; - case '5': /* compare MD5 */ - do_MD5 = TRUE; - break; - case ':': - case 'V': - default: - break; - } - } - /* - * Got MD5 Signature from Storage daemon - * It came across in the Opts field. - */ - } else if (stream == STREAM_MD5_SIGNATURE) { - if (attr_file_index != file_index) { - Jmsg2(jcr, M_FATAL, 0, _("MD5 index %d not same as attributes %d\n"), - file_index, attr_file_index); - jcr->JobStatus = JS_ErrorTerminated; - return 0; - } - if (do_MD5) { - db_escape_string(buf, Opts, strlen(Opts)); - if (strcmp(buf, fdbr.MD5) != 0) { - /***FIXME**** fname may not be valid */ - prt_fname(jcr); - if (debug_level >= 10) { - Jmsg(jcr, M_INFO, 0, _(" MD5 not same. File=%s Cat=%s\n"), buf, fdbr.MD5); - } else { - Jmsg(jcr, M_INFO, 0, _(" MD5 differs.\n")); - } - stat = JS_Differences; - } - } - } - jcr->jr.JobFiles = file_index; - + long file_index, attr_file_index; + int stream; + char *attr, *p; + char Opts_MD5[MAXSTRING]; /* Verify Opts or MD5 signature */ + + fname = (char *)check_pool_memory_size(fname, fd->msglen); + jcr->fname = (char *)check_pool_memory_size(jcr->fname, fd->msglen); + Dmsg1(50, "Atts+MD5=%s\n", fd->msg); + if ((len = sscanf(fd->msg, "%ld %d %100s %s", &file_index, &stream, + Opts_MD5, fname)) != 4) { + Jmsg3(jcr, M_FATAL, 0, _("birdmsglen, fd->msg); + jcr->JobStatus = JS_ErrorTerminated; + return 0; + } + /* + * Got attributes stream, decode it + */ + if (stream == STREAM_UNIX_ATTRIBUTES) { + attr_file_index = file_index; /* remember attribute file_index */ + len = strlen(fd->msg); + attr = &fd->msg[len+1]; + decode_stat(attr, &statf); /* decode file stat packet */ + do_MD5 = FALSE; + jcr->fn_printed = FALSE; + strip_trailing_junk(fname); + strcpy(jcr->fname, fname); /* move filename into JCR */ + + Dmsg2(040, "dirdfname); + Dmsg1(20, "dirddb, jcr->fname, &fdbr)) { + Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname); + Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname); + stat = JS_Differences; + continue; + } else { + /* + * mark file record as visited by stuffing the + * current JobId, which is unique, into the FileIndex + */ + db_mark_file_record(jcr->db, fdbr.FileId, jcr->JobId); + } + + Dmsg3(100, "Found %s in catalog. inx=%d Opts=%s\n", jcr->fname, + file_index, Opts_MD5); + decode_stat(fdbr.LStat, &statc); /* decode catalog stat */ + /* + * Loop over options supplied by user and verify the + * fields he requests. + */ + for (p=Opts_MD5; *p; p++) { + switch (*p) { + case 'i': /* compare INODEs */ + if (statc.st_ino != statf.st_ino) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_ino differ. Cat: %x File: %x\n"), + statc.st_ino, statf.st_ino); + stat = JS_Differences; + } + break; + case 'p': /* permissions bits */ + if (statc.st_mode != statf.st_mode) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_mode differ. Cat: %x File: %x\n"), + statc.st_mode, statf.st_mode); + stat = JS_Differences; + } + break; + case 'n': /* number of links */ + if (statc.st_nlink != statf.st_nlink) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_nlink differ. Cat: %d File: %d\n"), + statc.st_nlink, statf.st_nlink); + stat = JS_Differences; + } + break; + case 'u': /* user id */ + if (statc.st_uid != statf.st_uid) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_uid differ. Cat: %d File: %d\n"), + statc.st_uid, statf.st_uid); + stat = JS_Differences; + } + break; + case 'g': /* group id */ + if (statc.st_gid != statf.st_gid) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_gid differ. Cat: %d File: %d\n"), + statc.st_gid, statf.st_gid); + stat = JS_Differences; + } + break; + case 's': /* size */ + if (statc.st_size != statf.st_size) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_size differ. Cat: %d File: %d\n"), + statc.st_size, statf.st_size); + stat = JS_Differences; + } + break; + case 'a': /* access time */ + if (statc.st_atime != statf.st_atime) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_atime differs\n")); + stat = JS_Differences; + } + break; + case 'm': + if (statc.st_mtime != statf.st_mtime) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_mtime differs\n")); + stat = JS_Differences; + } + break; + case 'c': /* ctime */ + if (statc.st_ctime != statf.st_ctime) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_ctime differs\n")); + stat = JS_Differences; + } + break; + case 'd': /* file size decrease */ + if (statc.st_size > statf.st_size) { + prt_fname(jcr); + Jmsg(jcr, M_INFO, 0, _(" st_size decrease. Cat: %d File: %d\n"), + statc.st_size, statf.st_size); + stat = JS_Differences; + } + break; + case '5': /* compare MD5 */ + Dmsg1(500, "set Do_MD5 for %s\n", jcr->fname); + do_MD5 = TRUE; + break; + case ':': + case 'V': + default: + break; + } + } + /* + * Got MD5 Signature from Storage daemon + * It came across in the Opts_MD5 field. + */ + } else if (stream == STREAM_MD5_SIGNATURE) { + Dmsg2(100, "stream=MD5 inx=%d fname=%s\n", file_index, jcr->fname); + /* + * When ever we get an MD5 signature is MUST have been + * preceded by an attributes record, which sets attr_file_index + */ + if (attr_file_index != file_index) { + Jmsg2(jcr, M_FATAL, 0, _("MD5 index %d not same as attributes %d\n"), + file_index, attr_file_index); + jcr->JobStatus = JS_ErrorTerminated; + return 0; + } + if (do_MD5) { + db_escape_string(buf, Opts_MD5, strlen(Opts_MD5)); + if (strcmp(buf, fdbr.MD5) != 0) { + prt_fname(jcr); + if (debug_level >= 10) { + Jmsg(jcr, M_INFO, 0, _(" MD5 not same. File=%s Cat=%s\n"), buf, fdbr.MD5); + } else { + Jmsg(jcr, M_INFO, 0, _(" MD5 differs.\n")); + } + stat = JS_Differences; + } + do_MD5 = FALSE; + } + } + jcr->jr.JobFiles = file_index; } if (n < 0) { Jmsg2(jcr, M_FATAL, 0, _("bdirdmsglen, fd->msg); jcr->JobStatus = JS_ErrorTerminated; return 0; } + /* Now find all the files that are missing -- i.e. all files in * the database where the FileIndex != current JobId */ @@ -519,6 +536,7 @@ msglen=%d msg=%s\n"), len, fd->msglen, fd->msg); "AND File.FileIndex!=%d AND File.PathId=Path.PathId " "AND File.FilenameId=Filename.FilenameId", last_full_id, jcr->JobId); + /* missing_handler is called for each file found */ db_sql_query(jcr->db, buf, missing_handler, (void *)jcr); if (jcr->fn_printed) { stat = JS_Differences; diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index 7374fe3a5..9bbcff6b4 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -309,26 +309,13 @@ static int save_file(FF_PKT *ff_pkt, void *ijcr) /* Terminate any MD5 signature and send it to Storage daemon and the Director */ if (gotMD5 && ff_pkt->flags & FO_MD5) { -#ifdef really_needed - char MD5buf[50]; /* 24 bytes should do */ -#endif - MD5Final(signature, &md5c); - - /* First do Storage daemon */ bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_MD5_SIGNATURE); Dmsg1(10, "bfiled>stored:header %s\n", sd->msg); memcpy(sd->msg, signature, 16); sd->msglen = 16; bnet_send(sd); bnet_sig(sd, BNET_EOD); /* end of MD5 */ - -#ifdef really_needed - /* Now do Director (single record) */ - bin_to_base64(MD5buf, (char *)signature, 16); /* encode 16 bytes */ - bnet_fsend(dir, "%ld %d %s X", jcr->JobFiles, STREAM_MD5_SIGNATURE, - MD5buf); -#endif gotMD5 = 0; } #ifdef really_needed diff --git a/bacula/src/filed/filed.c b/bacula/src/filed/filed.c index 7e7ee3be1..5a40ade9f 100644 --- a/bacula/src/filed/filed.c +++ b/bacula/src/filed/filed.c @@ -144,7 +144,7 @@ int main (int argc, char *argv[]) } - init_msg(NULL); + init_msg(NULL, NULL); parse_config(configfile); LockRes(); @@ -179,7 +179,7 @@ Without that I don't know who I am :-(\n"), configfile); me += 1000000; #endif - init_watchdog(); /* start watchdog thread */ + start_watchdog(); /* start watchdog thread */ /* Become server, and handle requests */ Dmsg1(10, "filed: listening on port %d\n", me->FDport); @@ -190,7 +190,7 @@ Without that I don't know who I am :-(\n"), configfile); void terminate_filed(int sig) { - term_watchdog(); + stop_watchdog(); if (configfile != NULL) { free(configfile); diff --git a/bacula/src/filed/status.c b/bacula/src/filed/status.c index da15c6fe6..832f7511f 100755 --- a/bacula/src/filed/status.c +++ b/bacula/src/filed/status.c @@ -71,8 +71,8 @@ static void do_status(void sendit(char *msg, int len, void *sarg), void *arg) } len = Mmsg(&msg, _(" Files=%s Bytes=%s Termination Status=%s\n"), - edit_uint_with_commas(last_job.JobFiles, b1), - edit_uint_with_commas(last_job.JobBytes, b2), + edit_uint64_with_commas(last_job.JobFiles, b1), + edit_uint64_with_commas(last_job.JobBytes, b2), termstat); sendit(msg, len, arg); } @@ -96,12 +96,12 @@ static void do_status(void sendit(char *msg, int len, void *sarg), void *arg) } bps = njcr->JobBytes / sec; len = Mmsg(&msg, _(" Files=%s Bytes=%s Bytes/sec=%s\n"), - edit_uint_with_commas(njcr->JobFiles, b1), - edit_uint_with_commas(njcr->JobBytes, b2), - edit_uint_with_commas(bps, b3)); + edit_uint64_with_commas(njcr->JobFiles, b1), + edit_uint64_with_commas(njcr->JobBytes, b2), + edit_uint64_with_commas(bps, b3)); sendit(msg, len, arg); len = Mmsg(&msg, _(" Files Examined=%s\n"), - edit_uint_with_commas(njcr->num_files_examined, b1)); + edit_uint64_with_commas(njcr->num_files_examined, b1)); sendit(msg, len, arg); if (njcr->JobFiles > 0) { len = Mmsg(&msg, _(" Processing file: %s\n"), njcr->last_fname); diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 67eab1f68..a083c0b1e 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -45,14 +45,11 @@ void do_verify(JCR *jcr) set_find_options(jcr->ff, jcr->incremental, jcr->mtime); Dmsg0(10, "Start find files\n"); /* Subroutine verify_file() is called for each file */ - if (!find_files(jcr->ff, verify_file, (void *)jcr)) { - /****FIXME**** error termination */ - Dmsg0(0, "========= Error return from find_files\n"); - } + find_files(jcr->ff, verify_file, (void *)jcr); Dmsg0(10, "End find files\n"); - dir->msglen = 0; - bnet_send(dir); /* signal end attributes to director */ + bnet_sig(dir, BNET_EOD); /* signal end of data */ + if (jcr->big_buf) { free(jcr->big_buf); jcr->big_buf = NULL; @@ -71,7 +68,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) { char attribs[MAXSTRING]; int32_t n; - int fid; + int fid, stat; struct MD5Context md5c; unsigned char signature[16]; BSOCK *sd, *dir; @@ -128,14 +125,18 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) return 1; } - if ((fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) { - ff_pkt->ff_errno = errno; - Jmsg(jcr, M_ERROR, -1, _(" Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno)); - return 1; + + if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode) && + ff_pkt->statp.st_size > 0) { + if ((fid = open(ff_pkt->fname, O_RDONLY | O_BINARY)) < 0) { + ff_pkt->ff_errno = errno; + Jmsg(jcr, M_NOTSAVED, -1, _("Cannot open %s: ERR=%s.\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno)); + return 1; + } + } else { + fid = -1; } - Dmsg2(50, "opened %s fid=%d\n", ff_pkt->fname, fid); - Dmsg1(10, "bfiled: sending %s to Director\n", ff_pkt->fname); encode_stat(attribs, &ff_pkt->statp); jcr->JobFiles++; /* increment number of files sent */ @@ -144,48 +145,63 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) ff_pkt->VerifyOpts[0] = 'V'; ff_pkt->VerifyOpts[1] = 0; } + + + /* + * Send file attributes to Director + * File_index + * Stream + * Verify Options + * Filename (full path) + * Encoded attributes + * Link name (if type==FT_LNK) + * For a directory, link is the same as fname, but with trailing + * slash. For a linked file, link is the link. + */ /* Send file attributes to Director (note different format than for Storage) */ + Dmsg2(400, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, ff_pkt->fname); if (ff_pkt->type == FT_LNK) { - dir->msglen = sprintf(dir->msg,"%d %d %s %s%c%s%c%s%c", jcr->JobFiles, + stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0); } else { - dir->msglen = sprintf(dir->msg,"%d %d %s %s%c%s%c%c", jcr->JobFiles, + stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 0, attribs, 0, 0); } Dmsg2(20, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg); - bnet_send(dir); /* send to Director */ - + if (!stat) { + Jmsg(jcr, M_ERROR, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir)); + if (fid >= 0) { + close(fid); + } + return 0; + } - /* - * If MD5 is requested, read the file and compute the MD5 - * - */ - if (ff_pkt->flags & FO_MD5) { + /* If file opened, compute MD5 */ + if (fid >= 0 && ff_pkt->flags & FO_MD5) { char MD5buf[50]; /* 24 should do */ MD5Init(&md5c); - if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode) && - ff_pkt->statp.st_size > 0) { - while ((n=read(fid, jcr->big_buf, jcr->buf_size)) > 0) { - MD5Update(&md5c, ((unsigned char *) jcr->big_buf), n); - jcr->JobBytes += n; - } - if (n < 0) { - Jmsg(jcr, M_ERROR, -1, _(" Error reading %s: ERR=%s\n"), ff_pkt->fname, strerror(ff_pkt->ff_errno)); - } + while ((n=read(fid, jcr->big_buf, jcr->buf_size)) > 0) { + MD5Update(&md5c, ((unsigned char *) jcr->big_buf), n); + 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)); } MD5Final(signature, &md5c); bin_to_base64(MD5buf, (char *)signature, 16); /* encode 16 bytes */ - dir->msglen = sprintf(dir->msg, "%d %d %s X", jcr->JobFiles, - STREAM_MD5_SIGNATURE, MD5buf); + Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, MD5buf); + bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_SIGNATURE, MD5buf, + jcr->JobFiles); Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg); - bnet_send(dir); /* send MD5 signature to Director */ } - close(fid); + if (fid >= 0) { + close(fid); + } return 1; } diff --git a/bacula/src/filed/win32/bin/mount.exe b/bacula/src/filed/win32/bin/mount.exe new file mode 100755 index 0000000000000000000000000000000000000000..cc7129caf5db2f213883ded682a4c1758764ca40 GIT binary patch literal 10240 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 K#~06x=f42rY18@u literal 0 Hc-jL100001 diff --git a/bacula/src/filed/win32/bin/sh.exe b/bacula/src/filed/win32/bin/sh.exe new file mode 100755 index 0000000000000000000000000000000000000000..b79811edb03ae7a7f77257b235329f70948dc1ba GIT binary patch literal 68608 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[0] = 0; jcr->errmsg = (char *) get_pool_memory(PM_MESSAGE); jcr->errmsg[0] = 0; - init_msg(jcr); /* init job message chain */ jobs = jcr; V(mutex); return jcr; @@ -118,7 +117,9 @@ static void free_common_jcr(JCR *jcr) break; } pthread_mutex_destroy(&jcr->mutex); + close_msg(jcr); /* close messages for this job */ + /* do this after closing messages */ if (jcr->client_name) { free(jcr->client_name); @@ -134,7 +135,6 @@ static void free_common_jcr(JCR *jcr) free_pool_memory(jcr->VolumeName); jcr->VolumeName = NULL; } - close_msg(jcr); /* close messages for this job */ if (jcr->dir_bsock) { bnet_close(jcr->dir_bsock); diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index 622f5ed0e..ec5cb3806 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -46,16 +46,7 @@ FILE *con_fd = NULL; /* Imported functions */ -/* This chain contains all the possible destinations */ -DEST *dest_chain = NULL; -/* - * send_msg has a bit set for each type that has a - * message destination. The info in send_msg[] is - * contained in the dest structures, - * but we keep it here for speed so that we don't have to - * search all the structures in all the cases. - */ -char send_msg[nbytes_for_bits(M_MAX+1)]; +static MSGS daemon_msg; /* global messages */ /* * Set daemon name. Also, find canonical execution @@ -131,28 +122,32 @@ void my_name_is(int argc, char *argv[], char *name) /* Initialize message handler */ void -init_msg(void *vjcr) +init_msg(void *vjcr, MSGS *msg) { DEST *d, *dnew, *temp_chain = NULL; JCR *jcr = (JCR *)vjcr; + if (!msg) { /* If nothing specified, use */ + msg = &daemon_msg; /* daemon global message resource */ + } if (!jcr) { - memset(send_msg, 0, sizeof(send_msg)); /* init daemon stuff */ + memset(msg, 0, sizeof(msg)); /* init daemon global message */ } else { /* init for job */ /* Walk down the global chain duplicating it * for the current Job. No need to duplicate * the attached strings. */ - for (d=dest_chain; d; d=d->next) { + for (d=daemon_msg.dest_chain; d; d=d->next) { dnew = (DEST *) malloc(sizeof(DEST)); memcpy(dnew, d, sizeof(DEST)); dnew->next = temp_chain; dnew->fd = NULL; + dnew->mail_filename = NULL; temp_chain = dnew; } jcr->dest_chain = temp_chain; - memcpy(jcr->send_msg, send_msg, sizeof(send_msg)); + memcpy(jcr->send_msg, daemon_msg.send_msg, sizeof(daemon_msg.send_msg)); } } @@ -189,30 +184,30 @@ void init_console_msg(char *wd) * but in the case of MAIL is a space separated list of * email addresses, ... */ -void add_msg_dest(int dest_code, int msg_type, char *where, char *mail_cmd) +void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd) { DEST *d; /* First search the existing chain and see if we * can simply add this msg_type to an existing entry. */ - for (d=dest_chain; d; d=d->next) { + for (d=daemon_msg.dest_chain; d; d=d->next) { if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) || (strcmp(where, d->where) == 0))) { Dmsg4(200, "Add to existing d=%x msgtype=%d destcode=%d where=%s\n", d, msg_type, dest_code, where); set_bit(msg_type, d->msg_types); - set_bit(msg_type, send_msg); /* set msg_type bit in our local */ + set_bit(msg_type, daemon_msg.send_msg); /* set msg_type bit in our local */ return; } } /* Not found, create a new entry */ d = (DEST *) malloc(sizeof(DEST)); memset(d, 0, sizeof(DEST)); - d->next = dest_chain; + d->next = daemon_msg.dest_chain; d->dest_code = dest_code; set_bit(msg_type, d->msg_types); /* set type bit in structure */ - set_bit(msg_type, send_msg); /* set type bit in our local */ + set_bit(msg_type, daemon_msg.send_msg); /* set type bit in our local */ if (where) { d->where = bstrdup(where); } @@ -222,7 +217,7 @@ void add_msg_dest(int dest_code, int msg_type, char *where, char *mail_cmd) Dmsg5(200, "add new d=%x msgtype=%d destcode=%d where=%s mailcmd=%s\n", d, msg_type, dest_code, where?where:"(null)", d->mail_cmd?d->mail_cmd:"(null)"); - dest_chain = d; + daemon_msg.dest_chain = d; } /* @@ -230,11 +225,11 @@ void add_msg_dest(int dest_code, int msg_type, char *where, char *mail_cmd) * * Remove a message destination */ -void rem_msg_dest(int dest_code, int msg_type, char *where) +void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where) { DEST *d; - for (d=dest_chain; d; d=d->next) { + for (d=daemon_msg.dest_chain; d; d=d->next) { Dmsg2(200, "Remove_msg_dest d=%x where=%s\n", d, d->where); if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) && ((where == NULL && d->where == NULL) || @@ -525,14 +520,14 @@ void close_msg(void *vjcr) rem_temp_file: /* Remove temp file */ fclose(d->fd); - make_unique_mail_filename(jcr, &cmd, d); - Dmsg1(200, "unlink: %s\n", cmd); - unlink(cmd); + unlink(d->mail_filename); + free_pool_memory(d->mail_filename); + d->mail_filename = NULL; break; default: break; } - d->fd = 0; + d->fd = NULL; } old = d; /* save pointer to release */ d = d->next; /* point to next buffer */ @@ -551,12 +546,17 @@ void term_msg() { DEST *d, *n; - for (d=dest_chain; d; d=n) { + for (d=daemon_msg.dest_chain; d; d=n) { if (d->fd) { if (d->dest_code == MD_FILE || d->dest_code == MD_APPEND) { fclose(d->fd); /* close open file descriptor */ + d->fd = NULL; } else if (d->dest_code == MD_MAIL || d->dest_code == MD_MAIL_ON_ERROR) { - pclose(d->fd); /* close open pipe */ + fclose(d->fd); + d->fd = NULL; + unlink(d->mail_filename); + free_pool_memory(d->mail_filename); + d->mail_filename = NULL; } } n = d->next; @@ -603,7 +603,7 @@ void dispatch_message(void *vjcr, int type, int level, char *buf) if (jcr) { d = jcr->dest_chain; /* use job message chain */ } else { - d = dest_chain; /* use global chain */ + d = daemon_msg.dest_chain; /* use global chain */ } for ( ; d; d=d->next) { if (bit_is_set(type, d->msg_types)) { @@ -646,22 +646,22 @@ void dispatch_message(void *vjcr, int type, int level, char *buf) fputs(buf, d->fd); /* Messages to the operator go one at a time */ pclose(d->fd); + d->fd = NULL; } break; case MD_MAIL: case MD_MAIL_ON_ERROR: Dmsg1(200, "MAIL for following err: %s\n", buf); if (!d->fd) { - char *name = (char *) get_pool_memory(PM_MESSAGE); + char *name = (char *)get_pool_memory(PM_MESSAGE); make_unique_mail_filename(jcr, &name, d); d->fd = fopen(name, "w+"); - Dmsg2(100, "Open mail file %d: %s\n", d->fd, name); if (!d->fd) { Emsg2(M_ERROR, 0, "fopen %s failed: ERR=%s\n", name, strerror(errno)); free_pool_memory(name); break; } - free_pool_memory(name); + d->mail_filename = name; } len = strlen(buf); if (len > d->max_len) { @@ -779,7 +779,7 @@ e_msg(char *file, int line, int type, int level, char *fmt,...) * Check if we have a message destination defined. * We always report M_ABORT */ - if (type != M_ABORT && !bit_is_set(type, send_msg)) + if (type != M_ABORT && !bit_is_set(type, daemon_msg.send_msg)) return; /* no destination */ switch (type) { case M_ABORT: diff --git a/bacula/src/lib/message.h b/bacula/src/lib/message.h index 99e5ed5a0..6d3d9c5bd 100644 --- a/bacula/src/lib/message.h +++ b/bacula/src/lib/message.h @@ -57,6 +57,7 @@ typedef struct s_dest { char msg_types[nbytes_for_bits(M_MAX+1)]; /* message type mask */ char *where; /* filename/program name */ char *mail_cmd; /* mail command */ + char *mail_filename; /* unique mail filename */ } DEST; /* Message Destination values for dest field of DEST */ diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index 5017929f4..6978470c2 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -60,29 +60,29 @@ extern int res_all_size; static int res_locked = 0; /* set when resource chains locked */ /* Forward referenced subroutines */ -static void scan_types(LEX *lc, int dest, char *where, char *cmd); +static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd); /* Common Resource definitions */ /* Message resource directives - * name handler store_addr code flags default_value + * name handler value code flags default_value */ struct res_items msgs_items[] = { {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0}, {"description", store_str, ITEM(res_msgs.hdr.desc), 0, 0, 0}, {"mailcommand", store_str, ITEM(res_msgs.mail_cmd), 0, 0, 0}, {"operatorcommand", store_str, ITEM(res_msgs.operator_cmd), 0, 0, 0}, - {"syslog", store_msgs, NULL, MD_SYSLOG, 0, 0}, - {"mail", store_msgs, NULL, MD_MAIL, 0, 0}, - {"mailonerror", store_msgs, NULL, MD_MAIL_ON_ERROR, 0, 0}, - {"file", store_msgs, NULL, MD_FILE, 0, 0}, - {"append", store_msgs, NULL, MD_APPEND, 0, 0}, - {"stdout", store_msgs, NULL, MD_STDOUT, 0, 0}, - {"stderr", store_msgs, NULL, MD_STDERR, 0, 0}, - {"director", store_msgs, NULL, MD_DIRECTOR, 0, 0}, - {"console", store_msgs, NULL, MD_CONSOLE, 0, 0}, - {"operator", store_msgs, NULL, MD_OPERATOR, 0, 0}, + {"syslog", store_msgs, ITEM(res_msgs), MD_SYSLOG, 0, 0}, + {"mail", store_msgs, ITEM(res_msgs), MD_MAIL, 0, 0}, + {"mailonerror", store_msgs, ITEM(res_msgs), MD_MAIL_ON_ERROR, 0, 0}, + {"file", store_msgs, ITEM(res_msgs), MD_FILE, 0, 0}, + {"append", store_msgs, ITEM(res_msgs), MD_APPEND, 0, 0}, + {"stdout", store_msgs, ITEM(res_msgs), MD_STDOUT, 0, 0}, + {"stderr", store_msgs, ITEM(res_msgs), MD_STDERR, 0, 0}, + {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0}, + {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0}, + {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0}, {NULL, NULL, NULL, 0} }; @@ -151,12 +151,12 @@ void init_resource(int type, struct res_items *items) if (items[i].handler == store_yesno) { *(int *)(items[i].value) |= items[i].code; } else if (items[i].handler == store_pint || - items[i].handler == store_int || - items[i].handler == store_time) { + items[i].handler == store_int) { *(int *)(items[i].value) = items[i].default_value; } else if (items[i].handler == store_int64) { *(int64_t *)(items[i].value) = items[i].default_value; - } else if (items[i].handler == store_size) { + } else if (items[i].handler == store_size || + items[i].handler == store_time) { *(uint64_t *)(items[i].value) = items[i].default_value; } } @@ -182,7 +182,7 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass) case MD_STDERR: case MD_SYSLOG: /* syslog */ case MD_CONSOLE: - scan_types(lc, item->code, NULL, NULL); + scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL); break; case MD_OPERATOR: /* send to operator */ case MD_DIRECTOR: /* send to Director */ @@ -220,7 +220,7 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass) break; } Dmsg1(200, "mail_cmd=%s\n", cmd); - scan_types(lc, item->code, dest, cmd); + scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd); free_pool_memory(dest); Dmsg0(200, "done with dest codes\n"); break; @@ -240,7 +240,7 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass) if (token != T_EQUALS) { scan_err1(lc, "expected an =, got: %s", lc->str); } - scan_types(lc, item->code, dest, NULL); + scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL); free_pool_memory(dest); Dmsg0(200, "done with dest codes\n"); break; @@ -261,7 +261,7 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass) * (WARNING, ERROR, FATAL, INFO, ...) with an appropriate * destination (MAIL, FILE, OPERATOR, ...) */ -static void scan_types(LEX *lc, int dest_code, char *where, char *cmd) +static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd) { int token, i, found, quit, is_not; int msg_type; @@ -293,13 +293,13 @@ static void scan_types(LEX *lc, int dest_code, char *where, char *cmd) if (msg_type == M_MAX+1) { /* all? */ for (i=1; i<=M_MAX; i++) { /* yes set all types */ - add_msg_dest(dest_code, i, where, cmd); + add_msg_dest(msg, dest_code, i, where, cmd); } } else { if (is_not) { - rem_msg_dest(dest_code, msg_type, where); + rem_msg_dest(msg, dest_code, msg_type, where); } else { - add_msg_dest(dest_code, msg_type, where, cmd); + add_msg_dest(msg, dest_code, msg_type, where, cmd); } } if (lc->ch != ',') { @@ -457,11 +457,11 @@ void store_int(LEX *lc, struct res_items *item, int index, int pass) int token; token = lex_get_token(lc); - if (token != T_NUMBER) { + if (token != T_NUMBER || !is_a_number(lc->str)) { scan_err1(lc, "expected an integer number, got: %s", lc->str); } else { errno = 0; - *(int *)(item->value) = strtol(lc->str, NULL, 0); + *(int *)(item->value) = (int)strtod(lc->str, NULL); if (errno != 0) { scan_err1(lc, "expected an integer number, got: %s", lc->str); } @@ -476,11 +476,11 @@ void store_pint(LEX *lc, struct res_items *item, int index, int pass) int token; token = lex_get_token(lc); - if (token != T_NUMBER) { - scan_err1(lc, "expected an integer number, got: %s", lc->str); + if (token != T_NUMBER || !is_a_number(lc->str)) { + scan_err1(lc, "expected a positive integer number, got: %s", lc->str); } else { errno = 0; - token = strtol(lc->str, NULL, 0); + token = (int)strtod(lc->str, NULL); if (errno != 0 || token < 0) { scan_err1(lc, "expected a postive integer number, got: %s", lc->str); } @@ -497,7 +497,8 @@ void store_int64(LEX *lc, struct res_items *item, int index, int pass) int token; token = lex_get_token(lc); - if (token != T_NUMBER) { + Dmsg2(400, "int64=:%s: %f\n", lc->str, strtod(lc->str, NULL)); + if (token != T_NUMBER || !is_a_number(lc->str)) { scan_err1(lc, "expected an integer number, got: %s", lc->str); } else { errno = 0; @@ -514,14 +515,16 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass) { int token, i, ch; uint64_t value; - int mod[] = {'k', 'm', 'g'}; - uint64_t mult[] = {1024, /* kilobyte */ + int mod[] = {'*', 'k', 'm', 'g', 0}; /* first item * not used */ + uint64_t mult[] = {1, /* byte */ + 1024, /* kilobyte */ 1048576, /* megabyte */ 1073741824}; /* gigabyte */ #ifdef we_have_a_compiler_that_works - int mod[] = {'k', 'm', 'g', 't'}; - uint64_t mult[] = {1024, /* kilobyte */ + int mod[] = {'*', 'k', 'm', 'g', 't', 0}; + uint64_t mult[] = {1, /* byte */ + 1024, /* kilobyte */ 1048576, /* megabyte */ 1073741824, /* gigabyte */ 1099511627776};/* terabyte */ @@ -532,9 +535,10 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass) errno = 0; switch (token) { case T_NUMBER: + Dmsg2(400, "size num=:%s: %f\n", lc->str, strtod(lc->str, NULL)); value = (uint64_t)strtod(lc->str, NULL); if (errno != 0 || token < 0) { - scan_err1(lc, "expected a size, got: %s", lc->str); + scan_err1(lc, "expected a size number, got: %s", lc->str); } *(uint64_t *)(item->value) = value; break; @@ -547,25 +551,27 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass) if (ISUPPER(ch)) { ch = tolower(ch); } - while (i < (int)sizeof(mod)) { + while (mod[++i] != 0) { if (ch == mod[i]) { lc->str_len--; lc->str[lc->str_len] = 0; /* strip modifier */ break; } - i++; } } - if (i >= (int)sizeof(mod)) { - scan_err1(lc, "expected a size, got: %s", lc->str); + if (mod[i] == 0 || !is_a_number(lc->str)) { + scan_err1(lc, "expected a size number, got: %s", lc->str); } + Dmsg3(400, "size str=:%s: %f i=%d\n", lc->str, strtod(lc->str, NULL), i); + value = (uint64_t)strtod(lc->str, NULL); Dmsg1(400, "Int value = %d\n", (int)value); if (errno != 0 || value < 0) { - scan_err1(lc, "expected a size, got: %s", lc->str); + scan_err1(lc, "expected a size number, got: %s", lc->str); } - *(uint64_t *)(item->value) = (uint64_t)(strtod(lc->str, NULL) * mult[i]); - Dmsg1(400, "Full value = %f\n", strtod(lc->str, NULL) * mult[i]); + *(uint64_t *)(item->value) = value * mult[i]; + Dmsg2(400, "Full value = %f %" lld "\n", strtod(lc->str, NULL) * mult[i], + value *mult[i]); break; default: scan_err1(lc, "expected a size, got: %s", lc->str); @@ -580,45 +586,25 @@ void store_size(LEX *lc, struct res_items *item, int index, int pass) /* Store a time period in seconds */ void store_time(LEX *lc, struct res_items *item, int index, int pass) { - int token, i, ch, value; - int mod[] = {'s', 'm', 'h', 'd', 'w', 'o', 'q', 'y'}; - int mult[] = {1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30, - 60*60*24*91, 60*60*24*365}; + int token; + btime_t value; token = lex_get_token(lc); errno = 0; switch (token) { case T_NUMBER: - token = strtol(lc->str, NULL, 0); - if (errno != 0 || token < 0) { + value = (btime_t)strtod(lc->str, NULL); + if (errno != 0 || value < 0) { scan_err1(lc, "expected a time period, got: %s", lc->str); } - *(int *)(item->value) = token; + *(btime_t *)(item->value) = value; break; case T_IDENTIFIER: case T_STRING: - /* Look for modifier */ - ch = lc->str[lc->str_len - 1]; - i = 0; - if (ISALPHA(ch)) { - if (ISUPPER(ch)) { - ch = tolower(ch); - } - while (i < (int)sizeof(mod)) { - if (ch == mod[i]) { - break; - } - i++; - } - } - if (i >= (int)sizeof(mod)) { - scan_err1(lc, "expected a time period, got: %s", lc->str); - } - value = strtol(lc->str, NULL, 0); - if (errno != 0 || value < 0) { + if (!string_to_btime(lc->str, &value)) { scan_err1(lc, "expected a time period, got: %s", lc->str); } - *(int *)(item->value) = value * mult[i]; + *(btime_t *)(item->value) = value; break; default: scan_err1(lc, "expected a time period, got: %s", lc->str); diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index fb1091ca4..cc114032e 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -22,126 +22,132 @@ */ /* base64.c */ -void base64_init __PROTO((void)); -int to_base64 __PROTO((intmax_t value, char *where)); -int from_base64 __PROTO((intmax_t *value, char *where)); -void encode_stat __PROTO((char *buf, struct stat *statp)); -void decode_stat __PROTO((char *buf, struct stat *statp)); -int bin_to_base64 __PROTO((char *buf, char *bin, int len)); +void base64_init __PROTO((void)); +int to_base64 __PROTO((intmax_t value, char *where)); +int from_base64 __PROTO((intmax_t *value, char *where)); +void encode_stat __PROTO((char *buf, struct stat *statp)); +void decode_stat __PROTO((char *buf, struct stat *statp)); +int bin_to_base64 __PROTO((char *buf, char *bin, int len)); /* bmisc.c */ -void *b_malloc (char *file, int line, size_t size); +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, ...); -int create_pid_file (char *dir, char *progname, int port, char *errmsg); -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, ...); +int create_pid_file (char *dir, char *progname, int port, char *errmsg); +int delete_pid_file (char *dir, char *progname, int port); /* bnet.c */ -int32_t bnet_recv __PROTO((BSOCK *bsock)); -int bnet_send __PROTO((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 __PROTO((BSOCK *bsock)); -BSOCK * init_bsock __PROTO((int sockfd, char *who, char *ip, int port)); -BSOCK * dup_bsock __PROTO((BSOCK *bsock)); -void term_bsock __PROTO((BSOCK *bsock)); -char * bnet_strerror __PROTO((BSOCK *bsock)); -char * bnet_sig_to_ascii __PROTO((BSOCK *bsock)); -int bnet_wait_data __PROTO((BSOCK *bsock, int sec)); +int32_t bnet_recv __PROTO((BSOCK *bsock)); +int bnet_send __PROTO((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 __PROTO((BSOCK *bsock)); +BSOCK * init_bsock __PROTO((int sockfd, char *who, char *ip, int port)); +BSOCK * dup_bsock __PROTO((BSOCK *bsock)); +void term_bsock __PROTO((BSOCK *bsock)); +char * bnet_strerror __PROTO((BSOCK *bsock)); +char * bnet_sig_to_ascii __PROTO((BSOCK *bsock)); +int bnet_wait_data __PROTO((BSOCK *bsock, int sec)); /* 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); /* create_file.c */ int create_file(void *jcr, char *fname, char *ofile, char *lname, - int type, struct stat *statp, int *ofd); + int type, struct stat *statp, int *ofd); int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type, - struct stat *statp); + struct stat *statp); /* crc32.c */ uint32_t bcrc32(uint8_t *buf, int len); /* daemon.c */ -void daemon_start __PROTO(()); +void daemon_start __PROTO(()); /* lex.c */ -LEX * lex_close_file __PROTO((LEX *lf)); -LEX * lex_open_file __PROTO((LEX *lf, char *fname)); -int lex_get_char __PROTO((LEX *lf)); -void lex_unget_char __PROTO((LEX *lf)); -char * lex_tok_to_str __PROTO((int token)); -int lex_get_token __PROTO((LEX *lf)); +LEX * lex_close_file __PROTO((LEX *lf)); +LEX * lex_open_file __PROTO((LEX *lf, char *fname)); +int lex_get_char __PROTO((LEX *lf)); +void lex_unget_char __PROTO((LEX *lf)); +char * lex_tok_to_str __PROTO((int token)); +int lex_get_token __PROTO((LEX *lf)); /* makepath.c */ int make_path( - void *jcr, - const char *argpath, - int mode, - int parent_mode, - uid_t owner, - gid_t group, - int preserve_existing, - char *verbose_fmt_string); + void *jcr, + const char *argpath, + int mode, + int parent_mode, + uid_t owner, + gid_t group, + int preserve_existing, + char *verbose_fmt_string); /* message.c */ -void my_name_is __PROTO((int argc, char *argv[], char *name)); -void init_msg __PROTO((void *jcr)); -void term_msg __PROTO((void)); -void close_msg __PROTO((void *jcr)); -void add_msg_dest __PROTO((int dest, int type, char *where, char *dest_code)); -void rem_msg_dest __PROTO((int dest, int type, char *where)); -void Jmsg (void *jcr, int type, int level, char *fmt, ...); -void dispatch_message __PROTO((void *jcr, int type, int level, char *buf)); -void init_console_msg __PROTO((char *wd)); +void my_name_is __PROTO((int argc, char *argv[], char *name)); +void init_msg __PROTO((void *jcr, MSGS *msg)); +void term_msg __PROTO((void)); +void close_msg __PROTO((void *jcr)); +void add_msg_dest __PROTO((MSGS *msg, int dest, int type, char *where, char *dest_code)); +void rem_msg_dest __PROTO((MSGS *msg, int dest, int type, char *where)); +void Jmsg (void *jcr, int type, int level, char *fmt, ...); +void dispatch_message __PROTO((void *jcr, int type, int level, char *buf)); +void init_console_msg __PROTO((char *wd)); /* bnet_server.c */ -void bnet_thread_server(int port, int max_clients, workq_t *client_wq, - void handle_client_request(void *bsock)); -void bnet_server __PROTO((int port, void handle_client_request(BSOCK *bsock))); -int net_connect __PROTO((int port)); -BSOCK * bnet_bind __PROTO((int port)); -BSOCK * bnet_accept __PROTO((BSOCK *bsock, char *who)); +void bnet_thread_server(int port, int max_clients, workq_t *client_wq, + void handle_client_request(void *bsock)); +void bnet_server __PROTO((int port, void handle_client_request(BSOCK *bsock))); +int net_connect __PROTO((int port)); +BSOCK * bnet_bind __PROTO((int port)); +BSOCK * bnet_accept __PROTO((BSOCK *bsock, char *who)); /* signal.c */ -void init_signals __PROTO((void terminate(int sig))); -void init_stack_dump (void); +void init_signals __PROTO((void terminate(int sig))); +void init_stack_dump (void); /* util.c */ -void lcase __PROTO((char *str)); -void bash_spaces __PROTO((char *str)); -void unbash_spaces __PROTO((char *str)); -void strip_trailing_junk __PROTO((char *str)); -void strip_trailing_slashes __PROTO((char *dir)); -int skip_spaces __PROTO((char **msg)); -int skip_nonspaces __PROTO((char **msg)); -int fstrsch __PROTO((char *a, char *b)); -char * encode_time __PROTO((time_t time, char *buf)); -char * encode_mode __PROTO((mode_t mode, char *buf)); -char * edit_uint_with_commas __PROTO((uint64_t val, char *buf)); -char * add_commas __PROTO((char *val, char *buf)); -int do_shell_expansion(char *name); +void lcase __PROTO((char *str)); +void bash_spaces __PROTO((char *str)); +void unbash_spaces __PROTO((char *str)); +void strip_trailing_junk __PROTO((char *str)); +void strip_trailing_slashes __PROTO((char *dir)); +int skip_spaces __PROTO((char **msg)); +int skip_nonspaces __PROTO((char **msg)); +int fstrsch __PROTO((char *a, char *b)); +char * encode_time __PROTO((time_t time, char *buf)); +char * encode_mode __PROTO((mode_t mode, char *buf)); +char * edit_uint64_with_commas __PROTO((uint64_t val, char *buf)); +char * add_commas __PROTO((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 string_to_btime(char *str, btime_t *value); +char *edit_btime(btime_t val, char *buf); + + /* - *void print_ls_output __PROTO((char *fname, char *lname, int type, struct stat *statp)); + *void print_ls_output __PROTO((char *fname, char *lname, int type, struct stat *statp)); */ /* watchdog.c */ -int init_watchdog(void); -int term_watchdog(void); +int start_watchdog(void); +int stop_watchdog(void); diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index e4d41b632..de9fdfe69 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -62,7 +62,7 @@ static void signal_handler(int sig) struct sigaction sigdefault; if (already_dead) { - abort(); + _exit(1); } already_dead = TRUE; if (sig == SIGTERM) { @@ -125,7 +125,6 @@ static void signal_handler(int sig) Dmsg0(500, "Doing sleep\n"); sleep(30); } - abort(); /* produce dump */ } #endif diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index ab82295e9..1235e7ffb 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -33,15 +33,127 @@ */ /* - * Edit a number with commas, the supplied buffer - * must be at least 27 bytes long. + * Convert a string to btime_t (64 bit seconds) + * Returns 0: if error + 1: if OK, and value stored in value */ -char *edit_uint_with_commas(uint64_t val, char *buf) +int string_to_btime(char *str, btime_t *value) +{ + int i, ch, len; + btime_t val; + static int mod[] = {'*', 's', 'm', 'h', 'd', 'w', 'o', 'q', 'y', 0}; + static int mult[] = {1, 1, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*30, + 60*60*24*91, 60*60*24*365}; + + /* Look for modifier */ + len = strlen(str); + ch = str[len - 1]; + i = 0; + if (ISALPHA(ch)) { + if (ISUPPER(ch)) { + ch = tolower(ch); + } + while (mod[++i] != 0) { + if (ch == mod[i]) { + len--; + str[len] = 0; /* strip modifier */ + break; + } + } + } + if (mod[i] == 0 || !is_a_number(str)) { + return 0; + } + val = (btime_t)strtod(str, NULL); + if (errno != 0 || val < 0) { + return 0; + } + *value = val * mult[i]; + return 1; + +} + +char *edit_btime(btime_t val, char *buf) +{ + char mybuf[30]; + static int mult[] = {60*60*24*365, 60*60*24*30, 60*60*24, 60*60, 60}; + static char *mod[] = {"year", "month", "day", "hour", "min"}; + int i; + uint32_t times; + + *buf = 0; + for (i=0; i<5; i++) { + times = val / mult[i]; + if (times > 0) { + val = val - (btime_t)times * mult[i]; + sprintf(mybuf, "%d %s%s ", times, mod[i], times>1?"s":""); + strcat(buf, mybuf); + } + } + if (val == 0 && strlen(buf) == 0) { + strcat(buf, "0 secs"); + } else if (val != 0) { + sprintf(mybuf, "%d sec%s", (uint32_t)val, val>1?"s":""); + strcat(buf, mybuf); + } + return buf; +} + +/* + * Check if specified string is a number or not. + * Taken from SQLite, cool, thanks. + */ +int is_a_number(const char *n) +{ + int digit_seen = 0; + + if( *n == '-' || *n == '+' ) { + n++; + } + while (ISDIGIT(*n)) { + digit_seen = 1; + n++; + } + if (digit_seen && *n == '.') { + n++; + while (ISDIGIT(*n)) { n++; } + } + if (digit_seen && (*n == 'e' || *n == 'E') + && (ISDIGIT(n[1]) || ((n[1]=='-' || n[1] == '+') && ISDIGIT(n[2])))) { + n += 2; /* skip e- or e+ or e digit */ + while (ISDIGIT(*n)) { n++; } + } + return digit_seen && *n==0; +} + + +/* + * Edit an integer number with commas, the supplied buffer + * must be at least 27 bytes long. The incoming number + * is always widened to 64 bits. + */ +char *edit_uint64_with_commas(uint64_t val, char *buf) { sprintf(buf, "%" lld, val); return add_commas(buf, buf); } +/* + * Edit an integer number, the supplied buffer + * must be at least 27 bytes long. The incoming number + * is always widened to 64 bits. + */ +char *edit_uint64(uint64_t val, char *buf) +{ + sprintf(buf, "%" lld, val); + return buf; +} + + +/* + * Add commas to a string, which is presumably + * a number. + */ char *add_commas(char *val, char *buf) { int len, nc; @@ -70,8 +182,7 @@ char *add_commas(char *val, char *buf) /* Convert a string in place to lower case */ -void -lcase(char *str) +void lcase(char *str) { while (*str) { if (ISUPPER(*str)) diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index 1bcccc4ef..9cda310aa 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -56,12 +56,12 @@ static void timeout_handler(int sig) /* - * Initialize watchdog thread + * Start watchdog thread * * Returns: 0 on success * errno on failure */ -int init_watchdog(void) +int start_watchdog(void) { int stat; pthread_t wdid; @@ -94,7 +94,7 @@ int init_watchdog(void) * Returns: 0 on success * errno on failure */ -int term_watchdog(void) +int stop_watchdog(void) { int stat; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index a7d3c19c0..b064dd907 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -30,7 +30,7 @@ /* Requests sent to the Director */ static char Find_media[] = "CatReq Job=%s FindMedia=%d\n"; -static char Find_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s\n"; +static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s\n"; static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s\ VolJobs=%d VolFiles=%d VolBlocks=%d VolBytes=%" lld " VolMounts=%d\ @@ -46,7 +46,7 @@ static char Job_status[] = "3012 Job %s jobstatus %d\n"; /* Responses received from the Director */ static char OK_media[] = "1000 OK VolName=%127s VolJobs=%d VolFiles=%d\ VolBlocks=%d VolBytes=%" lld " VolMounts=%d VolErrors=%d VolWrites=%d\ - VolMaxBytes=%" lld " VolCapacityBytes=%" lld "\n"; + VolMaxBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s\n"; static char OK_update[] = "1000 OK UpdateMedia\n"; @@ -80,7 +80,7 @@ static int do_request_volume_info(JCR *jcr) &vol->VolCatBlocks, &vol->VolCatBytes, &vol->VolCatMounts, &vol->VolCatErrors, &vol->VolCatWrites, &vol->VolCatMaxBytes, - &vol->VolCatCapacityBytes) != 10) { + &vol->VolCatCapacityBytes, vol->VolCatStatus) != 11) { Dmsg1(30, "Bad response from Dir: %s\n", dir->msg); return 0; } @@ -88,7 +88,6 @@ static int do_request_volume_info(JCR *jcr) strcpy(jcr->VolumeName, vol->VolCatName); /* set desired VolumeName */ Dmsg1(200, "Got Volume=%s\n", vol->VolCatName); - strcpy(vol->VolCatStatus, "Append"); return 1; } @@ -97,7 +96,8 @@ static int do_request_volume_info(JCR *jcr) * Get Volume info for a specific volume from the Director's Database * * Returns: 1 on success (not Director guarantees that Pool and MediaType - * are correct and VolStatus==Append) + * are correct and VolStatus==Append or + * VolStatus==Recycle) * 0 on failure * * Volume information returned in jcr @@ -109,7 +109,7 @@ int dir_get_volume_info(JCR *jcr) strcpy(jcr->VolCatInfo.VolCatName, jcr->VolumeName); Dmsg1(200, "dir_get_volume_info=%s\n", jcr->VolCatInfo.VolCatName); bash_spaces(jcr->VolCatInfo.VolCatName); - bnet_fsend(dir, Find_Vol_Info, jcr->Job, jcr->VolCatInfo.VolCatName); + bnet_fsend(dir, Get_Vol_Info, jcr->Job, jcr->VolCatInfo.VolCatName); return do_request_volume_info(jcr); } diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 7a20cf100..a3c21f92f 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -121,7 +121,7 @@ int main (int argc, char *argv[]) * Ensure that every message is always printed */ for (i=1; i<=M_MAX; i++) { - add_msg_dest(MD_STDOUT, i, NULL, NULL); + add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL); } jcr = new_jcr(sizeof(JCR), my_free_jcr); diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index de60d1af7..5fa23b504 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -148,7 +148,7 @@ int main (int argc, char *argv[]) * Ensure that every message is always printed */ for (i=1; i<=M_MAX; i++) { - add_msg_dest(MD_STDOUT, i, NULL, NULL); + add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL); } /* Try default device */ diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 7804241fd..6738d866c 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -87,7 +87,7 @@ int main (int argc, char *argv[]) * Ensure that every message is always printed */ for (i=1; i<=M_MAX; i++) { - add_msg_dest(MD_STDOUT, i, NULL, NULL); + add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL); } jcr = new_jcr(sizeof(JCR), my_free_jcr); diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 8aa3b4ba1..b6e606a2c 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -164,7 +164,7 @@ int main(int argc, char *argv[]) * Ensure that every message is always printed */ for (i=1; i<=M_MAX; i++) { - add_msg_dest(MD_STDOUT, i, NULL, NULL); + add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL); } diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index ead1ddf4d..f71b77f83 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -91,6 +91,7 @@ typedef struct s_volume_catalog_info { uint32_t VolCatErrors; /* Number of errors this volume */ uint32_t VolCatWrites; /* Number of writes this volume */ uint32_t VolCatReads; /* Number of reads this volume */ + uint32_t VolCatRecycles; /* Number of recycles this volume */ uint64_t VolCatMaxBytes; /* max bytes to write */ uint64_t VolCatCapacityBytes; /* capacity estimate */ char VolCatStatus[20]; /* Volume status */ diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index f92081f16..629fff851 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -288,6 +288,7 @@ static int mount_next_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *label_blk) static int ready_dev_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) { int mounted = 0; + int recycle = 0; Dmsg0(100, "Enter ready_dev_for_append\n"); @@ -331,6 +332,9 @@ static int ready_dev_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) case VOL_OK: Dmsg1(200, "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: /* Check if we can accept this as an anonymous volume */ @@ -387,8 +391,10 @@ mount_next_vol: * be appended just after the block label. If we are writing * an second volume, the calling routine will write the label * before writing the overflow block. + * + * If the tape is marked as Recycle, we rewrite the label. */ - if (dev->VolHdr.LabelType == PRE_LABEL) { /* fresh tape */ + if (dev->VolHdr.LabelType == PRE_LABEL || recycle) { Dmsg1(90, "ready_for_append found freshly labeled volume. dev=%x\n", dev); dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */ write_volume_label_to_block(jcr, dev, block); @@ -415,13 +421,26 @@ mount_next_vol: write_volume_label_to_block(jcr, dev, block); dev->VolCatInfo.VolCatJobs = 1; dev->VolCatInfo.VolCatFiles = 1; - dev->VolCatInfo.VolCatMounts = 1; dev->VolCatInfo.VolCatErrors = 0; - dev->VolCatInfo.VolCatWrites = 1; dev->VolCatInfo.VolCatBlocks = 1; + if (recycle) { + dev->VolCatInfo.VolCatMounts++; + dev->VolCatInfo.VolCatRecycles++; + } else { + dev->VolCatInfo.VolCatMounts = 1; + dev->VolCatInfo.VolCatRecycles = 0; + dev->VolCatInfo.VolCatWrites = 1; + dev->VolCatInfo.VolCatReads = 1; + } + strcpy(dev->VolCatInfo.VolCatStatus, "Append"); dir_update_volume_info(jcr, &dev->VolCatInfo); - Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume %s on device %s\n"), - jcr->VolumeName, dev_name(dev)); + if (recycle) { + Jmsg(jcr, M_INFO, 0, _("Recycled volume %s on device %s, all previous data lost.\n"), + jcr->VolumeName, dev_name(dev)); + } else { + Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume %s on device %s\n"), + jcr->VolumeName, dev_name(dev)); + } } else { /* OK, at this point, we have a valid Bacula label, but @@ -550,8 +569,8 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) /* Inform User about end of media */ Jmsg(jcr, M_INFO, 0, _("End of media on Volume %s Bytes=%s Blocks=%s.\n"), - PrevVolName, edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1), - edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2)); + PrevVolName, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1), + edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2)); if (!dev_is_tape(dev)) { /* If file, */ close_dev(dev); /* yes, close it */ diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index a2d0b62f3..4b81b1436 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -60,7 +60,7 @@ static int cancel_cmd(JCR *cjcr); static int mount_cmd(JCR *jcr); static int unmount_cmd(JCR *jcr); static int status_cmd(JCR *sjcr); -static void label_device_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname); +static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname); struct s_cmds { char *cmd; @@ -260,12 +260,12 @@ static int label_cmd(JCR *jcr) if (open_dev(dev, volname, READ_WRITE) < 0) { bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev)); } else { - label_device_if_ok(jcr, dev, volname, poolname); + label_volume_if_ok(jcr, dev, volname, poolname); force_close_dev(dev); } } else if (dev->dev_blocked && dev->dev_blocked != BST_DOING_ACQUIRE) { /* device blocked? */ - label_device_if_ok(jcr, dev, volname, poolname); + label_volume_if_ok(jcr, dev, volname, poolname); } else if (dev->state & ST_READ || dev->num_writers) { if (dev->state & ST_READ) { bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), @@ -275,7 +275,7 @@ static int label_cmd(JCR *jcr) dev_name(dev), dev->num_writers); } } else { /* device not being used */ - label_device_if_ok(jcr, dev, volname, poolname); + label_volume_if_ok(jcr, dev, volname, poolname); } V(dev->mutex); } else { @@ -300,7 +300,7 @@ static int label_cmd(JCR *jcr) * * Enter with the mutex set */ -static void label_device_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname) +static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname) { BSOCK *dir = jcr->dir_bsock; DEV_BLOCK *block; @@ -620,8 +620,8 @@ static int status_cmd(JCR *jcr) } bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"), - edit_uint_with_commas(last_job.JobFiles, b1), - edit_uint_with_commas(last_job.JobBytes, b2), + edit_uint64_with_commas(last_job.JobFiles, b1), + edit_uint64_with_commas(last_job.JobBytes, b2), termstat); } @@ -665,12 +665,12 @@ static int status_cmd(JCR *jcr) } bpb = dev->VolCatInfo.VolCatBytes / bpb; bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"), - edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1), - edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2), - edit_uint_with_commas(bpb, b3)); + edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1), + edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), + edit_uint64_with_commas(bpb, b3)); bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"), - edit_uint_with_commas(dev->file, b1), - edit_uint_with_commas(dev->block_num, b2)); + edit_uint64_with_commas(dev->file, b1), + edit_uint64_with_commas(dev->block_num, b2)); } else { bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev)); @@ -696,9 +696,9 @@ static int status_cmd(JCR *jcr) } bps = jcr->JobBytes / sec; bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"), - edit_uint_with_commas(jcr->JobFiles, b1), - edit_uint_with_commas(jcr->JobBytes, b2), - edit_uint_with_commas(bps, b3)); + edit_uint64_with_commas(jcr->JobFiles, b1), + edit_uint64_with_commas(jcr->JobBytes, b2), + edit_uint64_with_commas(bps, b3)); found = 1; #ifdef DEBUG if (jcr->file_bsock) { diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 45e22a902..8287cdffe 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -597,13 +597,13 @@ StartFile : %s\n\ EndFile : %s\n\ JobErrors : %s\n\ ", - edit_uint_with_commas(label.JobFiles, ec1), - edit_uint_with_commas(label.JobBytes, ec2), - edit_uint_with_commas(label.start_block, ec3), - edit_uint_with_commas(label.end_block, ec4), - edit_uint_with_commas(label.start_file, ec5), - edit_uint_with_commas(label.end_file, ec6), - edit_uint_with_commas(label.JobErrors, ec7)); + edit_uint64_with_commas(label.JobFiles, ec1), + edit_uint64_with_commas(label.JobBytes, ec2), + edit_uint64_with_commas(label.start_block, ec3), + edit_uint64_with_commas(label.end_block, ec4), + edit_uint64_with_commas(label.start_file, ec5), + edit_uint64_with_commas(label.end_file, ec6), + edit_uint64_with_commas(label.JobErrors, ec7)); } dt.julian_day_number = label.write_date; dt.julian_day_fraction = label.write_time; diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index eabbd18ef..cfe86abc7 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -162,7 +162,7 @@ int main (int argc, char *argv[]) configfile = bstrdup(CONFIG_FILE); } - init_msg(NULL); + init_msg(NULL, NULL); parse_config(configfile); check_config(); @@ -245,7 +245,7 @@ int main (int argc, char *argv[]) UnlockRes(); device = NULL; - init_watchdog(); /* start watchdog thread */ + start_watchdog(); /* start watchdog thread */ /* * Here we support either listening on one port or on two ports @@ -347,7 +347,7 @@ void terminate_stored(int sig) } in_here = TRUE; - term_watchdog(); + stop_watchdog(); Dmsg0(200, "In terminate_stored()\n"); diff --git a/bacula/src/version.h b/bacula/src/version.h index 1b38e6488..ee81553df 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ -#define VERSION "1.18" +#define VERSION "1.19" #define VSTRING "1" -#define DATE "22 April 2002" -#define LSMDATE "22Apr02" +#define DATE "10 May 2002" +#define LSMDATE "10May02" /* Debug flags */ #define DEBUG 1 -- 2.47.3