From 4493b8c506ee2e42ded3e9579d18aa6d1471135e Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@91ce42f0-d328-0410-95d8-f526ca767f89> Date: Sat, 11 May 2002 09:05:11 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'Release-1.19b'. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/tags/Release-1.19b@23 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 | 144 ++++-- 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, 3392 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 09d01728ac..4123a82625 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 2796af378c..723f1e48ee 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 cc1892aabe..66845723ee 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 179c880b6b..d49de02a5f 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 2707774c10..5268fbf4f6 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 00e075d1b3..ee55b709d4 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 2ab537fd64..52af67ddc6 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 6cf9512115..36d22e73b9 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 e0eba75249..d75187dcda 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 55bfe85549..4570d4b27a 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 0dfaefb2de..14f2ea0d9d 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 0000000000..1365db6f5d --- /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 0ffb178ac5..c5acf7a08a 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 f811e69873..31b29ec9f6 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 f420b21f57..e251ae94b6 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 59335b2edc..68b931fe35 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 c8436fa2d8..647d4115c5 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 7ad6497cef..479f97fea0 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 5fd896af9f..a022f84901 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 a50a179259..5c154917f8 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 a6757a83b7..2fdef3f191 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 4a2183a63c..eef77585c8 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 b9a43ce64d..bbe0d09f10 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 63c2ba27d1..89160b5e9f 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 e0ba071194..5a7fa1c3ec 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 f061bcd5ab..2cafd53e6a 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 8929df66bd..24c6e7a8aa 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 fc5284ce70..555a08bfbb 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 04fdc7b85f..89b345b806 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 699d0a8e06..a7aeaf24b3 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 3d5c4c239c..92c1f6e200 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 ee60d0d15b..3087e87fe9 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 f4e82ce0f5..d13d23c446 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 bc1607d367..a9a49da782 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 aea47de80e..7d327814e2 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 161ac4f673..f70441d526 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 9200ccaddd..539b73cae0 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 1f7dda1714..bf698a382b 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 0c693d8b9a..8cd2a22ba5 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 35accb51c6..51581b34a6 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 c58a713f5d..21b69f8944 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 d9f41204d8..2336a4b2b2 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 791ca47f05..06a08498a2 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,9 @@ 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; + pr.AutoPrune = pool->AutoPrune; if (pool->label_format) { strcpy(pr.LabelFormat, pool->label_format); } else { @@ -529,7 +535,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 +546,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 +566,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 +574,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 +592,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 +946,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 +956,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 +971,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 +1075,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 +1095,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 +1112,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 +1231,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 +1286,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 +1297,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 12aa6f7141..a466e3e185 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 53250db4a3..9a24d052b1 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 e77673cfd7..ff572affa4 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 0000000000..d790e78c82 --- /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 0000000000..552d8d9096 --- /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 8a5c90b50a..a44d73ea03 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 d0ac1a4bef..f0329268a6 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 1ce7260392..8722a028d7 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 a05ee54b1c..eb8b651f71 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 57d97e4c6e..8c3c63d9b9 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 7374fe3a53..9bbcff6b41 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 7e7ee3be1d..5a40ade9fb 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 da15c6fe65..832f7511f9 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 67eab1f68c..a083c0b1e0 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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 M!SsDzyUBk13q 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 Swsh`wrL!kptO3#~{QYkwU;UB* literal 0 HcmV?d00001 diff --git a/bacula/src/filed/win32/bin/umount.exe b/bacula/src/filed/win32/bin/umount.exe new file mode 100755 index 0000000000000000000000000000000000000000..e1b1c58c16feb6ad971dd469df88742fde2ee094 GIT binary patch literal 7680 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 literal 0 HcmV?d00001 diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 7557539c42..e25ed3ab86 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -98,6 +98,7 @@ struct s_jcr { char *VolumeName; /* Volume name desired -- pool_memory */ char *client_name; /* client name */ char *sd_auth_key; /* SD auth key */ + MSGS *msgs; /* Message resource */ DEST *dest_chain; /* Job message destination chain */ char send_msg[nbytes_for_bits(M_MAX+1)]; /* message bit mask */ diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 8332faf5e0..01d96d8376 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -38,8 +38,7 @@ LIBSRCS = alloc.c base64.c bmisc.c bnet.c bnet_server.c \ makepath.c \ md5.c message.c mem_pool.c parse_conf.c \ queue.c rwlock.c save-cwd.c serial.c \ - signal.c smartall.c util.c watchdog.c workq.c - + signal.c smartall.c util.c watchdog.c workq.c # immortal.c filesys.c diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index aeee5c9fe8..c17616793c 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -63,7 +63,6 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) jcr->VolumeName[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 622f5ed0ea..ec5cb38061 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 99e5ed5a0e..6d3d9c5bd8 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 5017929f47..6978470c24 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 fb1091ca4e..cc114032ec 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 e4d41b632a..de9fdfe691 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 ab82295e92..1235e7ffb1 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 1bcccc4ef6..9cda310aa7 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 a7d3c19c08..b064dd9070 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 7a20cf1000..a3c21f92f1 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 de60d1af7f..5fa23b504a 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 7804241fd5..6738d866c8 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 8aa3b4ba1d..b6e606a2c9 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 ead1ddf4d4..f71b77f83f 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 f92081f16d..629fff8515 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 a2d0b62f3b..4b81b14369 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 45e22a9020..8287cdffe2 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 eabbd18efd..cfe86abc75 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 1b38e64888..ee81553dff 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.39.5