From da8584df92d56dd3cbf3c9a7563b22d8335ba219 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 29 Jan 2005 22:39:04 +0000 Subject: [PATCH] Vacation work -- see tech log git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1806 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ReleaseNotes | 15 +- bacula/autoconf/acconfig.h | 7 +- bacula/autoconf/aclocal.m4 | 66 ++++ bacula/autoconf/config.h.in | 7 +- bacula/autoconf/config.h.in.save | 13 +- bacula/autoconf/configure.in | 21 +- bacula/configure | 100 ++++- bacula/examples/python/EndJob.py | 4 +- bacula/kernstodo | 14 +- bacula/platforms/solaris/bacula-dir.in | 2 +- bacula/platforms/solaris/bacula-fd.in | 2 +- bacula/platforms/solaris/bacula-sd.in | 2 +- bacula/src/baconfig.h | 21 +- bacula/src/cats/bdb_create.c | 15 +- bacula/src/cats/cats.h | 170 ++++++++- bacula/src/cats/create_bacula_database.in | 4 +- bacula/src/cats/create_sqlite_database.in | 3 +- bacula/src/cats/drop_bacula_database.in | 4 +- bacula/src/cats/drop_bacula_tables.in | 4 +- bacula/src/cats/drop_sqlite_database.in | 2 +- bacula/src/cats/grant_bacula_privileges.in | 4 +- bacula/src/cats/make_bacula_tables.in | 4 +- bacula/src/cats/make_mysql_tables.in | 36 ++ bacula/src/cats/make_postgresql_tables.in | 391 ++++++++++---------- bacula/src/cats/make_sqlite_tables.in | 61 ++- bacula/src/cats/protos.h | 19 +- bacula/src/cats/sql.c | 34 +- bacula/src/cats/sql_create.c | 253 ++++++++++--- bacula/src/cats/sql_delete.c | 12 +- bacula/src/cats/sql_find.c | 49 +-- bacula/src/cats/sql_get.c | 188 +++++----- bacula/src/cats/sql_list.c | 10 +- bacula/src/cats/sql_update.c | 50 +-- bacula/src/cats/sqlite.c | 34 +- bacula/src/cats/update_bacula_tables.in | 4 +- bacula/src/cats/update_mysql_tables.in | 1 + bacula/src/cats/update_postgresql_tables.in | 4 + bacula/src/cats/update_sqlite_tables.in | 7 +- bacula/src/dird/backup.c | 61 ++- bacula/src/dird/bsr.c | 42 ++- bacula/src/dird/catreq.c | 66 ++-- bacula/src/dird/dird.c | 39 +- bacula/src/dird/dird_conf.c | 180 +++++++-- bacula/src/dird/dird_conf.h | 387 ++++++++++--------- bacula/src/dird/getmsg.c | 83 +++-- bacula/src/dird/inc_conf.c | 2 +- bacula/src/dird/job.c | 97 ++--- bacula/src/dird/jobq.c | 96 ++--- bacula/src/dird/mac.c | 58 ++- bacula/src/dird/msgchan.c | 175 +++++++-- bacula/src/dird/protos.h | 4 +- bacula/src/dird/restore.c | 18 +- bacula/src/dird/scheduler.c | 8 +- bacula/src/dird/sql_cmds.c | 2 +- bacula/src/dird/ua_acl.c | 6 +- bacula/src/dird/ua_cmds.c | 197 +++++----- bacula/src/dird/ua_dotcmds.c | 22 +- bacula/src/dird/ua_label.c | 120 +++--- bacula/src/dird/ua_output.c | 77 ++-- bacula/src/dird/ua_query.c | 52 +-- bacula/src/dird/ua_restore.c | 117 +++--- bacula/src/dird/ua_run.c | 202 +++++----- bacula/src/dird/ua_server.c | 28 +- bacula/src/dird/ua_tree.c | 46 +-- bacula/src/dird/verify.c | 11 +- bacula/src/filed/acl.c | 6 +- bacula/src/filed/job.c | 8 +- bacula/src/filed/verify_vol.c | 58 +-- bacula/src/jcr.h | 8 +- bacula/src/lib/alist.h | 8 +- bacula/src/lib/bnet.c | 7 +- bacula/src/lib/bpipe.c | 42 +-- bacula/src/lib/daemon.c | 4 +- bacula/src/lib/edit.c | 47 ++- bacula/src/lib/htable.c | 53 ++- bacula/src/lib/htable.h | 8 +- bacula/src/lib/jcr.c | 48 +-- bacula/src/lib/message.c | 130 +++---- bacula/src/lib/parse_conf.c | 105 +++--- bacula/src/lib/protos.h | 17 +- bacula/src/lib/scan.c | 38 +- bacula/src/lib/watchdog.c | 18 +- bacula/src/lib/workq.c | 62 ++-- bacula/src/stored/acquire.c | 262 ++++++++----- bacula/src/stored/append.c | 38 +- bacula/src/stored/askdir.c | 24 +- bacula/src/stored/autochanger.c | 103 +++--- bacula/src/stored/bcopy.c | 24 +- bacula/src/stored/bextract.c | 48 +-- bacula/src/stored/block.c | 43 ++- bacula/src/stored/block.h | 4 +- bacula/src/stored/bls.c | 26 +- bacula/src/stored/bsr.h | 4 +- bacula/src/stored/btape.c | 342 +++++++++-------- bacula/src/stored/butil.c | 18 +- bacula/src/stored/dev.c | 377 +++++++++---------- bacula/src/stored/dev.h | 347 +++++++++-------- bacula/src/stored/device.c | 38 +- bacula/src/stored/dircmd.c | 44 ++- bacula/src/stored/fd_cmds.c | 15 +- bacula/src/stored/job.c | 206 +++++++---- bacula/src/stored/label.c | 252 ++++++++++--- bacula/src/stored/mount.c | 36 +- bacula/src/stored/parse_bsr.c | 57 ++- bacula/src/stored/protos.h | 259 ++++++------- bacula/src/stored/read.c | 11 +- bacula/src/stored/read_record.c | 51 ++- bacula/src/stored/record.c | 24 +- bacula/src/stored/spool.c | 31 +- bacula/src/stored/status.c | 100 ++--- bacula/src/stored/stored.c | 51 ++- bacula/src/stored/stored_conf.c | 235 +++++++----- bacula/src/stored/stored_conf.h | 113 +++--- bacula/src/version.h | 6 +- 114 files changed, 4503 insertions(+), 3186 deletions(-) diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index 42cb27e695..d8bd80297d 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,10 +1,21 @@ - Release Notes for Bacula 1.37.2 + Release Notes for Bacula 1.37.3 - Bacula code: Total files = 398 Total lines = 117,151 (*.h *.c *.in) + Bacula code: Total files = 411 Total lines = 121,855 (*.h *.c *.in) Major Changes: +- This version has a new database format that is not compatible + with previous databases. There are NO upgrade scripts yet. +- Due to the massive changes made during the last two weeks, + version 1.37.3 should be considered unstable. It does, however, + pass the regression tests. +- SQLite3 support. +- First cut at ANSI labels. +- New communications protocol between DIR and SD to reserve + drives. + + - Preliminary Python Event support has been added. See below for configuration. A Python script will be called at particular points or conditions diff --git a/bacula/autoconf/acconfig.h b/bacula/autoconf/acconfig.h index bd0bb6b78e..e93344357f 100644 --- a/bacula/autoconf/acconfig.h +++ b/bacula/autoconf/acconfig.h @@ -35,13 +35,12 @@ /* Define if you want to use SQLite */ #undef HAVE_SQLITE +/* Define if you want to use SQLite3 */ +#undef HAVE_SQLITE3 + /* Define if you want to use Berkeley DB */ #undef HAVE_BERKELEY_DB - -/* Define if you want to use PostgreSQL */ -#undef HAVE_PGSQL - /* Define if you want to use mSQL */ #undef HAVE_MSQL diff --git a/bacula/autoconf/aclocal.m4 b/bacula/autoconf/aclocal.m4 index 3f05d19f35..8641178cfd 100644 --- a/bacula/autoconf/aclocal.m4 +++ b/bacula/autoconf/aclocal.m4 @@ -541,6 +541,72 @@ AC_SUBST(SQL_BINDIR) ]) +AC_DEFUN(BA_CHECK_SQLITE3_DB, +[ +db_found=no +AC_MSG_CHECKING(for SQLite3 support) +AC_ARG_WITH(sqlite3, +[ + --with-sqlite3[=DIR] Include SQLite3 support. DIR is the SQLite3 base + install directory, default is to search through + a number of common places for the SQLite3 files.], +[ + if test "$withval" != "no"; then + if test "$withval" = "yes"; then + if test -f /usr/local/include/sqlite3.h; then + SQLITE_INCDIR=/usr/local/include + SQLITE_LIBDIR=/usr/local/lib + SQLITE_BINDIR=/usr/local/bin + elif test -f /usr/include/sqlite3.h; then + SQLITE_INCDIR=/usr/include + SQLITE_LIBDIR=/usr/lib + SQLITE_BINDIR=/usr/bin + elif test -f $prefix/include/sqlite3.h; then + SQLITE_INCDIR=$prefix/include + SQLITE_LIBDIR=$prefix/lib + SQLITE_BINDIR=$prefix/bin + else + AC_MSG_RESULT(no) + AC_MSG_ERROR(Unable to find sqlite3.h in standard locations) + fi + else + if test -f $withval/sqlite3.h; then + SQLITE_INCDIR=$withval + SQLITE_LIBDIR=$withval + SQLITE_BINDIR=$withval + elif test -f $withval/include/sqlite3.h; then + SQLITE_INCDIR=$withval/include + SQLITE_LIBDIR=$withval/lib + SQLITE_BINDIR=$withval/bin + else + AC_MSG_RESULT(no) + AC_MSG_ERROR(Invalid SQLite3 directory $withval - unable to find sqlite3.h under $withval) + fi + fi + SQL_INCLUDE=-I$SQLITE_INCDIR + SQL_LFLAGS="-L$SQLITE_LIBDIR -lsqlite3" + SQL_BINDIR=$SQLITE_BINDIR + + AC_DEFINE(HAVE_SQLITE3) + AC_MSG_RESULT(yes) + db_found=yes + support_sqlite3=yes + db_name=SQLite3 + DB_NAME=sqlite3 + + else + AC_MSG_RESULT(no) + fi +],[ + AC_MSG_RESULT(no) +]) +AC_SUBST(SQL_LFLAGS) +AC_SUBST(SQL_INCLUDE) +AC_SUBST(SQL_BINDIR) + +]) + + AC_DEFUN(BA_CHECK_POSTGRESQL_DB, [ diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index 8d3797e6b4..9470a3e23a 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -36,13 +36,12 @@ /* Define if you want to use SQLite */ #undef HAVE_SQLITE +/* Define if you want to use SQLite3 */ +#undef HAVE_SQLITE3 + /* Define if you want to use Berkeley DB */ #undef HAVE_BERKELEY_DB - -/* Define if you want to use PostgreSQL */ -#undef HAVE_PGSQL - /* Define if you want to use mSQL */ #undef HAVE_MSQL diff --git a/bacula/autoconf/config.h.in.save b/bacula/autoconf/config.h.in.save index adac090114..9470a3e23a 100644 --- a/bacula/autoconf/config.h.in.save +++ b/bacula/autoconf/config.h.in.save @@ -36,13 +36,12 @@ /* Define if you want to use SQLite */ #undef HAVE_SQLITE +/* Define if you want to use SQLite3 */ +#undef HAVE_SQLITE3 + /* Define if you want to use Berkeley DB */ #undef HAVE_BERKELEY_DB - -/* Define if you want to use PostgreSQL */ -#undef HAVE_PGSQL - /* Define if you want to use mSQL */ #undef HAVE_MSQL @@ -594,9 +593,9 @@ /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at run-time. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if the `S_IS*' macros in do not work properly. */ diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index a3e70fa4a4..cd22084c4a 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -147,6 +147,7 @@ fi support_mysql=no support_sqlite=no +support_sqlite3=no support_postgresql=no support_smartalloc=yes support_readline=yes @@ -577,6 +578,12 @@ if test ! x$CDRECORD = x ; then if test x${CDSTL} = x ; then CDSTL=`${CDRECORD} -scanbus 2>/dev/null | grep CD+RW | ${AWK} '{print $1}'` fi + if test x${CDSTL} = x ; then + CDSTL=`${CDRECORD} -scanbus 2>/dev/null | grep DVD+RW | ${AWK} '{print $1}'` + fi + if test x${CDSTL} = x ; then + CDSTL=`${CDRECORD} -scanbus 2>/dev/null | grep DVD-RW | ${AWK} '{print $1}'` + fi if test x${CDSTL} = x ; then CDSTL="3,0,0" fi @@ -1187,6 +1194,8 @@ BA_CHECK_POSTGRESQL_DB BA_CHECK_MYSQL_DB +BA_CHECK_SQLITE3_DB + BA_CHECK_SQLITE_DB AC_SUBST(cats) @@ -1959,8 +1968,8 @@ AC_OUTPUT([autoconf/Make.common \ scripts/dvd-writepart \ scripts/dvd-freespace \ scripts/bacula-tray-monitor.desktop \ - scripts/logwatch/Makefile \ - scripts/logwatch/logfile.bacula.conf \ + scripts/logwatch/Makefile \ + scripts/logwatch/logfile.bacula.conf \ doc/Makefile \ src/Makefile \ src/host.h \ @@ -2003,6 +2012,12 @@ AC_OUTPUT([autoconf/Make.common \ src/cats/grant_sqlite_privileges \ src/cats/drop_sqlite_tables \ src/cats/drop_sqlite_database \ + src/cats/create_sqlite3_database \ + src/cats/update_sqlite3_tables \ + src/cats/make_sqlite3_tables \ + src/cats/grant_sqlite3_privileges \ + src/cats/drop_sqlite3_tables \ + src/cats/drop_sqlite3_database \ src/cats/sqlite \ src/cats/mysql \ src/cats/create_bdb_database \ @@ -2091,7 +2106,7 @@ if test "x${db_name}" = "xInternal" ; then echo " " echo " " echo "You have not specified either --enable-client-only or one of the" - echo " supported databases: MySQL, PostgreSQL, or SQLite". + echo " supported databases: MySQL, PostgreSQL, SQLite3 or SQLite." echo " This is not permitted. Please reconfigure." echo " " echo "Aborting the configuration ..." diff --git a/bacula/configure b/bacula/configure index 870cd22dc2..1c1693a48e 100755 --- a/bacula/configure +++ b/bacula/configure @@ -922,6 +922,10 @@ Optional Packages: install directory, default is to search through a number of common places for the MySQL files. + --with-sqlite3=DIR Include SQLite3 support. DIR is the SQLite3 base + install directory, default is to search through + a number of common places for the SQLite3 files. + --with-sqlite=DIR Include SQLite support. DIR is the SQLite base install directory, default is to search through a number of common places for the SQLite files. @@ -4701,6 +4705,7 @@ fi support_mysql=no support_sqlite=no +support_sqlite3=no support_postgresql=no support_smartalloc=yes support_readline=yes @@ -7483,6 +7488,12 @@ if test ! x$CDRECORD = x ; then if test x${CDSTL} = x ; then CDSTL=`${CDRECORD} -scanbus 2>/dev/null | grep CD+RW | ${AWK} '{print $1}'` fi + if test x${CDSTL} = x ; then + CDSTL=`${CDRECORD} -scanbus 2>/dev/null | grep DVD+RW | ${AWK} '{print $1}'` + fi + if test x${CDSTL} = x ; then + CDSTL=`${CDRECORD} -scanbus 2>/dev/null | grep DVD-RW | ${AWK} '{print $1}'` + fi if test x${CDSTL} = x ; then CDSTL="3,0,0" fi @@ -9005,6 +9016,85 @@ fi; +db_found=no +echo "$as_me:$LINENO: checking for SQLite3 support" >&5 +echo $ECHO_N "checking for SQLite3 support... $ECHO_C" >&6 + +# Check whether --with-sqlite3 or --without-sqlite3 was given. +if test "${with_sqlite3+set}" = set; then + withval="$with_sqlite3" + + if test "$withval" != "no"; then + if test "$withval" = "yes"; then + if test -f /usr/local/include/sqlite3.h; then + SQLITE_INCDIR=/usr/local/include + SQLITE_LIBDIR=/usr/local/lib + SQLITE_BINDIR=/usr/local/bin + elif test -f /usr/include/sqlite3.h; then + SQLITE_INCDIR=/usr/include + SQLITE_LIBDIR=/usr/lib + SQLITE_BINDIR=/usr/bin + elif test -f $prefix/include/sqlite3.h; then + SQLITE_INCDIR=$prefix/include + SQLITE_LIBDIR=$prefix/lib + SQLITE_BINDIR=$prefix/bin + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: Unable to find sqlite3.h in standard locations" >&5 +echo "$as_me: error: Unable to find sqlite3.h in standard locations" >&2;} + { (exit 1); exit 1; }; } + fi + else + if test -f $withval/sqlite3.h; then + SQLITE_INCDIR=$withval + SQLITE_LIBDIR=$withval + SQLITE_BINDIR=$withval + elif test -f $withval/include/sqlite3.h; then + SQLITE_INCDIR=$withval/include + SQLITE_LIBDIR=$withval/lib + SQLITE_BINDIR=$withval/bin + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: Invalid SQLite3 directory $withval - unable to find sqlite3.h under $withval" >&5 +echo "$as_me: error: Invalid SQLite3 directory $withval - unable to find sqlite3.h under $withval" >&2;} + { (exit 1); exit 1; }; } + fi + fi + SQL_INCLUDE=-I$SQLITE_INCDIR + SQL_LFLAGS="-L$SQLITE_LIBDIR -lsqlite3" + SQL_BINDIR=$SQLITE_BINDIR + + cat >>confdefs.h <<\_ACEOF +#define HAVE_SQLITE3 1 +_ACEOF + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + db_found=yes + support_sqlite3=yes + db_name=SQLite3 + DB_NAME=sqlite3 + + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi + +else + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + +fi; + + + + + + + db_found=no echo "$as_me:$LINENO: checking for SQLite support" >&5 echo $ECHO_N "checking for SQLite support... $ECHO_C" >&6 @@ -21411,7 +21501,7 @@ if test "x${subsysdir}" = "x${sbindir}" ; then exit 1 fi - ac_config_files="$ac_config_files autoconf/Make.common Makefile rescue/Makefile rescue/linux/Makefile rescue/linux/floppy/Makefile rescue/linux/cdrom/Makefile rescue/linux/cdrom/bacula/Makefile rescue/freebsd/Makefile rescue/solaris/Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/bconsole scripts/gconsole scripts/bacula scripts/devel_bacula scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/bacula.desktop.gnome1.consolehelper scripts/bacula.desktop.gnome2.consolehelper scripts/bacula.desktop.gnome1.xsu scripts/bacula.desktop.gnome2.xsu scripts/gnome-console.console_apps scripts/mtx-changer scripts/dvd-writepart scripts/dvd-freespace scripts/bacula-tray-monitor.desktop scripts/logwatch/Makefile scripts/logwatch/logfile.bacula.conf doc/Makefile src/Makefile src/host.h src/console/Makefile src/console/bconsole.conf src/gnome-console/Makefile src/gnome-console/gnome-console.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/wx-console/Makefile src/wx-console/wx-console.conf src/tray-monitor/Makefile src/tray-monitor/tray-monitor.conf src/dird/Makefile src/dird/bacula-dir.conf src/lib/Makefile src/stored/Makefile src/stored/bacula-sd.conf src/filed/Makefile src/filed/bacula-fd.conf src/filed/win32/Makefile src/cats/Makefile src/cats/make_catalog_backup src/cats/delete_catalog_backup src/cats/create_postgresql_database src/cats/update_postgresql_tables src/cats/make_postgresql_tables src/cats/grant_postgresql_privileges src/cats/drop_postgresql_tables src/cats/drop_postgresql_database src/cats/create_mysql_database src/cats/update_mysql_tables src/cats/make_mysql_tables src/cats/grant_mysql_privileges src/cats/drop_mysql_tables src/cats/drop_mysql_database src/cats/create_sqlite_database src/cats/update_sqlite_tables src/cats/make_sqlite_tables src/cats/grant_sqlite_privileges src/cats/drop_sqlite_tables src/cats/drop_sqlite_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/update_bdb_tables src/cats/make_bdb_tables src/cats/grant_bdb_privileges src/cats/drop_bdb_tables src/cats/drop_bdb_database src/cats/create_bacula_database src/cats/update_bacula_tables src/cats/grant_bacula_privileges src/cats/make_bacula_tables src/cats/drop_bacula_tables src/cats/drop_bacula_database src/findlib/Makefile src/tools/Makefile src/win32/winbacula.nsi src/win32/baculafd/bacula-fd.conf src/win32/Makefile src/win32/console/bconsole.conf src/win32/wx-console/wx-console.conf src/win32/pebuilder/Makefile src/bimagemgr/Makefile src/bimagemgr/bacula-bimagemgr.spec $PFILES" + ac_config_files="$ac_config_files autoconf/Make.common Makefile rescue/Makefile rescue/linux/Makefile rescue/linux/floppy/Makefile rescue/linux/cdrom/Makefile rescue/linux/cdrom/bacula/Makefile rescue/freebsd/Makefile rescue/solaris/Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/bconsole scripts/gconsole scripts/bacula scripts/devel_bacula scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/bacula.desktop.gnome1.consolehelper scripts/bacula.desktop.gnome2.consolehelper scripts/bacula.desktop.gnome1.xsu scripts/bacula.desktop.gnome2.xsu scripts/gnome-console.console_apps scripts/mtx-changer scripts/dvd-writepart scripts/dvd-freespace scripts/bacula-tray-monitor.desktop scripts/logwatch/Makefile scripts/logwatch/logfile.bacula.conf doc/Makefile src/Makefile src/host.h src/console/Makefile src/console/bconsole.conf src/gnome-console/Makefile src/gnome-console/gnome-console.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/wx-console/Makefile src/wx-console/wx-console.conf src/tray-monitor/Makefile src/tray-monitor/tray-monitor.conf src/dird/Makefile src/dird/bacula-dir.conf src/lib/Makefile src/stored/Makefile src/stored/bacula-sd.conf src/filed/Makefile src/filed/bacula-fd.conf src/filed/win32/Makefile src/cats/Makefile src/cats/make_catalog_backup src/cats/delete_catalog_backup src/cats/create_postgresql_database src/cats/update_postgresql_tables src/cats/make_postgresql_tables src/cats/grant_postgresql_privileges src/cats/drop_postgresql_tables src/cats/drop_postgresql_database src/cats/create_mysql_database src/cats/update_mysql_tables src/cats/make_mysql_tables src/cats/grant_mysql_privileges src/cats/drop_mysql_tables src/cats/drop_mysql_database src/cats/create_sqlite_database src/cats/update_sqlite_tables src/cats/make_sqlite_tables src/cats/grant_sqlite_privileges src/cats/drop_sqlite_tables src/cats/drop_sqlite_database src/cats/create_sqlite3_database src/cats/update_sqlite3_tables src/cats/make_sqlite3_tables src/cats/grant_sqlite3_privileges src/cats/drop_sqlite3_tables src/cats/drop_sqlite3_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/update_bdb_tables src/cats/make_bdb_tables src/cats/grant_bdb_privileges src/cats/drop_bdb_tables src/cats/drop_bdb_database src/cats/create_bacula_database src/cats/update_bacula_tables src/cats/grant_bacula_privileges src/cats/make_bacula_tables src/cats/drop_bacula_tables src/cats/drop_bacula_database src/findlib/Makefile src/tools/Makefile src/win32/winbacula.nsi src/win32/baculafd/bacula-fd.conf src/win32/Makefile src/win32/console/bconsole.conf src/win32/wx-console/wx-console.conf src/win32/pebuilder/Makefile src/bimagemgr/Makefile src/bimagemgr/bacula-bimagemgr.spec $PFILES" ac_config_commands="$ac_config_commands default" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -22016,6 +22106,12 @@ do "src/cats/grant_sqlite_privileges" ) CONFIG_FILES="$CONFIG_FILES src/cats/grant_sqlite_privileges" ;; "src/cats/drop_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_sqlite_tables" ;; "src/cats/drop_sqlite_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_sqlite_database" ;; + "src/cats/create_sqlite3_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_sqlite3_database" ;; + "src/cats/update_sqlite3_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/update_sqlite3_tables" ;; + "src/cats/make_sqlite3_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_sqlite3_tables" ;; + "src/cats/grant_sqlite3_privileges" ) CONFIG_FILES="$CONFIG_FILES src/cats/grant_sqlite3_privileges" ;; + "src/cats/drop_sqlite3_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_sqlite3_tables" ;; + "src/cats/drop_sqlite3_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_sqlite3_database" ;; "src/cats/sqlite" ) CONFIG_FILES="$CONFIG_FILES src/cats/sqlite" ;; "src/cats/mysql" ) CONFIG_FILES="$CONFIG_FILES src/cats/mysql" ;; "src/cats/create_bdb_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_bdb_database" ;; @@ -22988,7 +23084,7 @@ if test "x${db_name}" = "xInternal" ; then echo " " echo " " echo "You have not specified either --enable-client-only or one of the" - echo " supported databases: MySQL, PostgreSQL, or SQLite". + echo " supported databases: MySQL, PostgreSQL, SQLite3 or SQLite." echo " This is not permitted. Please reconfigure." echo " " echo "Aborting the configuration ..." diff --git a/bacula/examples/python/EndJob.py b/bacula/examples/python/EndJob.py index 7624766f31..282ac7c6ee 100644 --- a/bacula/examples/python/EndJob.py +++ b/bacula/examples/python/EndJob.py @@ -3,9 +3,9 @@ import bacula def EndJob(j): jobid = bacula.get(j, "JobId") client = bacula.get(j, "Client") - bacula.set(jcr=j, JobReport="Python JodJob output: JobId=%d Client=%s.\n" % (jobid, client)) + bacula.set(jcr=j, JobReport="Python EndJob output: JobId=%d Client=%s.\n" % (jobid, client)) if (jobid < 5) : startid = bacula.run(j, "run kernsave") - print "Python started jobid=", startid + print "Python started new Job: jobid=", startid return 1 diff --git a/bacula/kernstodo b/bacula/kernstodo index e5a94f422e..8404611547 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 31 December 2004 + 23 January 2005 Major development: Project Developer @@ -12,8 +12,10 @@ Version 1.37 Kern (see below) 1.37 Major Projects: #3 Migration (Move, Copy, Archive Jobs) -#4 Embedded Python Scripting (implemented in Dir) -#5 Events that call a Python program (Implemented in Dir) +#4 Embedded Python Scripting + (Implemented in Dir/SD) +#5 Events that call a Python program + (Implemented in Dir/SD) #6 Select one from among Multiple Storage Devices for Job #7 Single Job Writing to Multiple Storage Devices @@ -33,7 +35,6 @@ For 1.37: - Look at Preben's acl.c error handling code. - See multiple-store.txt for Multiple Storage implementation design. -- Add Set Error from Python. - Create a new GUI chapter explaining all the GUI programs. - Tell the "restore" user when browsing is no longer possible. - Add disk seeking on restore. @@ -42,9 +43,10 @@ For 1.37: get the bootstrap file. - Add dump of VolSessionId/Time and FileIndex with bls. - Make bootstrap file handle multiple MediaTypes (SD) -- Add offline command to Bacula console. +- Add offline tape command to Bacula console. - Add performance testing hooks -- Add Python writable variable for changing the Priority. +- Add Python writable variable for changing the Priority, + Client, Storage, JobStatus (error), ... - Document that Bootstrap files can be written with cataloging turned off. - Look at adding full Volume and Pool information to a Volume diff --git a/bacula/platforms/solaris/bacula-dir.in b/bacula/platforms/solaris/bacula-dir.in index bd433b1625..0346dafcc2 100755 --- a/bacula/platforms/solaris/bacula-dir.in +++ b/bacula/platforms/solaris/bacula-dir.in @@ -20,7 +20,7 @@ case "$1" in ;; stop) echo "Stopping the Director daemon: " -# killproc @sbindir@/bacula-dir + pkill -x bacula-dir RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f @subsysdir@/bacula-dir diff --git a/bacula/platforms/solaris/bacula-fd.in b/bacula/platforms/solaris/bacula-fd.in index 14160a7643..31dbbad476 100755 --- a/bacula/platforms/solaris/bacula-fd.in +++ b/bacula/platforms/solaris/bacula-fd.in @@ -19,7 +19,7 @@ case "$1" in ;; stop) echo "Stopping the Bacula File daemon: " -# killproc @sbindir@/bacula-fd + pkill -x bacula-fd RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f @subsysdir@/bacula-fd diff --git a/bacula/platforms/solaris/bacula-sd.in b/bacula/platforms/solaris/bacula-sd.in index fb55fb47cf..37230ff971 100755 --- a/bacula/platforms/solaris/bacula-sd.in +++ b/bacula/platforms/solaris/bacula-sd.in @@ -19,7 +19,7 @@ case "$1" in ;; stop) echo "Stopping the Bacula Storage daemon: " -# killproc @sbindir@/bacula-sd + pkill -x bacula-sd RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f @subsysdir@/bacula-sd diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 4771264511..8db3edca0c 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -5,7 +5,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -184,6 +184,13 @@ #define MD5_SIG 1 #define SHA1_SIG 2 +/* + * Tape label types -- stored in catalog + */ +#define B_BACULA_LABEL 0 +#define B_ANSI_LABEL 1 +#define B_IBM_LABEL 2 + /* Size of File Address stored in STREAM_SPARSE_DATA. Do NOT change! */ #define SPARSE_FADDR_SIZE (sizeof(uint64_t)) @@ -260,13 +267,13 @@ extern void _v(char *file, int line, pthread_mutex_t *m); #define P(x) \ do { int errstat; if ((errstat=pthread_mutex_lock(&(x)))) \ e_msg(__FILE__, __LINE__, M_ABORT, 0, "Mutex lock failure. ERR=%s\n",\ - strerror(errstat)); \ + strerror(errstat)); \ } while(0) #define V(x) \ do { int errstat; if ((errstat=pthread_mutex_unlock(&(x)))) \ - e_msg(__FILE__, __LINE__, M_ABORT, 0, "Mutex unlock failure. ERR=%s\n",\ - strerror(errstat)); \ + e_msg(__FILE__, __LINE__, M_ABORT, 0, "Mutex unlock failure. ERR=%s\n",\ + strerror(errstat)); \ } while(0) #endif /* DEBUG_MUTEX */ @@ -275,13 +282,13 @@ extern void _v(char *file, int line, pthread_mutex_t *m); #define Pw(x) \ do { int errstat; if ((errstat=rwl_writelock(&(x)))) \ e_msg(__FILE__, __LINE__, M_ABORT, 0, "Write lock lock failure. ERR=%s\n",\ - strerror(errstat)); \ + strerror(errstat)); \ } while(0) #define Vw(x) \ do { int errstat; if ((errstat=rwl_writeunlock(&(x)))) \ - e_msg(__FILE__, __LINE__, M_ABORT, 0, "Write lock unlock failure. ERR=%s\n",\ - strerror(errstat)); \ + e_msg(__FILE__, __LINE__, M_ABORT, 0, "Write lock unlock failure. ERR=%s\n",\ + strerror(errstat)); \ } while(0) #define LockRes() b_LockRes(__FILE__, __LINE__) diff --git a/bacula/src/cats/bdb_create.c b/bacula/src/cats/bdb_create.c index 1654041240..c9d9d9bbc7 100644 --- a/bacula/src/cats/bdb_create.c +++ b/bacula/src/cats/bdb_create.c @@ -46,7 +46,7 @@ #ifdef HAVE_BACULA_DB /* Forward referenced functions */ -int db_create_pool_record(B_DB *mdb, POOL_DBR *pr); +bool db_create_pool_record(B_DB *mdb, POOL_DBR *pr); /* ----------------------------------------------------------------------- * @@ -137,7 +137,7 @@ bool db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jm) * Returns: 0 on failure * 1 on success */ -int db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) +bool db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) { int len; POOL_DBR mpr; @@ -171,6 +171,15 @@ int db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) return 1; } +bool db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr) +{ return false; } + +bool db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *dr) +{ return false; } + +bool db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *dr) +{ return false; } + /* * Create Unique Media record. This record @@ -259,7 +268,7 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) * Returns: 0 on failure * 1 on success */ -int db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) +bool db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) { int len; FILESET_DBR lfsr; diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 28c6a41de1..c2d2637b38 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -15,7 +15,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -48,16 +48,6 @@ typedef int (DB_RESULT_HANDLER)(void *, int, char **); #ifdef HAVE_SQLITE -#ifdef HAVE_SQLITE3 -#define sqlite_last_insert_rowid sqlite3_last_insert_rowid -#define sqlite_open sqlite3_open -#define sqlite_close sqlite3_close -#define sqlite_result sqlite3_result -#define sqlite_exec sqlite3_exec -#define sqlite_get_table sqlite3_get_table -#define sqlite_free_table sqlite3_free_table -#endif - #define BDB_VERSION 8 #include @@ -150,6 +140,125 @@ typedef struct s_db { +/* In cats/sqlite.c */ +void my_sqlite_free_table(B_DB *mdb); +SQL_ROW my_sqlite_fetch_row(B_DB *mdb); +int my_sqlite_query(B_DB *mdb, char *cmd); +void my_sqlite_field_seek(B_DB *mdb, int field); +SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb); + + +#else + +/* S Q L I T E 3 */ + + +#ifdef HAVE_SQLITE3 + + +#define BDB_VERSION 8 + +#include + +/* Define opaque structure for sqlite */ +struct sqlite3 { + char dummy; +}; + +#define IS_NUM(x) ((x) == 1) +#define IS_NOT_NULL(x) ((x) == 1) + +typedef struct s_sql_field { + char *name; /* name of column */ + int length; /* length */ + int max_length; /* max length */ + uint32_t type; /* type */ + uint32_t flags; /* flags */ +} SQL_FIELD; + +/* + * This is the "real" definition that should only be + * used inside sql.c and associated database interface + * subroutines. + * S Q L I T E + */ +typedef struct s_db { + BQUEUE bq; /* queue control */ + brwlock_t lock; /* transaction lock */ + struct sqlite3 *db; + char **result; + int status; + int nrow; /* nrow returned from sqlite */ + int ncolumn; /* ncolum returned from sqlite */ + int num_rows; /* used by code */ + int row; /* seek row */ + int field; /* seek field */ + SQL_FIELD **fields; /* defined fields */ + int ref_count; + char *db_name; + char *db_user; + char *db_address; /* host name address */ + char *db_socket; /* socket for local access */ + char *db_password; + int db_port; /* port for host name address */ + bool connected; /* connection made to db */ + bool have_insert_id; /* do not have insert id */ + bool fields_defined; /* set when fields defined */ + char *sqlite_errmsg; /* error message returned by sqlite */ + POOLMEM *errmsg; /* nicely edited error message */ + POOLMEM *cmd; /* SQL command string */ + POOLMEM *cached_path; /* cached path name */ + int cached_path_len; /* length of cached path */ + uint32_t cached_path_id; /* cached path id */ + bool allow_transactions; /* transactions allowed */ + bool transaction; /* transaction started */ + int changes; /* changes during transaction */ + POOLMEM *fname; /* Filename only */ + POOLMEM *path; /* Path only */ + POOLMEM *esc_name; /* Escaped file/path name */ + int fnl; /* file name length */ + int pnl; /* path name length */ +} B_DB; + +/* + * Conversion of sqlite 2 names to sqlite3 + */ +#define sqlite_last_insert_rowid sqlite3_last_insert_rowid +#define sqlite_open sqlite3_open +#define sqlite_close sqlite3_close +#define sqlite_result sqlite3_result +#define sqlite_exec sqlite3_exec +#define sqlite_get_table sqlite3_get_table +#define sqlite_free_table sqlite3_free_table + + +/* + * "Generic" names for easier conversion + * + * S Q L I T E 3 + */ +#define sql_store_result(x) (x)->result +#define sql_free_result(x) my_sqlite_free_table(x) +#define sql_fetch_row(x) my_sqlite_fetch_row(x) +#define sql_query(x, y) my_sqlite_query((x), (y)) +#ifdef HAVE_SQLITE3 +#define sql_insert_id(x,y) sqlite3_last_insert_rowid((x)->db) +#define sql_close(x) sqlite3_close((x)->db) +#else +#define sql_insert_id(x,y) sqlite_last_insert_rowid((x)->db) +#define sql_close(x) sqlite_close((x)->db) +#endif +#define sql_strerror(x) (x)->sqlite_errmsg?(x)->sqlite_errmsg:"unknown" +#define sql_num_rows(x) (x)->nrow +#define sql_data_seek(x, i) (x)->row = (i) +#define sql_affected_rows(x) 1 +#define sql_field_seek(x, y) my_sqlite_field_seek((x), (y)) +#define sql_fetch_field(x) my_sqlite_fetch_field(x) +#define sql_num_fields(x) ((x)->ncolumn) +#define SQL_ROW char** + + + /* In cats/sqlite.c */ void my_sqlite_free_table(B_DB *mdb); SQL_ROW my_sqlite_fetch_row(B_DB *mdb); @@ -357,6 +466,7 @@ typedef struct s_db { uint32_t cached_path_id; } B_DB; +#endif /* HAVE_SQLITE3 */ #endif /* HAVE_MYSQL */ #endif /* HAVE_SQLITE */ #endif /* HAVE_POSTGRESQL */ @@ -454,6 +564,7 @@ struct JOBMEDIA_DBR { /* Volume Parameter structure */ struct VOL_PARAMS { char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ + char MediaType[MAX_NAME_LENGTH]; /* Media Type */ uint32_t VolIndex; /* Volume seqence no. */ uint32_t FirstIndex; /* First index this Volume */ uint32_t LastIndex; /* Last index this Volume */ @@ -491,7 +602,6 @@ struct FILE_DBR { DBId_t PathId; JobId_t MarkId; char LStat[256]; -/* int Status; */ char SIG[50]; int SigType; /* NO_SIG/MD5_SIG/SHA1_SIG */ }; @@ -502,6 +612,7 @@ struct POOL_DBR { char Name[MAX_NAME_LENGTH]; /* Pool name */ uint32_t NumVols; /* total number of volumes */ uint32_t MaxVols; /* max allowed volumes */ + int32_t LabelType; /* Bacula/ANSI/IBM */ int32_t UseOnce; /* set to use once only */ int32_t UseCatalog; /* set to use catalog */ int32_t AcceptAnyVolume; /* set to accept any volume sequence */ @@ -518,6 +629,40 @@ struct POOL_DBR { faddr_t rec_addr; }; +class DEVICE_DBR { +public: + DBId_t DeviceId; + char Name[MAX_NAME_LENGTH]; /* Device name */ + DBId_t MediaTypeId; /* MediaType */ + DBId_t StorageId; /* Storage id if autochanger */ + uint32_t DevMounts; /* Number of times mounted */ + uint32_t DevErrors; /* Number of read/write errors */ + uint64_t DevReadBytes; /* Number of bytes read */ + uint64_t DevWriteBytes; /* Number of bytew written */ + uint64_t DevReadTime; /* time spent reading volume */ + uint64_t DevWriteTime; /* time spent writing volume */ + uint64_t DevReadTimeSincCleaning; /* read time since cleaning */ + uint64_t DevWriteTimeSincCleaning; /* write time since cleaning */ + time_t CleaningDate; /* time last cleaned */ + utime_t CleaningPeriod; /* time between cleanings */ +}; + +class STORAGE_DBR { +public: + DBId_t StorageId; + char Name[MAX_NAME_LENGTH]; /* Device name */ + DBId_t MediaTypeId; /* MediaType */ + int AutoChanger; /* Set if autochanger */ +}; + +class MEDIATYPE_DBR { +public: + DBId_t MediaTypeId; + char MediaType[MAX_NAME_LENGTH]; /* MediaType string */ + int ReadOnly; /* Set if read-only */ +}; + + /* Media record -- same as the database */ struct MEDIA_DBR { DBId_t MediaId; /* Unique volume id */ @@ -527,6 +672,7 @@ struct MEDIA_DBR { time_t FirstWritten; /* Time Volume first written */ time_t LastWritten; /* Time Volume last written */ time_t LabelDate; /* Date/Time Volume labeled */ + int32_t LabelType; /* Label (Bacula/ANSI/IBM) */ uint32_t VolJobs; /* number of jobs on this medium */ uint32_t VolFiles; /* Number of files */ uint32_t VolBlocks; /* Number of blocks */ diff --git a/bacula/src/cats/create_bacula_database.in b/bacula/src/cats/create_bacula_database.in index 57123c07d6..6a3775f823 100644 --- a/bacula/src/cats/create_bacula_database.in +++ b/bacula/src/cats/create_bacula_database.in @@ -3,9 +3,9 @@ # This routine creates the Bacula database # using PostgreSQL, MySQL, or SQLite. # -if test xsqlite = x@DB_NAME@ ; then +if test xsqlite = x@DB_NAME@ -o xsqlite3 = x@DB_NAME@ ; then echo "Creating SQLite database" - @scriptdir@/create_sqlite_database $* + @scriptdir@/create_@DB_NAME@_database $* else if test xmysql = x@DB_NAME@ ; then echo "Creating MySQL database" diff --git a/bacula/src/cats/create_sqlite_database.in b/bacula/src/cats/create_sqlite_database.in index 4cbd7338a6..3d7ba64644 100644 --- a/bacula/src/cats/create_sqlite_database.in +++ b/bacula/src/cats/create_sqlite_database.in @@ -4,7 +4,8 @@ bindir=@SQL_BINDIR@ cd @working_dir@ +sqlite=@DB_NAME@ -$bindir/sqlite $* bacula.db <errmsg, _("query %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_FATAL, 0, "%s", mdb->errmsg); if (verbose) { - j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); + j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return 0; } @@ -118,7 +118,7 @@ InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) m_msg(file, line, &mdb->errmsg, _("insert %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_FATAL, 0, "%s", mdb->errmsg); if (verbose) { - j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); + j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return 0; } @@ -132,7 +132,7 @@ InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) m_msg(file, line, &mdb->errmsg, _("Insertion problem: affected_rows=%s\n"), edit_uint64(mdb->num_rows, ed1)); if (verbose) { - j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); + j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return 0; } @@ -152,7 +152,7 @@ UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) m_msg(file, line, &mdb->errmsg, _("update %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_ERROR, 0, "%s", mdb->errmsg); if (verbose) { - j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); + j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return 0; } @@ -183,7 +183,7 @@ DeleteDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) m_msg(file, line, &mdb->errmsg, _("delete %s failed:\n%s\n"), cmd, sql_strerror(mdb)); j_msg(file, line, jcr, M_ERROR, 0, "%s", mdb->errmsg); if (verbose) { - j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); + j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } return -1; } @@ -206,7 +206,7 @@ int get_sql_record_max(JCR *jcr, B_DB *mdb) if (QUERY_DB(jcr, mdb, mdb->cmd)) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); stat = -1; } else { stat = atoi(row[0]); @@ -411,7 +411,7 @@ list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) for (i = 0; i < sql_num_fields(mdb); i++) { field = sql_fetch_field(mdb); for (j = 0; j < (int)field->max_length + 2; j++) { - send(ctx, "-"); + send(ctx, "-"); } send(ctx, "+"); } @@ -455,7 +455,7 @@ list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type t col_len = field->max_length; } if (col_len < 4 && !IS_NOT_NULL(field->flags)) { - col_len = 4; /* 4 = length of the word "NULL" */ + col_len = 4; /* 4 = length of the word "NULL" */ } field->max_length = col_len; /* reset column info */ } @@ -486,12 +486,12 @@ list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type t for (i = 0; i < sql_num_fields(mdb); i++) { field = sql_fetch_field(mdb); if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL"); + bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL"); } else if (IS_NUM(field->type) && !jcr->gui && is_an_integer(row[i])) { - bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length, + bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length, add_commas(row[i], ewc)); } else { - bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]); + bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]); } send(ctx, buf); } @@ -508,12 +508,12 @@ vertical_list: for (i = 0; i < sql_num_fields(mdb); i++) { field = sql_fetch_field(mdb); if (row[i] == NULL) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); + bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); } else if (IS_NUM(field->type) && !jcr->gui && is_an_integer(row[i])) { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, + bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, add_commas(row[i], ewc)); } else { - bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); + bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); } send(ctx, buf); } @@ -523,4 +523,4 @@ vertical_list: } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 6dffada302..689d4dcc3e 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -34,7 +34,7 @@ #include "bacula.h" #include "cats.h" -#if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL +#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL /* ----------------------------------------------------------------------- * @@ -122,9 +122,9 @@ db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jm) count++; Mmsg(mdb->cmd, - "INSERT INTO JobMedia (JobId,MediaId,FirstIndex,LastIndex," - "StartFile,EndFile,StartBlock,EndBlock,VolIndex) " - "VALUES (%u,%u,%u,%u,%u,%u,%u,%u,%u)", + "INSERT INTO JobMedia (JobId,MediaId,FirstIndex,LastIndex," + "StartFile,EndFile,StartBlock,EndBlock,VolIndex) " + "VALUES (%u,%u,%u,%u,%u,%u,%u,%u,%u)", jm->JobId, jm->MediaId, jm->FirstIndex, jm->LastIndex, jm->StartFile, jm->EndFile, jm->StartBlock, jm->EndBlock,count); @@ -136,10 +136,10 @@ db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jm) } else { /* Worked, now update the Media record with the EndFile and EndBlock */ Mmsg(mdb->cmd, - "UPDATE Media SET EndFile=%u, EndBlock=%u WHERE MediaId=%u", + "UPDATE Media SET EndFile=%u, EndBlock=%u WHERE MediaId=%u", jm->EndFile, jm->EndBlock, jm->MediaId); if (!UPDATE_DB(jcr, mdb, mdb->cmd)) { - Mmsg2(&mdb->errmsg, _("Update Media record %s failed: ERR=%s\n"), mdb->cmd, + Mmsg2(&mdb->errmsg, _("Update Media record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); ok = false; } @@ -152,13 +152,13 @@ db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jm) /* Create Unique Pool record - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int +bool db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) { - int stat; + bool stat; char ed1[30], ed2[30], ed3[50]; Dmsg0(200, "In create pool\n"); @@ -169,10 +169,10 @@ db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 0) { - Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pr->Name); + Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pr->Name); sql_free_result(mdb); db_unlock(mdb); - return 0; + return false; } sql_free_result(mdb); } @@ -198,17 +198,159 @@ db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); pr->PoolId = 0; - stat = 0; + stat = false; } else { pr->PoolId = sql_insert_id(mdb, _("Pool")); - stat = 1; + stat = true; } db_unlock(mdb); + return stat; +} + +/* + * Create Unique Device record + * Returns: false on failure + * true on success + */ +bool +db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr) +{ + bool stat; + char ed1[30], ed2[30]; + + Dmsg0(200, "In create Device\n"); + db_lock(mdb); + Mmsg(mdb->cmd, "SELECT DeviceId,Name FROM Device WHERE Name='%s'", dr->Name); + Dmsg1(200, "selectdevice: %s\n", mdb->cmd); + + if (QUERY_DB(jcr, mdb, mdb->cmd)) { + mdb->num_rows = sql_num_rows(mdb); + if (mdb->num_rows > 0) { + Mmsg1(&mdb->errmsg, _("Device record %s already exists\n"), dr->Name); + sql_free_result(mdb); + db_unlock(mdb); + return false; + } + sql_free_result(mdb); + } + /* Must create it */ + Mmsg(mdb->cmd, +"INSERT INTO Device (Name,MediaTypeId,StorageId) " +"VALUES ('%s',%s,%s)", + dr->Name, + edit_uint64(dr->MediaTypeId, ed1), + edit_uint64(dr->StorageId, ed2)); + Dmsg1(200, "Create Device: %s\n", mdb->cmd); + if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + Mmsg2(&mdb->errmsg, _("Create db Device record %s failed: ERR=%s\n"), + mdb->cmd, sql_strerror(mdb)); + dr->DeviceId = 0; + stat = false; + } else { + dr->DeviceId = sql_insert_id(mdb, _("Device")); + stat = true; + } + db_unlock(mdb); + return stat; +} + +/* + * Create Unique storage record + * Returns: false on failure + * true on success + */ +bool +db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr) +{ + bool stat; + + Dmsg0(200, "In create storage\n"); + db_lock(mdb); + Mmsg(mdb->cmd, "SELECT StorageId,Name FROM Storage WHERE Name='%s'", sr->Name); + Dmsg1(200, "selectstorage: %s\n", mdb->cmd); + + if (QUERY_DB(jcr, mdb, mdb->cmd)) { + mdb->num_rows = sql_num_rows(mdb); + if (mdb->num_rows > 0) { + Mmsg1(&mdb->errmsg, _("Storage record %s already exists\n"), sr->Name); + sql_free_result(mdb); + db_unlock(mdb); + return false; + } + sql_free_result(mdb); + } + + /* Must create it */ + Mmsg(mdb->cmd, +"INSERT INTO Storage (Name,AutoChanger) " +"VALUES ('%s',%d)", + sr->Name, + sr->AutoChanger); + Dmsg1(200, "Create storage: %s\n", mdb->cmd); + if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + Mmsg2(&mdb->errmsg, _("Create db storage record %s failed: ERR=%s\n"), + mdb->cmd, sql_strerror(mdb)); + sr->StorageId = 0; + stat = false; + } else { + sr->StorageId = sql_insert_id(mdb, _("Storage")); + stat = true; + } + db_unlock(mdb); return stat; } +/* + * Create Unique MediaType record + * Returns: false on failure + * true on success + */ +bool +db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *mr) +{ + bool stat; + + Dmsg0(200, "In create mediatype\n"); + db_lock(mdb); + Mmsg(mdb->cmd, "SELECT MediaTypeId,MediaType FROM MediaType WHERE MediaType='%s'", mr->MediaType); + Dmsg1(200, "selectmediatype: %s\n", mdb->cmd); + + if (QUERY_DB(jcr, mdb, mdb->cmd)) { + mdb->num_rows = sql_num_rows(mdb); + if (mdb->num_rows > 0) { + Mmsg1(&mdb->errmsg, _("mediatype record %s already exists\n"), mr->MediaType); + sql_free_result(mdb); + db_unlock(mdb); + return false; + } + sql_free_result(mdb); + } + + /* Must create it */ + Mmsg(mdb->cmd, +"INSERT INTO MediaType (MediaType,ReadOnly) " +"VALUES ('%s',%d)", + mr->MediaType, + mr->ReadOnly); + Dmsg1(200, "Create mediatype: %s\n", mdb->cmd); + if (!INSERT_DB(jcr, mdb, mdb->cmd)) { + Mmsg2(&mdb->errmsg, _("Create db mediatype record %s failed: ERR=%s\n"), + mdb->cmd, sql_strerror(mdb)); + mr->MediaTypeId = 0; + stat = false; + } else { + mr->MediaTypeId = sql_insert_id(mdb, _("MediaType")); + stat = true; + } + db_unlock(mdb); + return stat; +} + + + + /* * Create Media record. VolumeName and non-zero Slot must be unique * @@ -230,7 +372,7 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 0) { - Mmsg1(&mdb->errmsg, _("Volume \"%s\" already exists.\n"), mr->VolumeName); + Mmsg1(&mdb->errmsg, _("Volume \"%s\" already exists.\n"), mr->VolumeName); sql_free_result(mdb); db_unlock(mdb); return 0; @@ -243,8 +385,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes," "Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," "VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts," -"EndFile,EndBlock) " -"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0)", +"EndFile,EndBlock,LabelType) " +"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d)", mr->VolumeName, mr->MediaType, mr->PoolId, edit_uint64(mr->MaxVolBytes,ed1), @@ -260,7 +402,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->InChanger, edit_uint64(mr->VolReadTime, ed6), edit_uint64(mr->VolWriteTime, ed7), - mr->VolParts + mr->VolParts, + mr->LabelType ); @@ -275,9 +418,9 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) if (mr->LabelDate) { char dt[MAX_TIME_LENGTH]; localtime_r(&mr->LabelDate, &tm); - strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); - Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' " - "WHERE MediaId=%d", dt, mr->MediaId); + strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); + Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' " + "WHERE MediaId=%d", dt, mr->MediaId); stat = UPDATE_DB(jcr, mdb, mdb->cmd); } } @@ -303,7 +446,7 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) { SQL_ROW row; int stat; - char ed1[30], ed2[30]; + char ed1[50], ed2[50]; db_lock(mdb); Mmsg(mdb->cmd, "SELECT ClientId,Uname FROM Client WHERE Name='%s'", cr->Name); @@ -313,18 +456,18 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) mdb->num_rows = sql_num_rows(mdb); /* If more than one, report error, but return first row */ if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("More than one Client!: %d\n"), (int)(mdb->num_rows)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("More than one Client!: %d\n"), (int)(mdb->num_rows)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching Client row: %s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching Client row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); sql_free_result(mdb); db_unlock(mdb); return 0; } - cr->ClientId = atoi(row[0]); + cr->ClientId = str_to_int64(row[0]); if (row[1]) { bstrncpy(cr->Uname, row[1], sizeof(cr->Uname)); } else { @@ -338,9 +481,9 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) } /* Must create it */ - Mmsg(mdb->cmd, "INSERT INTO Client (Name, Uname, AutoPrune, " -"FileRetention, JobRetention) VALUES " -"('%s', '%s', %d, %s, %s)", cr->Name, cr->Uname, cr->AutoPrune, + 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)); @@ -403,10 +546,10 @@ int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr) * Returns: 0 on failure * 1 on success with FileSetId in record */ -int db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) +bool db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) { SQL_ROW row; - int stat; + bool stat; struct tm tm; db_lock(mdb); @@ -418,18 +561,18 @@ int db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("More than one FileSet!: %d\n"), (int)(mdb->num_rows)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("More than one FileSet!: %d\n"), (int)(mdb->num_rows)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching FileSet row: ERR=%s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching FileSet row: ERR=%s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); sql_free_result(mdb); db_unlock(mdb); - return 0; + return false; } - fsr->FileSetId = atoi(row[0]); + fsr->FileSetId = str_to_int64(row[0]); if (row[1] == NULL) { fsr->cCreateTime[0] = 0; } else { @@ -437,7 +580,7 @@ int db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) } sql_free_result(mdb); db_unlock(mdb); - return 1; + return true; } sql_free_result(mdb); } @@ -457,11 +600,11 @@ int db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) mdb->cmd, sql_strerror(mdb)); Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); fsr->FileSetId = 0; - stat = 0; + stat = false; } else { fsr->FileSetId = sql_insert_id(mdb, _("FileSet")); fsr->created = true; - stat = 1; + stat = true; } db_unlock(mdb); @@ -558,8 +701,8 @@ static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) /* Must create it */ Mmsg(mdb->cmd, - "INSERT INTO File (FileIndex,JobId,PathId,FilenameId," - "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')", + "INSERT INTO File (FileIndex,JobId,PathId,FilenameId," + "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')", ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, ar->attr); @@ -597,21 +740,21 @@ static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { char ed1[30]; - Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"), + Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"), edit_uint64(mdb->num_rows, ed1), mdb->path); - Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); } /* Even if there are multiple paths, take the first one */ if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); sql_free_result(mdb); ar->PathId = 0; ASSERT(ar->PathId); return 0; } - ar->PathId = atoi(row[0]); + ar->PathId = str_to_int64(row[0]); sql_free_result(mdb); /* Cache path */ if (ar->PathId != mdb->cached_path_id) { @@ -661,18 +804,18 @@ static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { char ed1[30]; - Mmsg2(&mdb->errmsg, _("More than one Filename! %s for file: %s\n"), + Mmsg2(&mdb->errmsg, _("More than one Filename! %s for file: %s\n"), edit_uint64(mdb->num_rows, ed1), mdb->fname); - Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg2(&mdb->errmsg, _("Error fetching row for file=%s: ERR=%s\n"), + Mmsg2(&mdb->errmsg, _("Error fetching row for file=%s: ERR=%s\n"), mdb->fname, sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); ar->FilenameId = 0; } else { - ar->FilenameId = atoi(row[0]); + ar->FilenameId = str_to_int64(row[0]); } sql_free_result(mdb); return ar->FilenameId > 0; @@ -693,4 +836,4 @@ static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) return ar->FilenameId > 0; } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ diff --git a/bacula/src/cats/sql_delete.c b/bacula/src/cats/sql_delete.c index a35b64e900..839c9b39e2 100644 --- a/bacula/src/cats/sql_delete.c +++ b/bacula/src/cats/sql_delete.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -37,7 +37,7 @@ #include "cats.h" -#if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL +#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL /* ----------------------------------------------------------------------- * * Generic Routines (or almost generic) @@ -76,18 +76,18 @@ db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows == 0) { - Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name); + Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name); sql_free_result(mdb); db_unlock(mdb); return 0; } else if (mdb->num_rows != 1) { - Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows); + Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows); sql_free_result(mdb); db_unlock(mdb); return 0; } if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb)); + Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb)); db_unlock(mdb); return 0; } @@ -235,4 +235,4 @@ int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index cb53f6b3d6..f364ca9141 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -11,7 +11,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -39,7 +39,7 @@ #include "bacula.h" #include "cats.h" -#if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL +#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL /* ----------------------------------------------------------------------- * @@ -90,14 +90,14 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) * backup */ if (!QUERY_DB(jcr, mdb, mdb->cmd)) { - Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), + Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); db_unlock(mdb); return 0; } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); - Mmsg(mdb->errmsg, _("No prior Full backup Job record found.\n")); + Mmsg(mdb->errmsg, _("No prior Full backup Job record found.\n")); db_unlock(mdb); return 0; } @@ -110,7 +110,7 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) jr->JobType, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name, jr->ClientId, jr->FileSetId); } else { - Mmsg1(&mdb->errmsg, _("Unknown level=%d\n"), jr->JobLevel); + Mmsg1(&mdb->errmsg, _("Unknown level=%d\n"), jr->JobLevel); db_unlock(mdb); return 0; } @@ -266,33 +266,35 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr if (item == -1) { /* find oldest volume */ /* Find oldest volume */ Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," - "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," - "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," - "FirstWritten,LastWritten,VolStatus,InChanger,VolParts " - "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus IN ('Full'," - "'Recycle','Purged','Used','Append') " - "ORDER BY LastWritten LIMIT 1", mr->PoolId, mr->MediaType); + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," + "FirstWritten,LastWritten,VolStatus,InChanger,VolParts," + "LabelType " + "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus IN ('Full'," + "'Recycle','Purged','Used','Append') " + "ORDER BY LastWritten LIMIT 1", mr->PoolId, mr->MediaType); item = 1; } else { /* Find next available volume */ if (InChanger) { - changer = "AND InChanger=1"; + changer = "AND InChanger=1"; } else { - changer = ""; + changer = ""; } if (strcmp(mr->VolStatus, "Recycled") == 0 || - strcmp(mr->VolStatus, "Purged") == 0) { - order = "ORDER BY LastWritten ASC,MediaId"; /* take oldest */ + strcmp(mr->VolStatus, "Purged") == 0) { + order = "ORDER BY LastWritten ASC,MediaId"; /* take oldest */ } else { - order = "ORDER BY LastWritten IS NULL,LastWritten DESC,MediaId"; /* take most recently written */ + order = "ORDER BY LastWritten IS NULL,LastWritten DESC,MediaId"; /* take most recently written */ } Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," - "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," - "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," - "FirstWritten,LastWritten,VolStatus,InChanger,VolParts " - "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' " - "%s " - "%s LIMIT %d", + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," + "FirstWritten,LastWritten,VolStatus,InChanger,VolParts," + "LabelType " + "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' " + "%s " + "%s LIMIT %d", mr->PoolId, mr->MediaType, mr->VolStatus, changer, order, item); } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { @@ -345,6 +347,7 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr bstrncpy(mr->VolStatus, row[19], sizeof(mr->VolStatus)); mr->InChanger = str_to_int64(row[20]); mr->VolParts = str_to_int64(row[21]); + mr->LabelType = str_to_int64(row[22]); sql_free_result(mdb); db_unlock(mdb); @@ -352,4 +355,4 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 958e86503c..eab5f76aaf 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -10,7 +10,7 @@ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -38,7 +38,7 @@ #include "bacula.h" #include "cats.h" -#if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL +#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL /* ----------------------------------------------------------------------- * @@ -125,12 +125,12 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) mdb->num_rows = sql_num_rows(mdb); Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows); if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("get_file_record want 1 got rows=%d\n"), + Mmsg1(&mdb->errmsg, _("get_file_record want 1 got rows=%d\n"), mdb->num_rows); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb)); + Mmsg1(&mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb)); } else { fdbr->FileId = (FileId_t)str_to_int64(row[0]); bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat)); @@ -138,7 +138,7 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) stat = 1; } } else { - Mmsg2(&mdb->errmsg, _("File record for PathId=%u FilenameId=%u not found.\n"), + Mmsg2(&mdb->errmsg, _("File record for PathId=%u FilenameId=%u not found.\n"), fdbr->PathId, fdbr->FilenameId); } sql_free_result(mdb); @@ -168,23 +168,23 @@ static int db_get_filename_record(JCR *jcr, B_DB *mdb) char ed1[30]; mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg2(&mdb->errmsg, _("More than one Filename!: %s for file: %s\n"), + Mmsg2(&mdb->errmsg, _("More than one Filename!: %s for file: %s\n"), edit_uint64(mdb->num_rows, ed1), mdb->fname); - Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); } else { FilenameId = atoi(row[0]); if (FilenameId <= 0) { - Mmsg2(&mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"), + Mmsg2(&mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"), mdb->cmd, FilenameId); FilenameId = 0; } } } else { - Mmsg1(&mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname); + Mmsg1(&mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname); } sql_free_result(mdb); } else { @@ -218,18 +218,18 @@ static int db_get_path_record(JCR *jcr, B_DB *mdb) char ed1[30]; mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { - Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"), + Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"), edit_uint64(mdb->num_rows, ed1), mdb->path); - Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); } /* Even if there are multiple paths, take the first one */ if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); } else { PathId = atoi(row[0]); if (PathId <= 0) { - Mmsg2(&mdb->errmsg, _("Get DB path record %s found bad record: %u\n"), + Mmsg2(&mdb->errmsg, _("Get DB path record %s found bad record: %u\n"), mdb->cmd, PathId); PathId = 0; } else { @@ -242,7 +242,7 @@ static int db_get_path_record(JCR *jcr, B_DB *mdb) } } } else { - Mmsg1(&mdb->errmsg, _("Path record: %s not found.\n"), mdb->path); + Mmsg1(&mdb->errmsg, _("Path record: %s not found.\n"), mdb->path); } sql_free_result(mdb); } else { @@ -314,19 +314,20 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) * * Returns: number of volumes on success */ -int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames) +int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **VolumeNames) { SQL_ROW row; + char ed1[50]; int stat = 0; int i; db_lock(mdb); /* Get one entry per VolumeName, but "sort" by VolIndex */ Mmsg(mdb->cmd, - "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE " - "JobMedia.JobId=%u AND JobMedia.MediaId=Media.MediaId " - "GROUP BY VolumeName " - "ORDER BY 2 ASC", JobId); + "SELECT VolumeName,MAX(VolIndex) FROM JobMedia,Media WHERE " + "JobMedia.JobId=%s AND JobMedia.MediaId=Media.MediaId " + "GROUP BY VolumeName " + "ORDER BY 2 ASC", edit_uint64(JobId,ed1)); Dmsg1(130, "VolNam=%s\n", mdb->cmd); *VolumeNames[0] = 0; @@ -334,19 +335,19 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **Volum mdb->num_rows = sql_num_rows(mdb); Dmsg1(130, "Num rows=%d\n", mdb->num_rows); if (mdb->num_rows <= 0) { - Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId); + Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId); stat = 0; } else { stat = mdb->num_rows; for (i=0; i < stat; i++) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); stat = 0; break; } else { if (*VolumeNames[0] != 0) { - pm_strcat(VolumeNames, "|"); + pm_strcat(VolumeNames, "|"); } pm_strcat(VolumeNames, row[0]); } @@ -368,26 +369,28 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **Volum * * Returns: number of volumes on success */ -int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams) +int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS **VolParams) { SQL_ROW row; + char ed1[50]; int stat = 0; int i; VOL_PARAMS *Vols = NULL; db_lock(mdb); Mmsg(mdb->cmd, -"SELECT VolumeName,FirstIndex,LastIndex,StartFile,JobMedia.EndFile," -"StartBlock,JobMedia.EndBlock" -" FROM JobMedia,Media WHERE JobMedia.JobId=%u" -" AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId", JobId); +"SELECT VolumeName,MediaType,FirstIndex,LastIndex,StartFile," +"JobMedia.EndFile,StartBlock,JobMedia.EndBlock" +" FROM JobMedia,Media WHERE JobMedia.JobId=%s" +" AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId", + edit_int64(JobId, ed1)); Dmsg1(130, "VolNam=%s\n", mdb->cmd); if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); Dmsg1(130, "Num rows=%d\n", mdb->num_rows); if (mdb->num_rows <= 0) { - Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId); + Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId); stat = 0; } else { stat = mdb->num_rows; @@ -396,18 +399,19 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, uint32_t JobId, VOL_PARAMS } for (i=0; i < stat; i++) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); stat = 0; break; } else { bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH); - Vols[i].FirstIndex = str_to_uint64(row[1]); - Vols[i].LastIndex = str_to_uint64(row[2]); - Vols[i].StartFile = str_to_uint64(row[3]); - Vols[i].EndFile = str_to_uint64(row[4]); - Vols[i].StartBlock = str_to_uint64(row[5]); - Vols[i].EndBlock = str_to_uint64(row[6]); + bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH); + Vols[i].FirstIndex = str_to_uint64(row[2]); + Vols[i].LastIndex = str_to_uint64(row[3]); + Vols[i].StartFile = str_to_uint64(row[4]); + Vols[i].EndFile = str_to_uint64(row[5]); + Vols[i].StartBlock = str_to_uint64(row[6]); + Vols[i].EndBlock = str_to_uint64(row[7]); } } } @@ -541,16 +545,16 @@ int db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { char ed1[30]; - Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), + Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), edit_uint64(mdb->num_rows, ed1)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } else if (mdb->num_rows == 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } else { pdbr->PoolId = str_to_int64(row[0]); - bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name)); + bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name)); pdbr->NumVols = str_to_int64(row[2]); pdbr->MaxVols = str_to_int64(row[3]); pdbr->UseOnce = str_to_int64(row[4]); @@ -563,12 +567,12 @@ int db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) pdbr->MaxVolJobs = str_to_int64(row[11]); pdbr->MaxVolFiles = str_to_int64(row[12]); pdbr->MaxVolBytes = str_to_uint64(row[13]); - bstrncpy(pdbr->PoolType, row[13]!=NULL?row[14]:"", sizeof(pdbr->PoolType)); - bstrncpy(pdbr->LabelFormat, row[14]!=NULL?row[15]:"", sizeof(pdbr->LabelFormat)); + bstrncpy(pdbr->PoolType, row[13]!=NULL?row[14]:"", sizeof(pdbr->PoolType)); + bstrncpy(pdbr->LabelFormat, row[14]!=NULL?row[15]:"", sizeof(pdbr->LabelFormat)); stat = pdbr->PoolId; } } else { - Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n")); + Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n")); } sql_free_result(mdb); } else { @@ -605,24 +609,24 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr) mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { char ed1[30]; - Mmsg1(&mdb->errmsg, _("More than one Client!: %s\n"), + Mmsg1(&mdb->errmsg, _("More than one Client!: %s\n"), edit_uint64(mdb->num_rows, ed1)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } else if (mdb->num_rows == 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } else { cdbr->ClientId = str_to_int64(row[0]); - bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name)); - bstrncpy(cdbr->Uname, row[2]!=NULL?row[1]:"", sizeof(cdbr->Uname)); + bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name)); + bstrncpy(cdbr->Uname, row[2]!=NULL?row[1]:"", sizeof(cdbr->Uname)); cdbr->AutoPrune = str_to_int64(row[3]); cdbr->FileRetention = str_to_int64(row[4]); cdbr->JobRetention = str_to_int64(row[5]); stat = 1; } } else { - Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n")); + Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n")); } sql_free_result(mdb); } else { @@ -651,13 +655,13 @@ int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr) /* If more than one, report error, but return first row */ if (mdb->num_rows > 1) { - Mmsg1(&mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("More than one Counter!: %d\n"), (int)(mdb->num_rows)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } if (mdb->num_rows >= 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); sql_free_result(mdb); db_unlock(mdb); return 0; @@ -698,29 +702,29 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) db_lock(mdb); if (fsr->FileSetId != 0) { /* find by id */ Mmsg(mdb->cmd, - "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet " - "WHERE FileSetId=%u", fsr->FileSetId); + "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet " + "WHERE FileSetId=%u", fsr->FileSetId); } else { /* find by name */ Mmsg(mdb->cmd, - "SELECT FileSetId,FileSet,CreateTime,MD5 FROM FileSet " - "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet); + "SELECT FileSetId,FileSet,CreateTime,MD5 FROM FileSet " + "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet); } if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { char ed1[30]; - Mmsg1(&mdb->errmsg, _("Error got %s FileSets but expected only one!\n"), + Mmsg1(&mdb->errmsg, _("Error got %s FileSets but expected only one!\n"), edit_uint64(mdb->num_rows, ed1)); sql_data_seek(mdb, mdb->num_rows-1); } if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet); + Mmsg1(&mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet); } else { fsr->FileSetId = atoi(row[0]); - bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet)); - bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5)); - bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime)); + bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet)); + bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5)); + bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime)); stat = fsr->FileSetId; } sql_free_result(mdb); @@ -808,33 +812,35 @@ int db_get_media_record(JCR *jcr, 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,MaxVolBytes,VolCapacityBytes," - "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," - "Recycle,Slot,FirstWritten,LastWritten,InChanger,EndFile,EndBlock,VolParts " - "FROM Media WHERE MediaId=%d", mr->MediaId); + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," + "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," + "EndFile,EndBlock,VolParts,LabelType " + "FROM Media WHERE MediaId=%u", mr->MediaId); } else { /* find by name */ Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," - "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," - "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," - "Recycle,Slot,FirstWritten,LastWritten,InChanger,EndFile,EndBlock,VolParts " - "FROM Media WHERE VolumeName='%s'", mr->VolumeName); + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," + "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," + "EndFile,EndBlock,VolParts,LabelType " + "FROM Media WHERE VolumeName='%s'", mr->VolumeName); } if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); if (mdb->num_rows > 1) { char ed1[30]; - Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"), + Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"), edit_uint64(mdb->num_rows, ed1)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } else if (mdb->num_rows == 1) { if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); - Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); } else { /* return values */ mr->MediaId = str_to_int64(row[0]); - bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName)); + bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName)); mr->VolJobs = str_to_int64(row[2]); mr->VolFiles = str_to_int64(row[3]); mr->VolBlocks = str_to_int64(row[4]); @@ -844,8 +850,8 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->VolWrites = str_to_int64(row[8]); mr->MaxVolBytes = str_to_uint64(row[9]); mr->VolCapacityBytes = str_to_uint64(row[10]); - bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType)); - bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus)); + bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType)); + bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus)); mr->PoolId = str_to_int64(row[13]); mr->VolRetention = str_to_uint64(row[14]); mr->VolUseDuration = str_to_uint64(row[15]); @@ -853,31 +859,37 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->MaxVolFiles = str_to_int64(row[17]); mr->Recycle = str_to_int64(row[18]); mr->Slot = str_to_int64(row[19]); - bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten)); + bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten)); mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten); - bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten)); + bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten)); mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten); mr->InChanger = str_to_uint64(row[22]); mr->EndFile = str_to_uint64(row[23]); mr->EndBlock = str_to_uint64(row[24]); mr->VolParts = str_to_int64(row[25]); + mr->LabelType = str_to_int64(row[26]); stat = mr->MediaId; } } else { if (mr->MediaId != 0) { - Mmsg1(&mdb->errmsg, _("Media record MediaId=%u not found.\n"), mr->MediaId); + Mmsg1(&mdb->errmsg, _("Media record MediaId=%u not found.\n"), mr->MediaId); } else { - Mmsg1(&mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"), + Mmsg1(&mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"), mr->VolumeName); } } sql_free_result(mdb); } else { - Mmsg(mdb->errmsg, _("Media record not found in Catalog.\n")); - } + if (mr->MediaId != 0) { + Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"), + mr->MediaId); + } else { + Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"), + mr->VolumeName); + } } db_unlock(mdb); return stat; } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index 287d780935..794a676479 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -34,7 +34,7 @@ #include "bacula.h" #include "cats.h" -#if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL +#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL /* ----------------------------------------------------------------------- * @@ -141,7 +141,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites," "VolCapacityBytes,VolStatus,Recycle,VolRetention," "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," - "EndFile,EndBlock,VolParts " + "EndFile,EndBlock,VolParts,LabelType " "FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName); } else { Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId," @@ -149,7 +149,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites," "VolCapacityBytes,VolStatus,Recycle,VolRetention," "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," - "EndFile,EndBlock,VolParts " + "EndFile,EndBlock,VolParts,LabelType " "FROM Media WHERE Media.PoolId=%u ORDER BY MediaId", mdbr->PoolId); } } else { @@ -337,4 +337,4 @@ db_list_files_for_job(JCR *jcr, B_DB *mdb, uint32_t jobid, DB_LIST_HANDLER *send } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index 3785fda5e7..e007bdf2e9 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -34,7 +34,7 @@ #include "bacula.h" #include "cats.h" -#if HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL +#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL /* ----------------------------------------------------------------------- * @@ -120,7 +120,7 @@ db_update_job_start_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) * */ void edit_num_or_null(char *s, size_t n, uint32_t id) { - bsnprintf(s, n, id ? "%u" : "NULL", id); + bsnprintf(s, n, id ? "%u" : "NULL", id); } @@ -261,7 +261,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) time_t ttime; struct tm tm; int stat; - char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30]; + char ed1[30], ed2[30], ed3[30], ed4[30]; Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten); @@ -286,7 +286,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) localtime_r(&ttime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' " - "WHERE VolumeName='%s'", dt, mr->VolumeName); + "WHERE VolumeName='%s'", dt, mr->VolumeName); stat = UPDATE_DB(jcr, mdb, mdb->cmd); } @@ -296,31 +296,35 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u," - "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," - "VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s'," - "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%s " - " WHERE VolumeName='%s'", + "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," + "VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s'," + "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d," + "LabelType=%d" + " WHERE VolumeName='%s'", mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), mr->VolMounts, mr->VolErrors, mr->VolWrites, edit_uint64(mr->MaxVolBytes, ed2), dt, mr->VolStatus, mr->Slot, mr->InChanger, edit_uint64(mr->VolReadTime, ed3), edit_uint64(mr->VolWriteTime, ed4), - edit_uint64(mr->VolParts, ed5), + mr->VolParts, + mr->LabelType, mr->VolumeName); } else { Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u," - "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," - "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s'," - "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%s " - " WHERE VolumeName='%s'", + "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," + "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s'," + "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d," + "LabelType=%d" + " WHERE VolumeName='%s'", mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), mr->VolMounts, mr->VolErrors, mr->VolWrites, edit_uint64(mr->MaxVolBytes, ed2), mr->VolStatus, mr->Slot, mr->InChanger, edit_uint64(mr->VolReadTime, ed3), edit_uint64(mr->VolWriteTime, ed4), - edit_uint64(mr->VolParts, ed5), + mr->VolParts, + mr->LabelType, mr->VolumeName); } @@ -351,9 +355,9 @@ db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) db_lock(mdb); if (mr->VolumeName[0]) { Mmsg(mdb->cmd, "UPDATE Media SET " - "Recycle=%d,VolRetention=%s,VolUseDuration=%s," - "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s" - " WHERE VolumeName='%s'", + "Recycle=%d,VolRetention=%s,VolUseDuration=%s," + "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s" + " WHERE VolumeName='%s'", mr->Recycle,edit_uint64(mr->VolRetention, ed1), edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles, @@ -361,9 +365,9 @@ db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->VolumeName); } else { Mmsg(mdb->cmd, "UPDATE Media SET " - "Recycle=%d,VolRetention=%s,VolUseDuration=%s," - "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s" - " WHERE PoolId=%u", + "Recycle=%d,VolRetention=%s,VolUseDuration=%s," + "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s" + " WHERE PoolId=%u", mr->Recycle,edit_uint64(mr->VolRetention, ed1), edit_uint64(mr->VolUseDuration, ed2), mr->MaxVolJobs, mr->MaxVolFiles, @@ -391,7 +395,7 @@ db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) { if (mr->InChanger != 0 && mr->Slot != 0) { Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0 WHERE " - "Slot=%d AND PoolId=%u AND MediaId!=%u", + "Slot=%d AND PoolId=%u AND MediaId!=%u", mr->Slot, mr->PoolId, mr->MediaId); Dmsg1(400, "%s\n", mdb->cmd); UPDATE_DB(jcr, mdb, mdb->cmd); @@ -407,4 +411,4 @@ db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) return; } -#endif /* HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ +#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/ diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index c0398f9aa8..4af75d52d0 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -35,7 +35,7 @@ #include "bacula.h" #include "cats.h" -#ifdef HAVE_SQLITE +#if HAVE_SQLITE || HAVE_SQLITE3 /* ----------------------------------------------------------------------- * @@ -70,7 +70,7 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char if (!mult_db_connections) { for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) { if (strcmp(mdb->db_name, db_name) == 0) { - Dmsg2(300, "DB REopen %d %s\n", mdb->ref_count, db_name); + Dmsg2(300, "DB REopen %d %s\n", mdb->ref_count, db_name); mdb->ref_count++; V(mutex); return mdb; /* already open */ @@ -139,16 +139,27 @@ db_open_database(JCR *jcr, B_DB *mdb) V(mutex); return 0; } + +#ifdef HAVE_SQLITE3 + int stat = sqlite3_open(db_name, &mdb->db); + if (stat != SQLITE_OK) { + mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); + } else { + mdb->sqlite_errmsg = NULL; + } + +#else mdb->db = sqlite_open( db_name, /* database name */ 644, /* mode */ &mdb->sqlite_errmsg); /* error message */ +#endif Dmsg0(300, "sqlite_open\n"); if (mdb->db == NULL) { Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"), - db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown")); + db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown")); free(db_name); V(mutex); return 0; @@ -159,7 +170,7 @@ db_open_database(JCR *jcr, B_DB *mdb) return 0; } - mdb->connected = TRUE; + mdb->connected = true; V(mutex); return 1; } @@ -198,6 +209,7 @@ db_close_database(JCR *jcr, B_DB *mdb) */ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) { +#ifdef xxxx SQL_ROW row; db_lock(mdb); @@ -227,6 +239,8 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) sql_free_result(mdb); db_unlock(mdb); +#endif + strcpy(index, "NULL"); return 1; } @@ -248,12 +262,12 @@ db_escape_string(char *snew, char *old, int len) while (len--) { switch (*o) { case '\'': - *n++ = '\''; - *n++ = '\''; + *n++ = '\''; + *n++ = '\''; o++; break; case 0: - *n++ = '\\'; + *n++ = '\\'; *n++ = 0; o++; break; @@ -294,7 +308,11 @@ int db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler db_lock(mdb); if (mdb->sqlite_errmsg) { +#ifdef HAVE_SQLITE3 + sqlite3_free(mdb->sqlite_errmsg); +#else actuallyfree(mdb->sqlite_errmsg); +#endif mdb->sqlite_errmsg = NULL; } rh_data.result_handler = result_handler; @@ -393,6 +411,4 @@ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb) return mdb->fields[mdb->field++]; } - - #endif /* HAVE_SQLITE */ diff --git a/bacula/src/cats/update_bacula_tables.in b/bacula/src/cats/update_bacula_tables.in index 5a7dc89261..d640da17c3 100755 --- a/bacula/src/cats/update_bacula_tables.in +++ b/bacula/src/cats/update_bacula_tables.in @@ -3,9 +3,9 @@ # This routine alters the appropriately configured # Bacula tables for PostgreSQL, MySQL, or SQLite. # -if test xsqlite = x@DB_NAME@ ; then +if test xsqlite = x@DB_NAME@ -o xsqlite3 = x@DB_NAME@ ; then echo "Altering SQLite tables" - @scriptdir@/update_sqlite_tables $* + @scriptdir@/update_@DB_NAME@_tables $* fi if test xmysql = x@DB_NAME@ ; then echo "Altering MySQL tables" diff --git a/bacula/src/cats/update_mysql_tables.in b/bacula/src/cats/update_mysql_tables.in index f47f2137c5..f1bd2a7b51 100755 --- a/bacula/src/cats/update_mysql_tables.in +++ b/bacula/src/cats/update_mysql_tables.in @@ -12,6 +12,7 @@ bindir=@SQL_BINDIR@ if $bindir/mysql $* -f <fname = get_pool_memory(PM_FNAME); - /* * Get the Pool record -- first apply any level defined pools */ @@ -109,11 +103,11 @@ int do_backup(JCR *jcr) while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */ /* Try to create the pool */ if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) { - Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, + Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, db_strerror(jcr->db)); goto bail_out; } else { - Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); + Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); } } jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */ @@ -148,7 +142,7 @@ int do_backup(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr)) { + if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) { goto bail_out; } /* @@ -234,9 +228,9 @@ int wait_for_job_termination(JCR *jcr) &ReadBytes, &JobBytes, &Errors) == 5) { fd_ok = true; set_jcr_job_status(jcr, jcr->FDJobStatus); - Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus); + Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus); } else { - Jmsg(jcr, M_WARNING, 0, _("Unexpected Client Job message: %s\n"), + Jmsg(jcr, M_WARNING, 0, _("Unexpected Client Job message: %s\n"), fd->msg); } if (job_canceled(jcr)) { @@ -326,18 +320,18 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr if (*fname == '|') { fname++; got_pipe = 1; - bpipe = open_bpipe(fname, 0, "w"); + bpipe = open_bpipe(fname, 0, "w"); fd = bpipe ? bpipe->wfd : NULL; } else { /* ***FIXME*** handle BASE */ - fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+"); + fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+"); } if (fd) { VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId, &VolParams); if (VolCount == 0) { - Jmsg(jcr, M_ERROR, 0, _("Could not get Job Volume Parameters to " - "update Bootstrap file. ERR=%s\n"), db_strerror(jcr->db)); + Jmsg(jcr, M_ERROR, 0, _("Could not get Job Volume Parameters to " + "update Bootstrap file. ERR=%s\n"), db_strerror(jcr->db)); if (jcr->SDJobFiles != 0) { set_jcr_job_status(jcr, JS_ErrorTerminated); } @@ -345,14 +339,15 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr } for (int i=0; i < VolCount; i++) { /* Write the record */ - fprintf(fd, "Volume=\"%s\"\n", VolParams[i].VolumeName); - fprintf(fd, "VolSessionId=%u\n", jcr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", jcr->VolSessionTime); - fprintf(fd, "VolFile=%u-%u\n", VolParams[i].StartFile, + fprintf(fd, "Volume=\"%s\"\n", VolParams[i].VolumeName); + fprintf(fd, "MediaType=\"%s\"\n", VolParams[i].MediaType); + fprintf(fd, "VolSessionId=%u\n", jcr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", jcr->VolSessionTime); + fprintf(fd, "VolFile=%u-%u\n", VolParams[i].StartFile, VolParams[i].EndFile); - fprintf(fd, "VolBlock=%u-%u\n", VolParams[i].StartBlock, + fprintf(fd, "VolBlock=%u-%u\n", VolParams[i].StartBlock, VolParams[i].EndBlock); - fprintf(fd, "FileIndex=%d-%d\n", VolParams[i].FirstIndex, + fprintf(fd, "FileIndex=%d-%d\n", VolParams[i].FirstIndex, VolParams[i].LastIndex); } if (VolParams) { @@ -365,8 +360,8 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr } } else { berrno be; - Jmsg(jcr, M_ERROR, 0, _("Could not open WriteBootstrap file:\n" - "%s: ERR=%s\n"), fname, be.strerror()); + Jmsg(jcr, M_ERROR, 0, _("Could not open WriteBootstrap file:\n" + "%s: ERR=%s\n"), fname, be.strerror()); set_jcr_job_status(jcr, JS_ErrorTerminated); } } @@ -375,14 +370,14 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr switch (jcr->JobStatus) { case JS_Terminated: if (jcr->Errors || jcr->SDErrors) { - term_msg = _("Backup OK -- with warnings"); + term_msg = _("Backup OK -- with warnings"); } else { - term_msg = _("Backup OK"); + term_msg = _("Backup OK"); } break; case JS_FatalError: case JS_ErrorTerminated: - term_msg = _("*** Backup Error ***"); + term_msg = _("*** Backup Error ***"); msg_type = M_ERROR; /* Generate error message */ if (jcr->store_bsock) { bnet_sig(jcr->store_bsock, BNET_TERMINATE); @@ -392,7 +387,7 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr } break; case JS_Canceled: - term_msg = _("Backup Canceled"); + term_msg = _("Backup Canceled"); if (jcr->store_bsock) { bnet_sig(jcr->store_bsock, BNET_TERMINATE); if (jcr->SD_msg_chan) { @@ -402,7 +397,7 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr break; default: term_msg = term_code; - sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus); + sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus); break; } bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime); @@ -421,7 +416,7 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr * normal exit should we complain about this error. */ if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes) { - Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); + Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); } jcr->VolumeName[0] = 0; /* none */ } @@ -431,9 +426,9 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr } else { compression = (double)100 - 100.0 * ((double)jcr->JobBytes / (double)jcr->ReadBytes); if (compression < 0.5) { - bstrncpy(compress, "None", sizeof(compress)); + bstrncpy(compress, "None", sizeof(compress)); } else { - bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression); + bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression); } } jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg)); diff --git a/bacula/src/dird/bsr.c b/bacula/src/dird/bsr.c index 4545d65504..9554cf2db7 100644 --- a/bacula/src/dird/bsr.c +++ b/bacula/src/dird/bsr.c @@ -11,7 +11,7 @@ */ /* - Copyright (C) 2002-2004 Kern Sibbald and John Walker + Copyright (C) 2002-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -79,10 +79,10 @@ static uint32_t write_findex(UAContext *ua, RBSR_FINDEX *fi, findex = fi->findex < FirstIndex ? FirstIndex : fi->findex; findex2 = fi->findex2 > LastIndex ? LastIndex : fi->findex2; if (findex == findex2) { - fprintf(fd, "FileIndex=%d\n", findex); + fprintf(fd, "FileIndex=%d\n", findex); count++; } else { - fprintf(fd, "FileIndex=%d-%d\n", findex, findex2); + fprintf(fd, "FileIndex=%d-%d\n", findex, findex2); count += findex2 - findex + 1; } } @@ -115,10 +115,10 @@ static void print_findex(UAContext *ua, RBSR_FINDEX *fi) bsendmsg(ua, "fi=0x%lx\n", fi); for ( ; fi; fi=fi->next) { if (fi->findex == fi->findex2) { - bsendmsg(ua, "FileIndex=%d\n", fi->findex); + bsendmsg(ua, "FileIndex=%d\n", fi->findex); // Dmsg1(100, "FileIndex=%d\n", fi->findex); } else { - bsendmsg(ua, "FileIndex=%d-%d\n", fi->findex, fi->findex2); + bsendmsg(ua, "FileIndex=%d-%d\n", fi->findex, fi->findex2); // Dmsg2(100, "FileIndex=%d-%d\n", fi->findex, fi->findex2); } } @@ -156,14 +156,14 @@ int complete_bsr(UAContext *ua, RBSR *bsr) memset(&jr, 0, sizeof(jr)); jr.JobId = bsr->JobId; if (!db_get_job_record(ua->jcr, ua->db, &jr)) { - bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db)); + bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db)); return 0; } bsr->VolSessionId = jr.VolSessionId; bsr->VolSessionTime = jr.VolSessionTime; if ((bsr->VolCount=db_get_job_volume_parameters(ua->jcr, ua->db, bsr->JobId, &(bsr->VolParams))) == 0) { - bsendmsg(ua, _("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db)); + bsendmsg(ua, _("Unable to get Job Volume Parameters. ERR=%s\n"), db_strerror(ua->db)); if (bsr->VolParams) { free(bsr->VolParams); bsr->VolParams = NULL; @@ -251,19 +251,20 @@ static uint32_t write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ continue; } - fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); - fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); + fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); + fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); + fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); } else { - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, + fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, bsr->VolParams[i].EndFile); } if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartBlock); + fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartBlock); } else { - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, + fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, bsr->VolParams[i].EndBlock); } // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", @@ -272,7 +273,7 @@ static uint32_t write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex, fd); if (count) { - fprintf(fd, "Count=%u\n", count); + fprintf(fd, "Count=%u\n", count); } total_count += count; /* If the same file is present on two tapes or in two files @@ -294,12 +295,13 @@ void print_bsr(UAContext *ua, RBSR *bsr) { if (bsr) { for (int i=0; i < bsr->VolCount; i++) { - bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); - bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId); - bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime); - bsendmsg(ua, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, + bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + bsendmsg(ua, "MediaType\"%s\"\n", bsr->VolParams[i].MediaType); + bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId); + bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime); + bsendmsg(ua, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, bsr->VolParams[i].EndFile); - bsendmsg(ua, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, + bsendmsg(ua, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, bsr->VolParams[i].EndBlock); print_findex(ua, bsr->fi); } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 1cacf01797..21d759e6e4 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -45,14 +45,14 @@ static char Find_media[] = "CatReq Job=%127s FindMedia=%d\n"; static char Get_Vol_Info[] = "CatReq Job=%127s GetVolInfo VolName=%127s write=%d\n"; static char Update_media[] = "CatReq Job=%127s UpdateMedia VolName=%s" -" VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%" lld " VolMounts=%u" -" VolErrors=%u VolWrites=%u MaxVolBytes=%" lld " EndTime=%d VolStatus=%10s" -" Slot=%d relabel=%d InChanger=%d VolReadTime=%" lld " VolWriteTime=%" lld -" VolParts=%u\n"; + " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%" lld " VolMounts=%u" + " VolErrors=%u VolWrites=%u MaxVolBytes=%" lld " EndTime=%d VolStatus=%10s" + " Slot=%d relabel=%d InChanger=%d VolReadTime=%" lld " VolWriteTime=%" lld + " VolParts=%u\n"; static char Create_job_media[] = "CatReq Job=%127s CreateJobMedia " -" FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u " -" StartBlock=%u EndBlock=%u\n"; + " FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u " + " StartBlock=%u EndBlock=%u\n"; /* Responses sent to Storage daemon */ @@ -60,7 +60,7 @@ static char OK_media[] = "1000 OK VolName=%s VolJobs=%u VolFiles=%u" " VolBlocks=%u VolBytes=%s VolMounts=%u VolErrors=%u VolWrites=%u" " MaxVolBytes=%s VolCapacityBytes=%s VolStatus=%s Slot=%d" " MaxVolJobs=%u MaxVolFiles=%u InChanger=%d VolReadTime=%s" - " VolWriteTime=%s EndFile=%u EndBlock=%u VolParts=%u\n"; + " VolWriteTime=%s EndFile=%u EndBlock=%u VolParts=%u LabelType=%d\n"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -83,9 +83,10 @@ static int send_volume_info_to_storage_daemon(JCR *jcr, BSOCK *sd, MEDIA_DBR *mr edit_uint64(mr->VolReadTime, ed4), edit_uint64(mr->VolWriteTime, ed5), mr->EndFile, mr->EndBlock, - mr->VolParts); + mr->VolParts, + mr->LabelType); unbash_spaces(mr->VolumeName); - Dmsg2(200, "Vol Info for %s: %s", jcr->Job, sd->msg); + Dmsg2(400, "Vol Info for %s: %s", jcr->Job, sd->msg); return stat; } @@ -104,7 +105,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) /* * Request to find next appendable Volume for this Job */ - Dmsg1(200, "catreq %s", bs->msg); + Dmsg1(400, "catreq %s", bs->msg); if (sscanf(bs->msg, Find_media, &Job, &index) == 2) { ok = find_next_volume_for_append(jcr, &mr, true /*permit create new vol*/); /* @@ -182,21 +183,22 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) * of a Storage daemon Job Session, when labeling/relabeling a * Volume, or when an EOF mark is written. */ - } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName, &sdmr.VolJobs, - &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes, &sdmr.VolMounts, &sdmr.VolErrors, - &sdmr.VolWrites, &sdmr.MaxVolBytes, &sdmr.LastWritten, &sdmr.VolStatus, - &sdmr.Slot, &label, &sdmr.InChanger, &sdmr.VolReadTime, - &sdmr.VolWriteTime, &sdmr.VolParts) == 18) { + } else if (sscanf(bs->msg, Update_media, &Job, &sdmr.VolumeName, + &sdmr.VolJobs, &sdmr.VolFiles, &sdmr.VolBlocks, &sdmr.VolBytes, + &sdmr.VolMounts, &sdmr.VolErrors, &sdmr.VolWrites, &sdmr.MaxVolBytes, + &sdmr.LastWritten, &sdmr.VolStatus, &sdmr.Slot, &label, &sdmr.InChanger, + &sdmr.VolReadTime, &sdmr.VolWriteTime, &sdmr.VolParts) == 18) { db_lock(jcr->db); - Dmsg3(300, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName, + Dmsg3(400, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName, mr.VolStatus, sdmr.VolStatus); bstrncpy(mr.VolumeName, sdmr.VolumeName, sizeof(mr.VolumeName)); /* copy Volume name */ unbash_spaces(mr.VolumeName); if (!db_get_media_record(jcr, jcr->db, &mr)) { Jmsg(jcr, M_ERROR, 0, _("Unable to get Media record for Volume %s: ERR=%s\n"), mr.VolumeName, db_strerror(jcr->db)); - bnet_fsend(bs, "1991 Catalog Request failed: %s", db_strerror(jcr->db)); + bnet_fsend(bs, "1991 Catalog Request for vol=%s failed: %s", + mr.VolumeName, db_strerror(jcr->db)); db_unlock(jcr->db); return; } @@ -205,7 +207,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) mr.FirstWritten = jcr->start_time; /* use Job start time as first write */ } /* If we just labeled the tape set time */ - Dmsg2(300, "label=%d labeldate=%d\n", label, mr.LabelDate); + Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate); if (label || mr.LabelDate == 0) { mr.LabelDate = time(NULL); } else { @@ -217,7 +219,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) mr.VolFiles, sdmr.VolFiles); } } - Dmsg2(300, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs); + Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs); /* Copy updated values to original media record */ mr.VolJobs = sdmr.VolJobs; mr.VolFiles = sdmr.VolFiles; @@ -234,7 +236,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) mr.VolParts = sdmr.VolParts; bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); - Dmsg2(300, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); + Dmsg2(400, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); /* * Check if it has expired, and if not update the DB. Note, if * Volume has expired, has_volume_expired() will update the DB. @@ -247,7 +249,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) Jmsg(jcr, M_ERROR, 0, _("Catalog error updating Media record. %s"), db_strerror(jcr->db)); bnet_fsend(bs, "1992 Update Media error\n"); - Dmsg0(190, "send error\n"); + Dmsg0(400, "send error\n"); } db_unlock(jcr->db); @@ -260,14 +262,14 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) jm.JobId = jcr->JobId; jm.MediaId = jcr->MediaId; - Dmsg6(300, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n", + Dmsg6(400, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n", jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex); if (!db_create_jobmedia_record(jcr, jcr->db, &jm)) { Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"), db_strerror(jcr->db)); bnet_fsend(bs, "1991 Update JobMedia error\n"); } else { - Dmsg0(300, "JobMedia record created\n"); + Dmsg0(400, "JobMedia record created\n"); bnet_fsend(bs, OK_create); } @@ -278,8 +280,8 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) Jmsg1(jcr, M_ERROR, 0, _("Invalid Catalog request: %s"), omsg); free_memory(omsg); } - Dmsg1(300, ">CatReq response: %s", bs->msg); - Dmsg1(200, "Leave catreq jcr 0x%x\n", jcr); + Dmsg1(400, ">CatReq response: %s", bs->msg); + Dmsg1(400, "Leave catreq jcr 0x%x\n", jcr); return; } @@ -320,8 +322,8 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) unser_uint32(data_len); p += unser_length(p); - Dmsg1(300, "UpdCat msg=%s\n", bs->msg); - Dmsg5(300, "UpdCat VolSessId=%d VolSessT=%d FI=%d Strm=%d data_len=%d\n", + Dmsg1(400, "UpdCat msg=%s\n", bs->msg); + Dmsg5(400, "UpdCat VolSessId=%d VolSessT=%d FI=%d Strm=%d data_len=%d\n", VolSessionId, VolSessionTime, FileIndex, Stream, data_len); if (Stream == STREAM_UNIX_ATTRIBUTES || Stream == STREAM_UNIX_ATTRIBUTES_EX) { @@ -333,8 +335,8 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) len = strlen(fname); /* length before attributes */ attr = &fname[len+1]; - Dmsg2(300, "dirdJobId; - Dmsg2(300, "dirddb, &ar)) { Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db)); @@ -367,7 +369,7 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) type = SHA1_SIG; } bin_to_base64(SIGbuf, fname, len); - Dmsg3(190, "SIGlen=%d SIG=%s type=%d\n", strlen(SIGbuf), SIGbuf, Stream); + Dmsg3(400, "SIGlen=%d SIG=%s type=%d\n", strlen(SIGbuf), SIGbuf, Stream); if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIGbuf, type)) { Jmsg(jcr, M_ERROR, 0, _("Catalog error updating MD5/SHA1. %s"), db_strerror(jcr->db)); diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index e3484c79db..7dccc44081 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -7,7 +7,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -50,6 +50,7 @@ void term_job_server(); void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass); void store_level(LEX *lc, RES_ITEM *item, int index, int pass); void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); +void init_device_resources(); static char *configfile = NULL; static char *runjob = NULL; @@ -74,7 +75,7 @@ extern URES res_all; static void usage() { fprintf(stderr, _( -"Copyright (C) 2000-2004 Kern Sibbald and John Walker\n" +"Copyright (C) 2000-2005 Kern Sibbald.\n" "\nVersion: " VERSION " (" BDATE ")\n\n" "Usage: dird [-f -s] [-c config_file] [-d debug_level] [config_file]\n" " -c set configuration file to file\n" @@ -238,6 +239,8 @@ int main (int argc, char *argv[]) init_job_server(director->MaxConcurrentJobs); + init_device_resources(); + Dmsg0(200, "wait for next job\n"); /* Main loop -- call scheduler to get next job to run */ while ((jcr = wait_for_next_job(runjob))) { @@ -499,13 +502,11 @@ static int check_resources() if (job->jobdefs) { /* Handle Storage alists specifically */ JOB *jobdefs = job->jobdefs; - for (i=0; i < MAX_STORE; i++) { - if (jobdefs->storage[i] && !job->storage[i]) { - STORE *st; - job->storage[i] = New(alist(10, not_owned_by_alist)); - foreach_alist(st, jobdefs->storage[i]) { - job->storage[i]->append(st); - } + if (jobdefs->storage && !job->storage) { + STORE *st; + job->storage = New(alist(10, not_owned_by_alist)); + foreach_alist(st, jobdefs->storage) { + job->storage->append(st); } } @@ -637,8 +638,26 @@ static int check_resources() foreach_res(pool, R_POOL) { create_pool(NULL, db, pool, POOL_OP_UPDATE); /* update request */ } - /* Loop over all counters, defining them in each database */ + /* ***FIXME*** we need to update store and media_type records */ + STORE *store; + foreach_res(store, R_STORAGE) { + STORAGE_DBR sr; + MEDIATYPE_DBR mr; + if (store->media_type) { + bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); + mr.ReadOnly = 0; + db_create_mediatype_record(NULL, db, &mr); + } else { + mr.MediaTypeId = 0; + } + sr.MediaTypeId = mr.MediaTypeId; + bstrncpy(sr.Name, store->name(), sizeof(sr.Name)); + sr.AutoChanger = store->autochanger; + db_create_storage_record(NULL, db, &sr); + } + + /* Loop over all counters, defining them in each database */ /* Set default value in all counters */ COUNTER *counter; foreach_res(counter, R_COUNTER) { diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 430d0a6bec..d388fc963b 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -63,8 +63,10 @@ extern void store_inc(LEX *lc, RES_ITEM *item, int index, int pass); void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass); void store_level(LEX *lc, RES_ITEM *item, int index, int pass); +void store_label(LEX *lc, RES_ITEM *item, int index, int pass); void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); void store_acl(LEX *lc, RES_ITEM *item, int index, int pass); +static void store_device(LEX *lc, RES_ITEM *item, int index, int pass); /* We build the current resource here as we are @@ -164,8 +166,7 @@ static RES_ITEM store_items[] = { {"sdaddress", store_str, ITEM(res_store.address), 0, 0, 0}, {"password", store_password, ITEM(res_store.password), 0, ITEM_REQUIRED, 0}, {"sdpassword", store_password, ITEM(res_store.password), 0, 0, 0}, - {"device", store_strname, ITEM(res_store.dev_name), 0, ITEM_REQUIRED, 0}, - {"sddevicename", store_strname, ITEM(res_store.dev_name), 0, 0, 0}, + {"device", store_device, ITEM(res_store.device), R_DEVICE, ITEM_REQUIRED, 0}, {"mediatype", store_strname, ITEM(res_store.media_type), 0, ITEM_REQUIRED, 0}, {"autochanger", store_yesno, ITEM(res_store.autochanger), 1, ITEM_DEFAULT, 0}, {"enablessl", store_yesno, ITEM(res_store.enable_ssl), 1, ITEM_DEFAULT, 0}, @@ -206,7 +207,7 @@ RES_ITEM job_items[] = { {"type", store_jobtype, ITEM(res_job.JobType), 0, ITEM_REQUIRED, 0}, {"level", store_level, ITEM(res_job.JobLevel), 0, 0, 0}, {"messages", store_res, ITEM(res_job.messages), R_MSGS, ITEM_REQUIRED, 0}, - {"storage", store_alist_res, ITEM(res_job.storage), R_STORAGE, ITEM_REQUIRED, MAX_STORE}, + {"storage", store_alist_res, ITEM(res_job.storage), R_STORAGE, ITEM_REQUIRED, 0}, {"pool", store_res, ITEM(res_job.pool), R_POOL, ITEM_REQUIRED, 0}, {"fullbackuppool", store_res, ITEM(res_job.full_pool), R_POOL, 0, 0}, {"incrementalbackuppool", store_res, ITEM(res_job.inc_pool), R_POOL, 0, 0}, @@ -279,22 +280,23 @@ static RES_ITEM pool_items[] = { {"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}, - {"cleaningprefix", store_strname, ITEM(res_pool.cleaning_prefix), 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}, + {"labeltype", store_label, ITEM(res_pool.LabelType), 0, 0, 0}, + {"cleaningprefix", store_strname, ITEM(res_pool.cleaning_prefix), 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}, {"purgeoldestvolume", store_yesno, ITEM(res_pool.purge_oldest_volume), 1, 0, 0}, - {"recycleoldestvolume", store_yesno, ITEM(res_pool.recycle_oldest_volume), 1, 0, 0}, + {"recycleoldestvolume", store_yesno, ITEM(res_pool.recycle_oldest_volume), 1, 0, 0}, {"recyclecurrentvolume", store_yesno, ITEM(res_pool.recycle_current_volume), 1, 0, 0}, - {"maximumvolumes", store_pint, ITEM(res_pool.max_volumes), 0, 0, 0}, + {"maximumvolumes", store_pint, ITEM(res_pool.max_volumes), 0, 0, 0}, {"maximumvolumejobs", store_pint, ITEM(res_pool.MaxVolJobs), 0, 0, 0}, {"maximumvolumefiles", store_pint, ITEM(res_pool.MaxVolFiles), 0, 0, 0}, {"maximumvolumebytes", store_size, ITEM(res_pool.MaxVolBytes), 0, 0, 0}, - {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, ITEM_DEFAULT, 1}, - {"catalogfiles", store_yesno, ITEM(res_pool.catalog_files), 1, ITEM_DEFAULT, 1}, - {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, - {"volumeuseduration", store_time, ITEM(res_pool.VolUseDuration),0, 0, 0}, - {"autoprune", store_yesno, ITEM(res_pool.AutoPrune), 1, ITEM_DEFAULT, 1}, - {"recycle", store_yesno, ITEM(res_pool.Recycle), 1, ITEM_DEFAULT, 1}, + {"acceptanyvolume", store_yesno, ITEM(res_pool.accept_any_volume), 1, ITEM_DEFAULT, 1}, + {"catalogfiles", store_yesno, ITEM(res_pool.catalog_files), 1, ITEM_DEFAULT, 1}, + {"volumeretention", store_time, ITEM(res_pool.VolRetention), 0, ITEM_DEFAULT, 60*60*24*365}, + {"volumeuseduration", store_time, ITEM(res_pool.VolUseDuration), 0, 0, 0}, + {"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} }; @@ -338,6 +340,7 @@ RES_TABLE resources[] = { {"counter", counter_items, R_COUNTER}, {"console", con_items, R_CONSOLE}, {"jobdefs", job_items, R_JOBDEFS}, + {"device", NULL, R_DEVICE}, /* info obtained from SD */ {NULL, NULL, 0} }; @@ -374,6 +377,19 @@ struct s_jt jobtypes[] = { {NULL, 0} }; +/* + * Tape Label types permitted in Pool records + * + * tape label label code = token + */ +struct s_kw tapelabels[] = { + {"bacula", B_BACULA_LABEL}, + {"ansi", B_ANSI_LABEL}, + {"ibm", B_IBM_LABEL}, + {NULL, 0} +}; + + #ifdef old_deprecated_code /* Keywords (RHS) permitted in Backup and Verify records */ @@ -427,6 +443,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm URES *res = (URES *)reshdr; bool recurse = true; char ed1[100], ed2[100]; + DEVICE *dev; if (res == NULL) { sendit(sock, "No %s resource defined\n", res_to_str(type)); @@ -484,12 +501,22 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock); } break; + case R_DEVICE: + dev = &res->res_dev; + sendit(sock, "Device: name=%s ok=%d num_writers=%d num_waiting=%d\n" +" use_cnt=%d open=%d append=%d read=%d labeled=%d\n" +" volname=%s MediaType=%s\n", + dev->hdr.name, dev->found, dev->num_writers, dev->num_waiting, + dev->use_count, dev->open, dev->append, dev->read, dev->labeled, + dev->VolumeName, dev->MediaType); + break; case R_STORAGE: sendit(sock, "Storage: name=%s address=%s SDport=%d MaxJobs=%u\n" " DeviceName=%s MediaType=%s\n", res->res_store.hdr.name, res->res_store.address, res->res_store.SDport, res->res_store.MaxConcurrentJobs, - res->res_store.dev_name, res->res_store.media_type); + res->res_store.dev_name(), + res->res_store.media_type); break; case R_CATALOG: sendit(sock, "Catalog: name=%s address=%s DBport=%d db_name=%s\n" @@ -539,10 +566,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm if (res->res_job.WriteBootstrap) { sendit(sock, " --> WriteBootstrap=%s\n", NPRT(res->res_job.WriteBootstrap)); } - if (res->res_job.storage[0]) { - sendit(sock, " --> "); - /* ***FIXME*** */ -// dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock); + if (res->res_job.storage) { + STORE *store; + foreach_alist(store, res->res_job.storage) { + sendit(sock, " --> "); + dump_resource(-R_STORAGE, (RES *)store, sendit, sock); + } } if (res->res_job.pool) { sendit(sock, " --> "); @@ -832,6 +861,7 @@ void free_resource(RES *sres, int type) free_addresses(res->res_dir.DIRaddrs); } break; + case R_DEVICE: case R_COUNTER: break; case R_CONSOLE: @@ -863,8 +893,8 @@ void free_resource(RES *sres, int type) if (res->res_store.media_type) { free(res->res_store.media_type); } - if (res->res_store.dev_name) { - free(res->res_store.dev_name); + if (res->res_store.device) { + delete res->res_store.device; } break; case R_CATALOG: @@ -948,10 +978,8 @@ void free_resource(RES *sres, int type) if (res->res_job.ClientRunAfterJob) { free(res->res_job.ClientRunAfterJob); } - for (int i=0; i < MAX_STORE; i++) { - if (res->res_job.storage[i]) { - delete (alist *)res->res_job.storage[i]; - } + if (res->res_job.storage) { + delete res->res_job.storage; } break; case R_MSGS: @@ -987,7 +1015,7 @@ void save_resource(int type, RES_ITEM *items, int pass) URES *res; int rindex = type - r_first; int i, size; - int error = 0; + bool error = false; /* Check Job requirements after applying JobDefs */ if (type != R_JOB && type != R_JOBDEFS) { @@ -1019,19 +1047,27 @@ void save_resource(int type, RES_ITEM *items, int pass) /* Resources not containing a resource */ case R_CONSOLE: case R_CATALOG: - case R_STORAGE: case R_POOL: case R_MSGS: case R_FILESET: + case R_DEVICE: break; - /* Resources containing another resource */ + /* Resources containing another resource or alist */ case R_DIRECTOR: if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource %s\n", res_all.res_dir.hdr.name); } res->res_dir.messages = res_all.res_dir.messages; break; + case R_STORAGE: + if ((res = (URES *)GetResWithName(type, res_all.res_store.hdr.name)) == NULL) { + Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource %s\n", + res_all.res_dir.hdr.name); + } + /* we must explicitly copy the device alist pointer */ + res->res_store.device = res_all.res_store.device; + break; case R_JOB: case R_JOBDEFS: if ((res = (URES *)GetResWithName(type, res_all.res_dir.hdr.name)) == NULL) { @@ -1042,9 +1078,7 @@ void save_resource(int type, RES_ITEM *items, int pass) res->res_job.schedule = res_all.res_job.schedule; res->res_job.client = res_all.res_job.client; res->res_job.fileset = res_all.res_job.fileset; - for (int i=0; i < MAX_STORE; i++) { - res->res_job.storage[i] = res_all.res_job.storage[i]; - } + res->res_job.storage = res_all.res_job.storage; res->res_job.pool = res_all.res_job.pool; res->res_job.full_pool = res_all.res_job.full_pool; res->res_job.inc_pool = res_all.res_job.inc_pool; @@ -1080,7 +1114,7 @@ void save_resource(int type, RES_ITEM *items, int pass) break; default: Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type); - error = 1; + error = true; break; } /* Note, the resource name was already saved during pass 1, @@ -1135,10 +1169,12 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_COUNTER: size = sizeof(COUNTER); break; + case R_DEVICE: + error = true; + break; default: printf("Unknown resource type %d in save_resrouce.\n", type); - error = 1; - size = 1; + error = true; break; } /* Common */ @@ -1166,6 +1202,55 @@ void save_resource(int type, RES_ITEM *items, int pass) } } +/* + * Store Device. Note, the resource is created upon the + * first reference. The details of the resource are obtained + * later from the SD. + */ +static void store_device(LEX *lc, RES_ITEM *item, int index, int pass) +{ + int token; + URES *res; + int rindex = R_DEVICE - r_first; + int size = sizeof(DEVICE); + bool found = false; + + if (pass == 1) { + token = lex_get_token(lc, T_NAME); + if (!res_head[rindex]) { + res = (URES *)malloc(size); + memset(res, 0, size); + res->res_dev.hdr.name = bstrdup(lc->str); + res_head[rindex] = (RES *)res; /* store first entry */ + Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(R_DEVICE), + res->res_dir.hdr.name, rindex); + } else { + RES *next; + /* See if it is already defined */ + for (next=res_head[rindex]; next->next; next=next->next) { + if (strcmp(next->name, lc->str) == 0) { + found = true; + break; + } + } + if (!found) { + res = (URES *)malloc(size); + memset(res, 0, size); + res->res_dev.hdr.name = bstrdup(lc->str); + next->next = (RES *)res; + Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(R_DEVICE), + res->res_dir.hdr.name, rindex, pass); + } + } + + scan_to_eol(lc); + set_bit(index, res_all.hdr.item_present); + } else { + store_alist_res(lc, item, index, pass); + } +} + + /* * Store JobType (backup, verify, restore) * @@ -1214,6 +1299,33 @@ void store_level(LEX *lc, RES_ITEM *item, int index, int pass) set_bit(index, res_all.hdr.item_present); } + +/* + * Store Tape Label Type (Bacula, ANSI, IBM) + * + */ +void store_label(LEX *lc, RES_ITEM *item, int index, int pass) +{ + int token, i; + + token = lex_get_token(lc, T_NAME); + /* Store the label pass 2 so that type is defined */ + for (i=0; tapelabels[i].name; i++) { + if (strcasecmp(lc->str, tapelabels[i].name) == 0) { + *(int *)(item->value) = tapelabels[i].token; + i = 0; + break; + } + } + if (i != 0) { + scan_err1(lc, "Expected a Tape Label keyword, got: %s", lc->str); + } + scan_to_eol(lc); + set_bit(index, res_all.hdr.item_present); +} + + + void store_replace(LEX *lc, RES_ITEM *item, int index, int pass) { int token, i; diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 084257de23..b1542aa1b3 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -43,8 +43,9 @@ enum { R_COUNTER, R_CONSOLE, R_JOBDEFS, + R_DEVICE, R_FIRST = R_DIRECTOR, - R_LAST = R_JOBDEFS /* keep this updated */ + R_LAST = R_DEVICE /* keep this updated */ }; @@ -68,9 +69,9 @@ struct s_kw { /* Job Level keyword structure */ struct s_jl { - const char *level_name; /* level keyword */ - int level; /* level */ - int job_type; /* JobType permitting this level */ + const char *level_name; /* level keyword */ + int level; /* level */ + int job_type; /* JobType permitting this level */ }; /* Job Type keyword structure */ @@ -86,28 +87,53 @@ struct CLIENT; struct FILESET; struct POOL; struct RUN; +struct DEVICE; /* * Director Resource * */ -struct DIRRES { - RES hdr; +class DIRRES { +public: + RES hdr; dlist *DIRaddrs; - char *password; /* Password for UA access */ - int enable_ssl; /* Use SSL for UA */ - char *query_file; /* SQL query file */ - char *working_directory; /* WorkingDirectory */ + char *password; /* Password for UA access */ + int enable_ssl; /* Use SSL for UA */ + char *query_file; /* SQL query file */ + char *working_directory; /* WorkingDirectory */ const char *scripts_directory; /* ScriptsDirectory */ - char *pid_directory; /* PidDirectory */ - char *subsys_directory; /* SubsysDirectory */ - int require_ssl; /* Require SSL for all connections */ - MSGS *messages; /* Daemon message handler */ - uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */ - utime_t FDConnectTimeout; /* timeout for connect in seconds */ - utime_t SDConnectTimeout; /* timeout in seconds */ + char *pid_directory; /* PidDirectory */ + char *subsys_directory; /* SubsysDirectory */ + int require_ssl; /* Require SSL for all connections */ + MSGS *messages; /* Daemon message handler */ + uint32_t MaxConcurrentJobs; /* Max concurrent jobs for whole director */ + utime_t FDConnectTimeout; /* timeout for connect in seconds */ + utime_t SDConnectTimeout; /* timeout in seconds */ }; +/* + * Device Resource + * This resource is a bit different from the other resources + * because it is not defined in the Director + * by DEVICE { ... }, but rather by a "reference" such as + * DEVICE = xxx; Then when the Director connects to the + * SD, it requests the information about the device. + */ +class DEVICE { +public: + RES hdr; + + bool found; /* found with SD */ + int num_writers; + int num_waiting; + int use_count; + bool open; + bool append; /* in append mode */ + bool read; + bool labeled; + char VolumeName[MAX_NAME_LENGTH]; + char MediaType[MAX_NAME_LENGTH]; +}; /* * Console ACL positions @@ -122,17 +148,18 @@ enum { Command_ACL, FileSet_ACL, Catalog_ACL, - Num_ACL /* keep last */ + Num_ACL /* keep last */ }; /* * Console Resource */ -struct CONRES { - RES hdr; - char *password; /* UA server password */ - int enable_ssl; /* Use SSL */ - alist *ACL_lists[Num_ACL]; /* pointers to ACLs */ +class CONRES { +public: + RES hdr; + char *password; /* UA server password */ + int enable_ssl; /* Use SSL */ + alist *ACL_lists[Num_ACL]; /* pointers to ACLs */ }; @@ -140,16 +167,17 @@ struct CONRES { * Catalog Resource * */ -struct CAT { - RES hdr; +class CAT { +public: + RES hdr; - int db_port; /* Port -- not yet implemented */ - char *db_address; /* host name for remote access */ - char *db_socket; /* Socket for local access */ + int db_port; /* Port -- not yet implemented */ + char *db_address; /* host name for remote access */ + char *db_socket; /* Socket for local access */ char *db_password; char *db_user; char *db_name; - int mult_db_connections; /* set if multiple connections wanted */ + int mult_db_connections; /* set if multiple connections wanted */ }; @@ -157,135 +185,148 @@ struct CAT { * Client Resource * */ -struct CLIENT { - RES hdr; - - int FDport; /* Where File daemon listens */ - int AutoPrune; /* Do automatic pruning? */ - utime_t FileRetention; /* file retention period in seconds */ - utime_t JobRetention; /* job retention period in seconds */ +class CLIENT { +public: + RES hdr; + + int FDport; /* Where File daemon listens */ + int AutoPrune; /* Do automatic pruning? */ + utime_t FileRetention; /* file retention period in seconds */ + utime_t JobRetention; /* job retention period in seconds */ char *address; char *password; - CAT *catalog; /* Catalog resource */ - uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ - uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ - int enable_ssl; /* Use SSL */ + CAT *catalog; /* Catalog resource */ + uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ + uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + int enable_ssl; /* Use SSL */ }; /* * Store Resource * */ -struct STORE { - RES hdr; +class STORE { +public: + RES hdr; - int SDport; /* port where Directors connect */ - int SDDport; /* data port for File daemon */ + int SDport; /* port where Directors connect */ + int SDDport; /* data port for File daemon */ char *address; char *password; char *media_type; - char *dev_name; - int autochanger; /* set if autochanger */ - uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ - uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ - int enable_ssl; /* Use SSL */ + alist *device; /* Device name(s) */ + int autochanger; /* set if autochanger */ + uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ + uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + int enable_ssl; /* Use SSL */ + + char *dev_name() const; + char *name() const; }; +inline char *STORE::dev_name() const +{ + DEVICE *dev = (DEVICE *)device->first(); + return dev->hdr.name; +} + +inline char *STORE::name() const { return hdr.name; } -#define MAX_STORE 2 /* Max storage directives in Job */ /* * Job Resource */ -struct JOB { - RES hdr; - - int JobType; /* job type (backup, verify, restore */ - int JobLevel; /* default backup/verify level */ - int Priority; /* Job priority */ - int RestoreJobId; /* What -- JobId to restore */ - char *RestoreWhere; /* Where on disk to restore -- directory */ - char *RestoreBootstrap; /* Bootstrap file */ - char *RunBeforeJob; /* Run program before Job */ - char *RunAfterJob; /* Run program after Job */ - char *RunAfterFailedJob; /* Run program after Job that errs */ - char *ClientRunBeforeJob; /* Run client program before Job */ - char *ClientRunAfterJob; /* Run client program after Job */ - char *WriteBootstrap; /* Where to write bootstrap Job updates */ - int replace; /* How (overwrite, ..) */ - utime_t MaxRunTime; /* max run time in seconds */ - utime_t MaxWaitTime; /* max blocking time in seconds */ - utime_t MaxStartDelay; /* max start delay in seconds */ - int PrefixLinks; /* prefix soft links with Where path */ - int PruneJobs; /* Force pruning of Jobs */ - int PruneFiles; /* Force pruning of Files */ - int PruneVolumes; /* Force pruning of Volumes */ - int SpoolAttributes; /* Set to spool attributes in SD */ - int spool_data; /* Set to spool data in SD */ - int rerun_failed_levels; /* Upgrade to rerun failed levels */ - uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ - int RescheduleOnError; /* Set to reschedule on error */ - int RescheduleTimes; /* Number of times to reschedule job */ - utime_t RescheduleInterval; /* Reschedule interval */ - utime_t JobRetention; /* job retention period in seconds */ - bool write_part_after_job; /* Set to write part after job in SD */ +class JOB { +public: + RES hdr; + + int JobType; /* job type (backup, verify, restore */ + int JobLevel; /* default backup/verify level */ + int Priority; /* Job priority */ + int RestoreJobId; /* What -- JobId to restore */ + char *RestoreWhere; /* Where on disk to restore -- directory */ + char *RestoreBootstrap; /* Bootstrap file */ + char *RunBeforeJob; /* Run program before Job */ + char *RunAfterJob; /* Run program after Job */ + char *RunAfterFailedJob; /* Run program after Job that errs */ + char *ClientRunBeforeJob; /* Run client program before Job */ + char *ClientRunAfterJob; /* Run client program after Job */ + char *WriteBootstrap; /* Where to write bootstrap Job updates */ + int replace; /* How (overwrite, ..) */ + utime_t MaxRunTime; /* max run time in seconds */ + utime_t MaxWaitTime; /* max blocking time in seconds */ + utime_t MaxStartDelay; /* max start delay in seconds */ + int PrefixLinks; /* prefix soft links with Where path */ + int PruneJobs; /* Force pruning of Jobs */ + int PruneFiles; /* Force pruning of Files */ + int PruneVolumes; /* Force pruning of Volumes */ + int SpoolAttributes; /* Set to spool attributes in SD */ + int spool_data; /* Set to spool data in SD */ + int rerun_failed_levels; /* Upgrade to rerun failed levels */ + uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ + int RescheduleOnError; /* Set to reschedule on error */ + int RescheduleTimes; /* Number of times to reschedule job */ + utime_t RescheduleInterval; /* Reschedule interval */ + utime_t JobRetention; /* job retention period in seconds */ + bool write_part_after_job; /* Set to write part after job in SD */ - MSGS *messages; /* How and where to send messages */ - SCHED *schedule; /* When -- Automatic schedule */ - CLIENT *client; /* Who to backup */ - FILESET *fileset; /* What to backup -- Fileset */ - alist *storage[MAX_STORE]; /* Where is device -- Storage daemon */ - POOL *pool; /* Where is media -- Media Pool */ - POOL *full_pool; /* Pool for Full backups */ - POOL *inc_pool; /* Pool for Incremental backups */ - POOL *dif_pool; /* Pool for Differental backups */ - JOB *verify_job; /* Job name to verify */ - JOB *jobdefs; /* Job defaults */ - uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ + MSGS *messages; /* How and where to send messages */ + SCHED *schedule; /* When -- Automatic schedule */ + CLIENT *client; /* Who to backup */ + FILESET *fileset; /* What to backup -- Fileset */ + alist *storage; /* Where is device -- Storage daemon */ + POOL *pool; /* Where is media -- Media Pool */ + POOL *full_pool; /* Pool for Full backups */ + POOL *inc_pool; /* Pool for Incremental backups */ + POOL *dif_pool; /* Pool for Differental backups */ + JOB *verify_job; /* Job name to verify */ + JOB *jobdefs; /* Job defaults */ + uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ }; -#undef MAX_FOPTS +#undef MAX_FOPTS #define MAX_FOPTS 34 /* File options structure */ struct FOPTS { - char opts[MAX_FOPTS]; /* options string */ - alist regex; /* regex string(s) */ - alist regexdir; /* regex string(s) for directories */ - alist regexfile; /* regex string(s) for files */ - alist wild; /* wild card strings */ - alist wilddir; /* wild card strings for directories */ - alist wildfile; /* wild card strings for files */ - alist base; /* list of base names */ - alist fstype; /* file system type limitation */ - char *reader; /* reader program */ - char *writer; /* writer program */ + char opts[MAX_FOPTS]; /* options string */ + alist regex; /* regex string(s) */ + alist regexdir; /* regex string(s) for directories */ + alist regexfile; /* regex string(s) for files */ + alist wild; /* wild card strings */ + alist wilddir; /* wild card strings for directories */ + alist wildfile; /* wild card strings for files */ + alist base; /* list of base names */ + alist fstype; /* file system type limitation */ + char *reader; /* reader program */ + char *writer; /* writer program */ }; /* This is either an include item or an exclude item */ struct INCEXE { - FOPTS *current_opts; /* points to current options structure */ - FOPTS **opts_list; /* options list */ - int num_opts; /* number of options items */ - alist name_list; /* filename list -- holds char * */ + FOPTS *current_opts; /* points to current options structure */ + FOPTS **opts_list; /* options list */ + int num_opts; /* number of options items */ + alist name_list; /* filename list -- holds char * */ }; /* * FileSet Resource * */ -struct FILESET { - RES hdr; +class FILESET { +public: + RES hdr; - bool new_include; /* Set if new include used */ - INCEXE **include_items; /* array of incexe structures */ - int num_includes; /* number in array */ + bool new_include; /* Set if new include used */ + INCEXE **include_items; /* array of incexe structures */ + int num_includes; /* number in array */ INCEXE **exclude_items; int num_excludes; - bool have_MD5; /* set if MD5 initialized */ - struct MD5Context md5c; /* MD5 of include/exclude */ - char MD5[30]; /* base 64 representation of MD5 */ + bool have_MD5; /* set if MD5 initialized */ + struct MD5Context md5c; /* MD5 of include/exclude */ + char MD5[30]; /* base 64 representation of MD5 */ int ignore_fs_changes; /* Don't force Full if FS changed */ }; @@ -294,8 +335,9 @@ struct FILESET { * Schedule Resource * */ -struct SCHED { - RES hdr; +class SCHED { +public: + RES hdr; RUN *run; }; @@ -303,45 +345,50 @@ struct SCHED { /* * Counter Resource */ -struct COUNTER { - RES hdr; - - int32_t MinValue; /* Minimum value */ - int32_t MaxValue; /* Maximum value */ - int32_t CurrentValue; /* Current value */ - COUNTER *WrapCounter; /* Wrap counter name */ - CAT *Catalog; /* Where to store */ - bool created; /* Created in DB */ +class COUNTER { +public: + RES hdr; + + int32_t MinValue; /* Minimum value */ + int32_t MaxValue; /* Maximum value */ + int32_t CurrentValue; /* Current value */ + COUNTER *WrapCounter; /* Wrap counter name */ + CAT *Catalog; /* Where to store */ + bool created; /* Created in DB */ }; /* * Pool Resource * */ -struct POOL { - RES hdr; - - char *pool_type; /* Pool type */ - char *label_format; /* Label format string */ - char *cleaning_prefix; /* Cleaning label prefix */ - 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 purge_oldest_volume; /* purge oldest volume */ - int recycle_oldest_volume; /* attempt to recycle oldest volume */ - int recycle_current_volume; /* attempt recycle of current volume */ - uint32_t max_volumes; /* max number of volumes */ - utime_t VolRetention; /* volume retention period in seconds */ - utime_t VolUseDuration; /* duration volume can be used */ - uint32_t MaxVolJobs; /* Maximum jobs on the Volume */ - uint32_t MaxVolFiles; /* Maximum files on the Volume */ - uint64_t MaxVolBytes; /* Maximum bytes on the Volume */ - int AutoPrune; /* default for pool auto prune */ - int Recycle; /* default for media recycle yes/no */ +class POOL { +public: + RES hdr; + + char *pool_type; /* Pool type */ + char *label_format; /* Label format string */ + char *cleaning_prefix; /* Cleaning label prefix */ + int LabelType; /* Bacula/ANSI/IBM label type */ + 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 purge_oldest_volume; /* purge oldest volume */ + int recycle_oldest_volume; /* attempt to recycle oldest volume */ + int recycle_current_volume; /* attempt recycle of current volume */ + uint32_t max_volumes; /* max number of volumes */ + utime_t VolRetention; /* volume retention period in seconds */ + utime_t VolUseDuration; /* duration volume can be used */ + uint32_t MaxVolJobs; /* Maximum jobs on the Volume */ + uint32_t MaxVolFiles; /* Maximum files on the Volume */ + uint64_t MaxVolBytes; /* Maximum bytes on the Volume */ + int AutoPrune; /* default for pool auto prune */ + int Recycle; /* default for media recycle yes/no */ }; + + /* Define the Union of all the above * resource structure definitions. */ @@ -350,40 +397,42 @@ union URES { CONRES res_con; CLIENT res_client; STORE res_store; - CAT res_cat; - JOB res_job; + CAT res_cat; + JOB res_job; FILESET res_fs; SCHED res_sch; POOL res_pool; MSGS res_msgs; COUNTER res_counter; - RES hdr; + DEVICE res_dev; + RES hdr; }; /* Run structure contained in Schedule Resource */ -struct RUN { - RUN *next; /* points to next run record */ - int level; /* level override */ - int Priority; /* priority override */ +class RUN { +public: + RUN *next; /* points to next run record */ + int level; /* level override */ + int Priority; /* priority override */ int job_type; - bool spool_data; /* Data spooling override */ - bool spool_data_set; /* Data spooling override given */ - bool write_part_after_job; /* Write part after job override */ + bool spool_data; /* Data spooling override */ + bool spool_data_set; /* Data spooling override given */ + bool write_part_after_job; /* Write part after job override */ bool write_part_after_job_set; /* Write part after job override given */ - POOL *pool; /* Pool override */ - POOL *full_pool; /* Pool override */ - POOL *inc_pool; /* Pool override */ - POOL *dif_pool; /* Pool override */ - STORE *storage; /* Storage override */ - MSGS *msgs; /* Messages override */ + POOL *pool; /* Pool override */ + POOL *full_pool; /* Pool override */ + POOL *inc_pool; /* Pool override */ + POOL *dif_pool; /* Pool override */ + STORE *storage; /* Storage override */ + MSGS *msgs; /* Messages override */ char *since; int level_no; - int minute; /* minute to run job */ - time_t last_run; /* last time run */ - time_t next_run; /* next time to run */ + int minute; /* minute to run job */ + time_t last_run; /* last time run */ + time_t next_run; /* next time to run */ char hour[nbytes_for_bits(24)]; /* bit set for each hour */ char mday[nbytes_for_bits(31)]; /* bit set for each day of month */ char month[nbytes_for_bits(12)]; /* bit set for each month */ diff --git a/bacula/src/dird/getmsg.c b/bacula/src/dird/getmsg.c index 6eba9894e9..79a6311722 100644 --- a/bacula/src/dird/getmsg.c +++ b/bacula/src/dird/getmsg.c @@ -21,7 +21,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -46,6 +46,9 @@ /* Forward referenced functions */ static char *find_msg_start(char *msg); +static char Job_status[] = "Status Job=%127s JobStatus=%d\n"; + + static char OK_msg[] = "1000 OK\n"; /* @@ -75,7 +78,7 @@ int bget_dirmsg(BSOCK *bs) for (;;) { n = bnet_recv(bs); - Dmsg2(120, "bget_dirmsg %d: %s\n", n, bs->msg); + Dmsg2(900, "bget_dirmsg %d: %s\n", n, bs->msg); if (is_bnet_stop(bs)) { return n; /* error or terminate */ @@ -102,15 +105,15 @@ int bget_dirmsg(BSOCK *bs) break; case BNET_STATUS: /* *****FIXME***** Implement more completely */ - bnet_fsend(bs, "Status OK\n"); + bnet_fsend(bs, "Status OK\n"); bnet_sig(bs, BNET_EOD); break; case BNET_BTIME: /* send Bacula time */ char ed1[50]; - bnet_fsend(bs, "btime %s\n", edit_uint64(get_current_btime(),ed1)); + bnet_fsend(bs, "btime %s\n", edit_uint64(get_current_btime(),ed1)); break; default: - Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen); + Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen); return n; } continue; @@ -128,18 +131,18 @@ int bget_dirmsg(BSOCK *bs) * Try to fulfill it. */ if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) { - Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); + Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); continue; } if (!(jcr=get_jcr_by_full_name(Job))) { - Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg); + Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg); continue; } - Dmsg1(200, "Getmsg got jcr 0x%x\n", jcr); + Dmsg1(900, "Getmsg got jcr 0x%x\n", jcr); /* Skip past "Jmsg Job=nnn" */ if (!(msg=find_msg_start(bs->msg))) { - Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); + Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); free_jcr(jcr); continue; } @@ -149,21 +152,21 @@ int bget_dirmsg(BSOCK *bs) * Jmsg Job=nnn type=nnn level=nnn Message-string */ if (bs->msg[0] == 'J') { /* Job message */ - if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d", + if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d", Job, &type, &level) != 3) { - Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); + Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); free_jcr(jcr); continue; } - Dmsg1(120, "Got msg: %s\n", bs->msg); + Dmsg1(900, "Got msg: %s\n", bs->msg); skip_spaces(&msg); skip_nonspaces(&msg); /* skip type=nnn */ skip_spaces(&msg); skip_nonspaces(&msg); /* skip level=nnn */ - if (*msg == ' ') { + if (*msg == ' ') { msg++; /* skip leading space */ } - Dmsg1(120, "Dispatch msg: %s", msg); + Dmsg1(900, "Dispatch msg: %s", msg); dispatch_message(jcr, type, level, msg); free_jcr(jcr); continue; @@ -173,25 +176,34 @@ int bget_dirmsg(BSOCK *bs) * CatReq Job=nn Catalog-Request-Message */ if (bs->msg[0] == 'C') { /* Catalog request */ - Dmsg2(120, "Catalog req jcr 0x%x: %s", jcr, bs->msg); + Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg); catalog_request(jcr, bs, msg); - Dmsg1(200, "Calling freejcr 0x%x\n", jcr); + Dmsg1(900, "Calling freejcr 0x%x\n", jcr); free_jcr(jcr); continue; } if (bs->msg[0] == 'U') { /* Catalog update */ - Dmsg2(120, "Catalog upd jcr 0x%x: %s", jcr, bs->msg); + Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg); catalog_update(jcr, bs, msg); - Dmsg1(200, "Calling freejcr 0x%x\n", jcr); + Dmsg1(900, "Calling freejcr 0x%x\n", jcr); free_jcr(jcr); continue; } if (bs->msg[0] == 'M') { /* Mount request */ - Dmsg1(120, "Mount req: %s", bs->msg); + Dmsg1(900, "Mount req: %s", bs->msg); mount_request(jcr, bs, msg); free_jcr(jcr); continue; } + if (bs->msg[0] == 'S') { /* Status change */ + int JobStatus; + char Job[MAX_NAME_LENGTH]; + if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) { + jcr->SDJobStatus = JobStatus; /* current status */ + free_jcr(jcr); + continue; + } + } return n; } } @@ -208,31 +220,32 @@ static char *find_msg_start(char *msg) } /* - * Get response from File daemon to a command we + * Get response from FD or SD to a command we * sent. Check that the response agrees with what we expect. * - * Returns: 0 on failure - * 1 on success + * Returns: false on failure + * true on success */ -int response(JCR *jcr, BSOCK *fd, char *resp, const char *cmd, e_prtmsg prtmsg) +bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg) { int n; - if (is_bnet_error(fd)) { - return 0; + if (is_bnet_error(bs)) { + return false; } - if ((n = bget_dirmsg(fd)) >= 0) { - Dmsg0(110, fd->msg); - if (strcmp(fd->msg, resp) == 0) { - return 1; + if ((n = bget_dirmsg(bs)) >= 0) { + Dmsg0(900, bs->msg); + if (strcmp(bs->msg, resp) == 0) { + return true; } + Dmsg1(900, "Bad response: ERR=%s", bs->msg); if (prtmsg == DISPLAY_ERROR) { - Jmsg(jcr, M_FATAL, 0, _("FD gave bad response to %s command: wanted %s got: %s\n"), - cmd, resp, fd->msg); + Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s got: %s\n"), + cmd, resp, bs->msg); } - return 0; + return false; } - Jmsg(jcr, M_FATAL, 0, _("Socket error from Filed on %s command: ERR=%s\n"), - cmd, bnet_strerror(fd)); - return 0; + Jmsg(jcr, M_FATAL, 0, _("Socket error on %s command: ERR=%s\n"), + cmd, bnet_strerror(bs)); + return false; } diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index 6f30607143..51f4ced8b8 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -323,7 +323,7 @@ void store_inc(LEX *lc, RES_ITEM *item, int index, int pass) } if (!inc_opts[0]) { - strcat(inc_opts, "0"); /* set no options */ + bstrncat(inc_opts, "0", sizeof(inc_opts)); /* set no options */ } inc_opts_len = strlen(inc_opts); diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index de88b1e914..1107ef425b 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -134,6 +134,15 @@ JobId_t run_job(JCR *jcr) Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n", jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel); + + if (!get_or_create_client_record(jcr)) { + goto bail_out; + } + + if (!jcr->fname) { + jcr->fname = get_pool_memory(PM_FNAME); + } + Dmsg0(200, "Add jrc to work queue\n"); /* Queue the job to be run */ @@ -343,7 +352,7 @@ int cancel_job(UAContext *ua, JCR *jcr) /* Cancel Storage daemon */ if (jcr->store_bsock) { - if (!ua->jcr->storage[0]) { + if (!ua->jcr->storage) { copy_storage(ua->jcr, jcr); } else { set_storage(ua->jcr, jcr->store); @@ -381,7 +390,7 @@ static void job_monitor_watchdog(watchdog_t *self) control_jcr = (JCR *)self->data; - Dmsg1(400, "job_monitor_watchdog %p called\n", self); + Dmsg1(800, "job_monitor_watchdog %p called\n", self); lock_jcr_chain(); @@ -389,7 +398,7 @@ static void job_monitor_watchdog(watchdog_t *self) bool cancel; if (jcr->JobId == 0) { - Dmsg2(400, "Skipping JCR %p (%s) with JobId 0\n", + Dmsg2(800, "Skipping JCR %p (%s) with JobId 0\n", jcr, jcr->Job); /* Keep reference counts correct */ free_locked_jcr(jcr); @@ -403,7 +412,7 @@ static void job_monitor_watchdog(watchdog_t *self) cancel |= job_check_maxruntime(control_jcr, jcr); if (cancel) { - Dmsg3(200, "Cancelling JCR %p jobid %d (%s)\n", + Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job); UAContext *ua = new_ua_context(jcr); @@ -411,7 +420,7 @@ static void job_monitor_watchdog(watchdog_t *self) cancel_job(ua, jcr); free_ua_context(ua); - Dmsg1(200, "Have cancelled JCR %p\n", jcr); + Dmsg1(800, "Have cancelled JCR %p\n", jcr); } /* Keep reference counts correct */ @@ -432,11 +441,11 @@ static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) return false; } if ((watchdog_time - jcr->start_time) < jcr->job->MaxWaitTime) { - Dmsg3(200, "Job %p (%s) with MaxWaitTime %d not expired\n", + Dmsg3(800, "Job %p (%s) with MaxWaitTime %d not expired\n", jcr, jcr->Job, jcr->job->MaxWaitTime); return false; } - Dmsg3(200, "Job %d (%s): MaxWaitTime of %d seconds exceeded, " + Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, " "checking status\n", jcr->JobId, jcr->Job, jcr->job->MaxWaitTime); switch (jcr->JobStatus) { @@ -454,16 +463,16 @@ static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) Dmsg0(200, "JCR blocked in #1\n"); break; case JS_Running: - Dmsg0(200, "JCR running, checking SD status\n"); + Dmsg0(800, "JCR running, checking SD status\n"); switch (jcr->SDJobStatus) { case JS_WaitMount: case JS_WaitMedia: case JS_WaitFD: cancel = true; - Dmsg0(200, "JCR blocked in #2\n"); + Dmsg0(800, "JCR blocked in #2\n"); break; default: - Dmsg0(200, "JCR not blocked in #2\n"); + Dmsg0(800, "JCR not blocked in #2\n"); break; } break; @@ -471,13 +480,13 @@ static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) case JS_ErrorTerminated: case JS_Canceled: case JS_FatalError: - Dmsg0(200, "JCR already dead in #3\n"); + Dmsg0(800, "JCR already dead in #3\n"); break; default: Jmsg1(jcr, M_ERROR, 0, _("Unhandled job status code %d\n"), jcr->JobStatus); } - Dmsg3(200, "MaxWaitTime result: %scancel JCR %p (%s)\n", + Dmsg3(800, "MaxWaitTime result: %scancel JCR %p (%s)\n", cancel ? "" : "do not ", jcr, jcr->job); return cancel; @@ -727,10 +736,8 @@ void dird_free_jcr(JCR *jcr) pthread_cond_destroy(&jcr->term_wait); } /* Delete lists setup to hold storage pointers */ - for (int i=0; istorage[i]) { - delete jcr->storage[i]; - } + if (jcr->storage) { + delete jcr->storage; } jcr->job_end_push.destroy(); Dmsg0(200, "End dird free_jcr\n"); @@ -745,6 +752,7 @@ void dird_free_jcr(JCR *jcr) */ void set_jcr_defaults(JCR *jcr, JOB *job) { + STORE *st; jcr->job = job; jcr->JobType = job->JobType; switch (jcr->JobType) { @@ -758,20 +766,17 @@ void set_jcr_defaults(JCR *jcr, JOB *job) } jcr->JobPriority = job->Priority; /* Copy storage definitions -- deleted in dir_free_jcr above */ - for (int i=0; i < MAX_STORE; i++) { - STORE *st; - if (job->storage[i]) { - if (jcr->storage[i]) { - delete jcr->storage[i]; - } - jcr->storage[i] = New(alist(10, not_owned_by_alist)); - foreach_alist(st, job->storage[i]) { - jcr->storage[i]->append(st); - } + if (job->storage) { + if (jcr->storage) { + delete jcr->storage; + } + jcr->storage = New(alist(10, not_owned_by_alist)); + foreach_alist(st, job->storage) { + jcr->storage->append(st); } } - if (jcr->storage[0]) { - jcr->store = (STORE *)jcr->storage[0]->first(); + if (jcr->storage) { + jcr->store = (STORE *)jcr->storage->first(); } jcr->client = job->client; if (!jcr->client_name) { @@ -821,28 +826,34 @@ void set_jcr_defaults(JCR *jcr, JOB *job) */ void copy_storage(JCR *new_jcr, JCR *old_jcr) { - for (int i=0; i < MAX_STORE; i++) { - if (old_jcr->storage[i]) { - STORE *st; - if (old_jcr->storage[i]) { - delete old_jcr->storage[i]; - } - new_jcr->storage[i] = New(alist(10, not_owned_by_alist)); - foreach_alist(st, old_jcr->storage[i]) { - new_jcr->storage[i]->append(st); - } + if (old_jcr->storage) { + STORE *st; + if (old_jcr->storage) { + delete old_jcr->storage; } - if (old_jcr->store) { - new_jcr->store = old_jcr->store; - } else if (new_jcr->storage[0]) { - new_jcr->store = (STORE *)new_jcr->storage[0]->first(); + new_jcr->storage = New(alist(10, not_owned_by_alist)); + foreach_alist(st, old_jcr->storage) { + new_jcr->storage->append(st); } } + if (old_jcr->store) { + new_jcr->store = old_jcr->store; + } else if (new_jcr->storage) { + new_jcr->store = (STORE *)new_jcr->storage->first(); + } } /* Set storage override */ void set_storage(JCR *jcr, STORE *store) { + STORE *storage; + jcr->store = store; - jcr->storage[0]->prepend(store); + foreach_alist(storage, jcr->storage) { + if (store == storage) { + return; + } + } + /* Store not in list, so add it */ + jcr->storage->prepend(store); } diff --git a/bacula/src/dird/jobq.c b/bacula/src/dird/jobq.c index 4ca44bc37a..eea66c004a 100755 --- a/bacula/src/dird/jobq.c +++ b/bacula/src/dird/jobq.c @@ -18,7 +18,7 @@ * */ /* - Copyright (C) 2003-2004 Kern Sibbald + Copyright (C) 2003-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -170,7 +170,7 @@ void *sched_wait(void *arg) JCR *jcr = ((wait_pkt *)arg)->jcr; jobq_t *jq = ((wait_pkt *)arg)->jq; - Dmsg0(300, "Enter sched_wait.\n"); + Dmsg0(2300, "Enter sched_wait.\n"); free(arg); time_t wtime = jcr->sched_time - time(NULL); set_jcr_job_status(jcr, JS_WaitStartTime); @@ -181,7 +181,7 @@ void *sched_wait(void *arg) } /* Check every 30 seconds if canceled */ while (wtime > 0) { - Dmsg2(300, "Waiting on sched time, jobid=%d secs=%d\n", jcr->JobId, wtime); + Dmsg2(2300, "Waiting on sched time, jobid=%d secs=%d\n", jcr->JobId, wtime); if (wtime > 30) { wtime = 30; } @@ -195,7 +195,7 @@ void *sched_wait(void *arg) jobq_add(jq, jcr); V(jcr->mutex); free_jcr(jcr); /* we are done with jcr */ - Dmsg0(300, "Exit sched_wait\n"); + Dmsg0(2300, "Exit sched_wait\n"); return NULL; } @@ -215,14 +215,14 @@ int jobq_add(jobq_t *jq, JCR *jcr) pthread_t id; wait_pkt *sched_pkt; - Dmsg3(300, "jobq_add jobid=%d jcr=0x%x use_count=%d\n", jcr->JobId, jcr, jcr->use_count); + Dmsg3(2300, "jobq_add jobid=%d jcr=0x%x use_count=%d\n", jcr->JobId, jcr, jcr->use_count); if (jq->valid != JOBQ_VALID) { Jmsg0(jcr, M_ERROR, 0, "Jobq_add queue not initialized.\n"); return EINVAL; } jcr->use_count++; /* mark jcr in use by us */ - Dmsg3(300, "jobq_add jobid=%d jcr=0x%x use_count=%d\n", jcr->JobId, jcr, jcr->use_count); + Dmsg3(2300, "jobq_add jobid=%d jcr=0x%x use_count=%d\n", jcr->JobId, jcr, jcr->use_count); if (!job_canceled(jcr) && wtime > 0) { set_thread_concurrency(jq->max_workers + 2); sched_pkt = (wait_pkt *)malloc(sizeof(wait_pkt)); @@ -253,15 +253,15 @@ int jobq_add(jobq_t *jq, JCR *jcr) if (job_canceled(jcr)) { /* Add job to ready queue so that it is canceled quickly */ jq->ready_jobs->prepend(item); - Dmsg1(300, "Prepended job=%d to ready queue\n", jcr->JobId); + Dmsg1(2300, "Prepended job=%d to ready queue\n", jcr->JobId); } else { /* Add this job to the wait queue in priority sorted order */ foreach_dlist(li, jq->waiting_jobs) { - Dmsg2(300, "waiting item jobid=%d priority=%d\n", + Dmsg2(2300, "waiting item jobid=%d priority=%d\n", li->jcr->JobId, li->jcr->JobPriority); if (li->jcr->JobPriority > jcr->JobPriority) { jq->waiting_jobs->insert_before(item, li); - Dmsg2(300, "insert_before jobid=%d before waiting job=%d\n", + Dmsg2(2300, "insert_before jobid=%d before waiting job=%d\n", li->jcr->JobId, jcr->JobId); inserted = true; break; @@ -270,7 +270,7 @@ int jobq_add(jobq_t *jq, JCR *jcr) /* If not jobs in wait queue, append it */ if (!inserted) { jq->waiting_jobs->append(item); - Dmsg1(300, "Appended item jobid=%d to waiting queue\n", jcr->JobId); + Dmsg1(2300, "Appended item jobid=%d to waiting queue\n", jcr->JobId); } } @@ -278,7 +278,7 @@ int jobq_add(jobq_t *jq, JCR *jcr) stat = start_server(jq); pthread_mutex_unlock(&jq->mutex); - Dmsg0(300, "Return jobq_add\n"); + Dmsg0(2300, "Return jobq_add\n"); return stat; } @@ -297,7 +297,7 @@ int jobq_remove(jobq_t *jq, JCR *jcr) bool found = false; jobq_item_t *item; - Dmsg2(300, "jobq_remove jobid=%d jcr=0x%x\n", jcr->JobId, jcr); + Dmsg2(2300, "jobq_remove jobid=%d jcr=0x%x\n", jcr->JobId, jcr); if (jq->valid != JOBQ_VALID) { return EINVAL; } @@ -316,19 +316,19 @@ int jobq_remove(jobq_t *jq, JCR *jcr) } if (!found) { pthread_mutex_unlock(&jq->mutex); - Dmsg2(300, "jobq_remove jobid=%d jcr=0x%x not in wait queue\n", jcr->JobId, jcr); + Dmsg2(2300, "jobq_remove jobid=%d jcr=0x%x not in wait queue\n", jcr->JobId, jcr); return EINVAL; } /* Move item to be the first on the list */ jq->waiting_jobs->remove(item); jq->ready_jobs->prepend(item); - Dmsg2(300, "jobq_remove jobid=%d jcr=0x%x moved to ready queue\n", jcr->JobId, jcr); + Dmsg2(2300, "jobq_remove jobid=%d jcr=0x%x moved to ready queue\n", jcr->JobId, jcr); stat = start_server(jq); pthread_mutex_unlock(&jq->mutex); - Dmsg0(300, "Return jobq_remove\n"); + Dmsg0(2300, "Return jobq_remove\n"); return stat; } @@ -343,14 +343,14 @@ static int start_server(jobq_t *jq) /* if any threads are idle, wake one */ if (jq->idle_workers > 0) { - Dmsg0(300, "Signal worker to wake up\n"); + Dmsg0(2300, "Signal worker to wake up\n"); if ((stat = pthread_cond_signal(&jq->work)) != 0) { berrno be; Jmsg1(NULL, M_ERROR, 0, "pthread_cond_signal: ERR=%s\n", be.strerror(stat)); return stat; } } else if (jq->num_workers < jq->max_workers) { - Dmsg0(300, "Create worker thread\n"); + Dmsg0(2300, "Create worker thread\n"); /* No idle threads so create a new one */ set_thread_concurrency(jq->max_workers + 1); if ((stat = pthread_create(&id, &jq->attr, jobq_server, (void *)jq)) != 0) { @@ -378,7 +378,7 @@ void *jobq_server(void *arg) bool timedout = false; bool work = true; - Dmsg0(300, "Start jobq_server\n"); + Dmsg0(2300, "Start jobq_server\n"); if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) { berrno be; Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_lock: ERR=%s\n", be.strerror(stat)); @@ -390,7 +390,7 @@ void *jobq_server(void *arg) struct timeval tv; struct timezone tz; - Dmsg0(300, "Top of for loop\n"); + Dmsg0(2300, "Top of for loop\n"); if (!work && !jq->quit) { gettimeofday(&tv, &tz); timeout.tv_nsec = 0; @@ -400,15 +400,15 @@ void *jobq_server(void *arg) /* * Wait 4 seconds, then if no more work, exit */ - Dmsg0(300, "pthread_cond_timedwait()\n"); + Dmsg0(2300, "pthread_cond_timedwait()\n"); stat = pthread_cond_timedwait(&jq->work, &jq->mutex, &timeout); if (stat == ETIMEDOUT) { - Dmsg0(300, "timedwait timedout.\n"); + Dmsg0(2300, "timedwait timedout.\n"); timedout = true; break; } else if (stat != 0) { - /* This shouldn't happen */ - Dmsg0(300, "This shouldn't happen\n"); + /* This shouldn't happen */ + Dmsg0(2300, "This shouldn't happen\n"); jq->num_workers--; pthread_mutex_unlock(&jq->mutex); return NULL; @@ -419,14 +419,14 @@ void *jobq_server(void *arg) /* * If anything is in the ready queue, run it */ - Dmsg0(300, "Checking ready queue.\n"); + Dmsg0(2300, "Checking ready queue.\n"); while (!jq->ready_jobs->empty() && !jq->quit) { JCR *jcr; je = (jobq_item_t *)jq->ready_jobs->first(); jcr = je->jcr; jq->ready_jobs->remove(je); if (!jq->ready_jobs->empty()) { - Dmsg0(300, "ready queue not empty start server\n"); + Dmsg0(2300, "ready queue not empty start server\n"); if (start_server(jq) != 0) { jq->num_workers--; pthread_mutex_unlock(&jq->mutex); @@ -434,7 +434,7 @@ void *jobq_server(void *arg) } } jq->running_jobs->append(je); - Dmsg1(300, "Took jobid=%d from ready and appended to run\n", jcr->JobId); + Dmsg1(2300, "Took jobid=%d from ready and appended to run\n", jcr->JobId); /* Release job queue lock */ if ((stat = pthread_mutex_unlock(&jq->mutex)) != 0) { @@ -445,10 +445,10 @@ void *jobq_server(void *arg) } /* Call user's routine here */ - Dmsg1(300, "Calling user engine for jobid=%d\n", jcr->JobId); + Dmsg1(2300, "Calling user engine for jobid=%d\n", jcr->JobId); jq->engine(je->jcr); - Dmsg1(300, "Back from user engine jobid=%d.\n", jcr->JobId); + Dmsg1(2300, "Back from user engine jobid=%d.\n", jcr->JobId); /* Reacquire job queue lock */ if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) { @@ -490,16 +490,16 @@ void *jobq_server(void *arg) */ jcr->reschedule_count++; jcr->sched_time = time(NULL) + jcr->job->RescheduleInterval; - Dmsg2(300, "Rescheduled Job %s to re-run in %d seconds.\n", jcr->Job, + Dmsg2(2300, "Rescheduled Job %s to re-run in %d seconds.\n", jcr->Job, (int)jcr->job->RescheduleInterval); bstrftime(dt, sizeof(dt), time(NULL)); - Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds.\n"), + Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds.\n"), jcr->Job, dt, (int)jcr->job->RescheduleInterval); dird_free_jcr(jcr); /* partial cleanup old stuff */ jcr->JobStatus = JS_WaitStartTime; jcr->SDJobStatus = 0; if (jcr->JobBytes == 0) { - Dmsg1(300, "Requeue job=%d\n", jcr->JobId); + Dmsg1(2300, "Requeue job=%d\n", jcr->JobId); jcr->JobStatus = JS_WaitStartTime; V(jq->mutex); jobq_add(jq, jcr); /* queue the job to run again */ @@ -520,19 +520,19 @@ void *jobq_server(void *arg) njcr->JobStatus = jcr->JobStatus; copy_storage(njcr, jcr); njcr->messages = jcr->messages; - Dmsg0(300, "Call to run new job\n"); + Dmsg0(2300, "Call to run new job\n"); V(jq->mutex); - run_job(njcr); /* This creates a "new" job */ - free_jcr(njcr); /* release "new" jcr */ + run_job(njcr); /* This creates a "new" job */ + free_jcr(njcr); /* release "new" jcr */ P(jq->mutex); - Dmsg0(300, "Back from running new job.\n"); + Dmsg0(2300, "Back from running new job.\n"); } /* Clean up and release old jcr */ if (jcr->db) { db_close_database(jcr, jcr->db); jcr->db = NULL; } - Dmsg2(300, "====== Termination job=%d use_cnt=%d\n", jcr->JobId, jcr->use_count); + Dmsg2(2300, "====== Termination job=%d use_cnt=%d\n", jcr->JobId, jcr->use_count); jcr->SDJobStatus = 0; V(jq->mutex); /* release internal lock */ free_jcr(jcr); @@ -543,17 +543,17 @@ void *jobq_server(void *arg) * If any job in the wait queue can be run, * move it to the ready queue */ - Dmsg0(300, "Done check ready, now check wait queue.\n"); + Dmsg0(2300, "Done check ready, now check wait queue.\n"); while (!jq->waiting_jobs->empty() && !jq->quit) { int Priority; je = (jobq_item_t *)jq->waiting_jobs->first(); jobq_item_t *re = (jobq_item_t *)jq->running_jobs->first(); if (re) { Priority = re->jcr->JobPriority; - Dmsg2(300, "JobId %d is running. Look for pri=%d\n", re->jcr->JobId, Priority); + Dmsg2(2300, "JobId %d is running. Look for pri=%d\n", re->jcr->JobId, Priority); } else { Priority = je->jcr->JobPriority; - Dmsg1(300, "No job running. Look for Job pri=%d\n", Priority); + Dmsg1(2300, "No job running. Look for Job pri=%d\n", Priority); } /* * Walk down the list of waiting jobs and attempt @@ -564,7 +564,7 @@ void *jobq_server(void *arg) JCR *jcr = je->jcr; bool skip_this_jcr = false; jobq_item_t *jn = (jobq_item_t *)jq->waiting_jobs->next(je); - Dmsg3(300, "Examining Job=%d JobPri=%d want Pri=%d\n", + Dmsg3(2300, "Examining Job=%d JobPri=%d want Pri=%d\n", jcr->JobId, jcr->JobPriority, Priority); /* Take only jobs of correct Priority */ if (jcr->JobPriority != Priority) { @@ -647,32 +647,32 @@ void *jobq_server(void *arg) jcr->acquired_resource_locks = true; jq->waiting_jobs->remove(je); jq->ready_jobs->append(je); - Dmsg1(300, "moved JobId=%d from wait to ready queue\n", je->jcr->JobId); + Dmsg1(2300, "moved JobId=%d from wait to ready queue\n", je->jcr->JobId); je = jn; /* Point to next waiting job */ } /* end for loop */ break; } /* end while loop */ - Dmsg0(300, "Done checking wait queue.\n"); + Dmsg0(2300, "Done checking wait queue.\n"); /* * If no more ready work and we are asked to quit, then do it */ if (jq->ready_jobs->empty() && jq->quit) { jq->num_workers--; if (jq->num_workers == 0) { - Dmsg0(300, "Wake up destroy routine\n"); + Dmsg0(2300, "Wake up destroy routine\n"); /* Wake up destroy routine if he is waiting */ pthread_cond_broadcast(&jq->work); } break; } - Dmsg0(300, "Check for work request\n"); + Dmsg0(2300, "Check for work request\n"); /* * If no more work requests, and we waited long enough, quit */ - Dmsg2(300, "timedout=%d read empty=%d\n", timedout, + Dmsg2(2300, "timedout=%d read empty=%d\n", timedout, jq->ready_jobs->empty()); if (jq->ready_jobs->empty() && timedout) { - Dmsg0(300, "break big loop\n"); + Dmsg0(2300, "break big loop\n"); jq->num_workers--; break; } @@ -701,7 +701,7 @@ void *jobq_server(void *arg) /* Recompute work as something may have changed in last 2 secs */ work = !jq->ready_jobs->empty() || !jq->waiting_jobs->empty(); } - Dmsg1(300, "Loop again. work=%d\n", work); + Dmsg1(2300, "Loop again. work=%d\n", work); } /* end of big for loop */ Dmsg0(200, "unlock mutex\n"); @@ -709,6 +709,6 @@ void *jobq_server(void *arg) berrno be; Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_unlock: ERR=%s\n", be.strerror(stat)); } - Dmsg0(300, "End jobq_server\n"); + Dmsg0(2300, "End jobq_server\n"); return NULL; } diff --git a/bacula/src/dird/mac.c b/bacula/src/dird/mac.c index c9853bdd68..e385204a95 100644 --- a/bacula/src/dird/mac.c +++ b/bacula/src/dird/mac.c @@ -16,7 +16,7 @@ */ /* - Copyright (C) 2004 Kern Sibbald and John Walker + Copyright (C) 2004-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -77,10 +77,6 @@ bool do_mac(JCR *jcr) break; } - if (!get_or_create_client_record(jcr)) { - goto bail_out; - } - if (!get_or_create_fileset_record(jcr, &fsr)) { goto bail_out; } @@ -93,15 +89,13 @@ bool do_mac(JCR *jcr) Dmsg1(100, "find last jobid for: %s\n", NPRT(Name)); if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) { Jmsg(jcr, M_FATAL, 0, _( - "Unable to find JobId of previous Job for this client.\n")); + "Unable to find JobId of previous Job for this client.\n")); goto bail_out; } input_jobid = jr.JobId; jcr->JobLevel = jr.JobLevel; Dmsg1(100, "Last jobid=%d\n", input_jobid); - jcr->fname = get_pool_memory(PM_FNAME); - /* * Get the Pool record -- first apply any level defined pools */ @@ -128,11 +122,11 @@ bool do_mac(JCR *jcr) while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */ /* Try to create the pool */ if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) { - Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, + Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, db_strerror(jcr->db)); goto bail_out; } else { - Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); + Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); } } jcr->PoolId = pr.PoolId; /****FIXME**** this can go away */ @@ -150,7 +144,6 @@ bool do_mac(JCR *jcr) goto bail_out; } - /* * Open a message channel connection with the Storage * daemon. This is to let him know that our client @@ -168,7 +161,7 @@ bool do_mac(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr)) { + if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) { goto bail_out; } /* @@ -247,18 +240,18 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, if (*fname == '|') { fname++; got_pipe = 1; - bpipe = open_bpipe(fname, 0, "w"); + bpipe = open_bpipe(fname, 0, "w"); fd = bpipe ? bpipe->wfd : NULL; } else { /* ***FIXME*** handle BASE */ - fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+"); + fd = fopen(fname, jcr->JobLevel==L_FULL?"w+":"a+"); } if (fd) { VolCount = db_get_job_volume_parameters(jcr, jcr->db, jcr->JobId, &VolParams); if (VolCount == 0) { - Jmsg(jcr, M_ERROR, 0, _("Could not get Job Volume Parameters to " - "update Bootstrap file. ERR=%s\n"), db_strerror(jcr->db)); + Jmsg(jcr, M_ERROR, 0, _("Could not get Job Volume Parameters to " + "update Bootstrap file. ERR=%s\n"), db_strerror(jcr->db)); if (jcr->SDJobFiles != 0) { set_jcr_job_status(jcr, JS_ErrorTerminated); } @@ -266,14 +259,15 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, } for (int i=0; i < VolCount; i++) { /* Write the record */ - fprintf(fd, "Volume=\"%s\"\n", VolParams[i].VolumeName); - fprintf(fd, "VolSessionId=%u\n", jcr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", jcr->VolSessionTime); - fprintf(fd, "VolFile=%u-%u\n", VolParams[i].StartFile, + fprintf(fd, "Volume=\"%s\"\n", VolParams[i].VolumeName); + fprintf(fd, "MediaType=\"%s\"\n", VolParams[i].MediaType); + fprintf(fd, "VolSessionId=%u\n", jcr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", jcr->VolSessionTime); + fprintf(fd, "VolFile=%u-%u\n", VolParams[i].StartFile, VolParams[i].EndFile); - fprintf(fd, "VolBlock=%u-%u\n", VolParams[i].StartBlock, + fprintf(fd, "VolBlock=%u-%u\n", VolParams[i].StartBlock, VolParams[i].EndBlock); - fprintf(fd, "FileIndex=%d-%d\n", VolParams[i].FirstIndex, + fprintf(fd, "FileIndex=%d-%d\n", VolParams[i].FirstIndex, VolParams[i].LastIndex); } if (VolParams) { @@ -286,8 +280,8 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, } } else { berrno be; - Jmsg(jcr, M_ERROR, 0, _("Could not open WriteBootstrap file:\n" - "%s: ERR=%s\n"), fname, be.strerror()); + Jmsg(jcr, M_ERROR, 0, _("Could not open WriteBootstrap file:\n" + "%s: ERR=%s\n"), fname, be.strerror()); set_jcr_job_status(jcr, JS_ErrorTerminated); } } @@ -296,14 +290,14 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, switch (jcr->JobStatus) { case JS_Terminated: if (jcr->Errors || jcr->SDErrors) { - term_msg = _("Backup OK -- with warnings"); + term_msg = _("Backup OK -- with warnings"); } else { - term_msg = _("Backup OK"); + term_msg = _("Backup OK"); } break; case JS_FatalError: case JS_ErrorTerminated: - term_msg = _("*** Backup Error ***"); + term_msg = _("*** Backup Error ***"); msg_type = M_ERROR; /* Generate error message */ if (jcr->store_bsock) { bnet_sig(jcr->store_bsock, BNET_TERMINATE); @@ -313,7 +307,7 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, } break; case JS_Canceled: - term_msg = _("Backup Canceled"); + term_msg = _("Backup Canceled"); if (jcr->store_bsock) { bnet_sig(jcr->store_bsock, BNET_TERMINATE); if (jcr->SD_msg_chan) { @@ -323,7 +317,7 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, break; default: term_msg = term_code; - sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus); + sprintf(term_code, _("Inappropriate term code: %c\n"), jcr->JobStatus); break; } bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime); @@ -342,7 +336,7 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, * normal exit should we complain about this error. */ if (jcr->JobStatus == JS_Terminated && jcr->jr.JobBytes) { - Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); + Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); } jcr->VolumeName[0] = 0; /* none */ } @@ -352,9 +346,9 @@ static void mac_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr, } else { compression = (double)100 - 100.0 * ((double)jcr->JobBytes / (double)jcr->ReadBytes); if (compression < 0.5) { - bstrncpy(compress, "None", sizeof(compress)); + bstrncpy(compress, "None", sizeof(compress)); } else { - bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression); + bsnprintf(compress, sizeof(compress), "%.1f %%", (float)compression); } } jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg)); diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index b34e29e4c0..f0d4cf8442 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -40,18 +40,23 @@ /* Commands sent to Storage daemon */ static char jobcmd[] = "JobId=%d job=%s job_name=%s client_name=%s " -"type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s SpoolData=%d WritePartAfterJob=%d"; -static char use_device[] = "use device=%s media_type=%s pool_name=%s pool_type=%s\n"; + "type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s " + "SpoolData=%d WritePartAfterJob=%d"; +static char use_device[] = "use device=%s media_type=%s pool_name=%s " + "pool_type=%s append=%d\n"; +static char query_device[] = "query device=%s"; /* Response from Storage daemon */ static char OKjob[] = "3000 OK Job SDid=%d SDtime=%d Authorization=%100s\n"; static char OK_device[] = "3000 OK use device\n"; +static char OK_query[] = "3001 OK query append=%d read=%d num_writers=%d " + "num_waiting=%d open=%d use_count=%d labeled=%d " + "media_type=%127s volume_name=%127s"; /* Storage Daemon requests */ static char Job_start[] = "3010 Job %127s start\n"; static char Job_end[] = "3099 Job %127s end JobStatus=%d JobFiles=%d JobBytes=%" lld "\n"; -static char Job_status[] = "3012 Job %127s jobstatus %d\n"; /* Forward referenced functions */ extern "C" void *msg_thread(void *arg); @@ -66,7 +71,10 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, BSOCK *sd; STORE *store; - store = (STORE *)jcr->storage[0]->first(); + if (jcr->store_bsock) { + return true; /* already connected */ + } + store = (STORE *)jcr->storage->first(); /* * Open message channel with the Storage daemon @@ -83,6 +91,47 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, jcr->store_bsock = sd; if (!authenticate_storage_daemon(jcr, store)) { + bnet_close(sd); + jcr->store_bsock = NULL; + return false; + } + return true; +} + +/* + * Here we ask the SD to send us the info for a + * particular device resource. + */ +bool update_device_res(JCR *jcr, DEVICE *dev) +{ + POOL_MEM device_name, media_type, volume_name; + int dev_open, dev_append, dev_read, dev_labeled; + BSOCK *sd; + if (!connect_to_storage_daemon(jcr, 5, 30, 0)) { + return false; + } + sd = jcr->store_bsock; + pm_strcpy(device_name, dev->hdr.name); + bash_spaces(device_name); + bnet_fsend(sd, query_device, device_name.c_str()); + if (bget_dirmsg(sd) > 0) { + Dmsg1(400, "msg); + if (sscanf(sd->msg, OK_query, &dev_append, &dev_read, + &dev->num_writers, &dev->num_waiting, &dev_open, + &dev->use_count, &dev_labeled, media_type.c_str(), + volume_name.c_str()) != 9) { + return false; + } + unbash_spaces(media_type); + unbash_spaces(volume_name); + bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType)); + bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName)); + dev->open = dev_open; + dev->append = dev_append; + dev->read = dev_read; + dev->labeled = dev_labeled; + dev->found = true; + } else { return false; } return true; @@ -91,14 +140,13 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, /* * Start a job with the Storage daemon */ -int start_storage_daemon_job(JCR *jcr) +int start_storage_daemon_job(JCR *jcr, alist *store, int append) { - int status = 0; + bool ok; STORE *storage; BSOCK *sd; char auth_key[100]; POOL_MEM device_name, pool_name, pool_type, media_type; - int i; sd = jcr->store_bsock; /* @@ -108,7 +156,7 @@ int start_storage_daemon_job(JCR *jcr) bash_spaces(jcr->client->hdr.name); bash_spaces(jcr->fileset->hdr.name); if (jcr->fileset->MD5[0] == 0) { - strcpy(jcr->fileset->MD5, "**Dummy**"); + bstrncpy(jcr->fileset->MD5, "**Dummy**", sizeof(jcr->fileset->MD5)); } bnet_fsend(sd, jobcmd, jcr->JobId, jcr->Job, jcr->job->hdr.name, jcr->client->hdr.name, jcr->JobType, jcr->JobLevel, @@ -135,34 +183,32 @@ int start_storage_daemon_job(JCR *jcr) return 0; } - /* - * Send use device = xxx media = yyy pool = zzz - */ - - for (i=0; i < MAX_STORE; i++) { - if (jcr->storage[i]) { - storage = (STORE *)jcr->storage[i]->first(); - pm_strcpy(device_name, storage->dev_name); - pm_strcpy(media_type, storage->media_type); - pm_strcpy(pool_type, jcr->pool->pool_type); - pm_strcpy(pool_name, jcr->pool->hdr.name); - bash_spaces(device_name); - bash_spaces(media_type); - bash_spaces(pool_type); - bash_spaces(pool_name); - bnet_fsend(sd, use_device, device_name.c_str(), - media_type.c_str(), pool_name.c_str(), pool_type.c_str()); - Dmsg1(110, ">stored: %s", sd->msg); - status = response(jcr, sd, OK_device, "Use Device", NO_DISPLAY); - if (!status) { - pm_strcpy(pool_type, sd->msg); /* save message */ - Jmsg(jcr, M_FATAL, 0, _("\n" - " Storage daemon didn't accept Device \"%s\" because:\n %s"), - device_name.c_str(), pool_type.c_str()/* sd->msg */); - } +// foreach_alist(storage, store) { + storage = (STORE *)store->first(); + pm_strcpy(device_name, storage->dev_name()); + pm_strcpy(media_type, storage->media_type); + pm_strcpy(pool_type, jcr->pool->pool_type); + pm_strcpy(pool_name, jcr->pool->hdr.name); + bash_spaces(device_name); + bash_spaces(media_type); + bash_spaces(pool_type); + bash_spaces(pool_name); + bnet_fsend(sd, use_device, device_name.c_str(), + media_type.c_str(), pool_name.c_str(), pool_type.c_str(), + append); + Dmsg1(200, ">stored: %s", sd->msg); + ok = response(jcr, sd, OK_device, "Use Device", NO_DISPLAY); + if (!ok) { + pm_strcpy(pool_type, sd->msg); /* save message */ + Jmsg(jcr, M_FATAL, 0, _("\n" + " Storage daemon didn't accept Device \"%s\" because:\n %s"), + device_name.c_str(), pool_type.c_str()/* sd->msg */); } +// } + if (ok) { + bnet_fsend(sd, "run"); } - return status; + return ok; } /* @@ -181,7 +227,8 @@ int start_storage_daemon_message_thread(JCR *jcr) V(jcr->mutex); Dmsg0(100, "Start SD msg_thread.\n"); if ((status=pthread_create(&thid, NULL, msg_thread, (void *)jcr)) != 0) { - Jmsg1(jcr, M_ABORT, 0, _("Cannot create message thread: %s\n"), strerror(status)); + berrno be; + Jmsg1(jcr, M_ABORT, 0, _("Cannot create message thread: %s\n"), be.strerror(status)); } Dmsg0(100, "SD msg_thread started.\n"); /* Wait for thread to start */ @@ -209,8 +256,7 @@ extern "C" void msg_thread_cleanup(void *arg) * Storage daemon). * Note, we are running in a separate thread. */ -extern "C" -void *msg_thread(void *arg) +extern "C" void *msg_thread(void *arg) { JCR *jcr = (JCR *)arg; BSOCK *sd; @@ -240,10 +286,6 @@ void *msg_thread(void *arg) jcr->SDJobBytes = JobBytes; break; } - if (sscanf(sd->msg, Job_status, &Job, &JobStatus) == 2) { - jcr->SDJobStatus = JobStatus; /* current status */ - continue; - } } if (is_bnet_error(sd)) { jcr->SDJobStatus = JS_ErrorTerminated; @@ -279,3 +321,54 @@ void wait_for_storage_daemon_termination(JCR *jcr) V(jcr->mutex); set_jcr_job_status(jcr, JS_Terminated); } + + +#define MAX_TRIES 30 +#define WAIT_TIME 2 +extern "C" void *device_thread(void *arg) +{ + int i; + JCR *jcr; + DEVICE *dev; + + + pthread_detach(pthread_self()); + jcr = new_control_jcr("*DeviceInit*", JT_SYSTEM); + for (i=0; i < MAX_TRIES; i++) { + if (!connect_to_storage_daemon(jcr, 10, 30, 1)) { + Dmsg0(000, "Failed connecting to SD.\n"); + continue; + } + LockRes(); + foreach_res(dev, R_DEVICE) { + if (!update_device_res(jcr, dev)) { + Dmsg1(900, "Error updating device=%s\n", dev->hdr.name); + } else { + Dmsg1(900, "Updated Device=%s\n", dev->hdr.name); + } + } + UnlockRes(); + bnet_close(jcr->store_bsock); + jcr->store_bsock = NULL; + break; + + } + free_jcr(jcr); + return NULL; +} + +/* + * Start a thread to handle getting Device resource information + * from SD. This is called once at startup of the Director. + */ +void init_device_resources() +{ + int status; + pthread_t thid; + + Dmsg0(100, "Start Device thread.\n"); + if ((status=pthread_create(&thid, NULL, device_thread, NULL)) != 0) { + berrno be; + Jmsg1(NULL, M_ABORT, 0, _("Cannot create message thread: %s\n"), be.strerror(status)); + } +} diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 81ae6d5c0b..17658c3eab 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -79,7 +79,7 @@ enum e_prtmsg { DISPLAY_ERROR, NO_DISPLAY }; -extern int response(JCR *jcr, BSOCK *fd, char *resp, const char *cmd, e_prtmsg prtmsg); +extern bool response(JCR *jcr, BSOCK *fd, char *resp, const char *cmd, e_prtmsg prtmsg); /* job.c */ extern void set_jcr_defaults(JCR *jcr, JOB *job); @@ -99,7 +99,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf); /* msgchan.c */ extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval, int max_retry_time, int verbose); -extern int start_storage_daemon_job(JCR *jcr); +extern int start_storage_daemon_job(JCR *jcr, alist *store, int append); extern int start_storage_daemon_message_thread(JCR *jcr); extern int bget_dirmsg(BSOCK *bs); extern void wait_for_storage_daemon_termination(JCR *jcr); diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index d8a894bf24..ef82f94dba 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -19,7 +19,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -67,11 +67,6 @@ int do_restore(JCR *jcr) BSOCK *fd; JOB_DBR rjr; /* restore job record */ - if (!get_or_create_client_record(jcr)) { - restore_cleanup(jcr, JS_ErrorTerminated); - return 0; - } - memset(&rjr, 0, sizeof(rjr)); jcr->jr.JobLevel = L_FULL; /* Full restore */ if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { @@ -80,7 +75,6 @@ int do_restore(JCR *jcr) return 0; } Dmsg0(20, "Updated job start record\n"); - jcr->fname = (char *) get_pool_memory(PM_FNAME); Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId); @@ -99,7 +93,7 @@ int do_restore(JCR *jcr) rjr.JobId = jcr->job->RestoreJobId; /* specified by Job Resource */ } if (!db_get_job_record(jcr, jcr->db, &rjr)) { - Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId, + Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId, db_strerror(jcr->db)); restore_cleanup(jcr, JS_ErrorTerminated); return 0; @@ -111,7 +105,7 @@ int do_restore(JCR *jcr) jcr->VolumeName[0] = 0; if (!db_get_job_volume_names(jcr, jcr->db, rjr.JobId, &jcr->VolumeName) || jcr->VolumeName[0] == 0) { - Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume names for restore Job %d. %s"), + Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume names for restore Job %d. %s"), rjr.JobId, db_strerror(jcr->db)); restore_cleanup(jcr, JS_ErrorTerminated); return 0; @@ -141,7 +135,7 @@ int do_restore(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr)) { + if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) { restore_cleanup(jcr, JS_ErrorTerminated); return 0; } @@ -281,9 +275,9 @@ static void restore_cleanup(JCR *jcr, int TermCode) switch (TermCode) { case JS_Terminated: if (jcr->ExpectedFiles > jcr->jr.JobFiles) { - term_msg = _("Restore OK -- warning file count mismatch"); + term_msg = _("Restore OK -- warning file count mismatch"); } else { - term_msg = _("Restore OK"); + term_msg = _("Restore OK"); } break; case JS_FatalError: diff --git a/bacula/src/dird/scheduler.c b/bacula/src/dird/scheduler.c index 3cbcee5000..edd9afe853 100644 --- a/bacula/src/dird/scheduler.c +++ b/bacula/src/dird/scheduler.c @@ -206,7 +206,7 @@ static void find_runs() /* Items corresponding to above at the next hour */ int nh_hour, nh_mday, nh_wday, nh_month, nh_wom, nh_woy, nh_year; - Dmsg0(200, "enter find_runs()\n"); + Dmsg0(1200, "enter find_runs()\n"); /* compute values for time now */ @@ -242,7 +242,7 @@ static void find_runs() if (sched == NULL) { /* scheduled? */ continue; /* no, skip this job */ } - Dmsg1(200, "Got job: %s\n", job->hdr.name); + Dmsg1(1200, "Got job: %s\n", job->hdr.name); for (run=sched->run; run; run=run->next) { bool run_now, run_nh; /* @@ -285,7 +285,7 @@ static void find_runs() bit_is_set(nh_wom, run->wom) && bit_is_set(nh_woy, run->woy); - Dmsg2(200, "run_now=%d run_nh=%d\n", run_now, run_nh); + Dmsg2(1200, "run_now=%d run_nh=%d\n", run_now, run_nh); /* find time (time_t) job is to be run */ localtime_r(&now, &tm); /* reset tm structure */ @@ -308,7 +308,7 @@ static void find_runs() } } UnlockRes(); - Dmsg0(200, "Leave find_runs()\n"); + Dmsg0(1200, "Leave find_runs()\n"); } static void add_job(JOB *job, RUN *run, time_t now, time_t runtime) diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index 99708e41ae..98432c1c57 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -36,7 +36,7 @@ const char *list_pool = "SELECT * FROM Pool WHERE PoolId=%u"; /* For ua_dotcmds.c */ const char *client_backups = "SELECT DISTINCT Job.JobId,Client.Name as Client,Level,StartTime," -"JobFiles,JobBytes,VolumeName" +"JobFiles,JobBytes,VolumeName,MediaType" " FROM Client,Job,JobMedia,Media" " WHERE Client.Name='%s'" " AND Client.ClientId=Job.ClientId" diff --git a/bacula/src/dird/ua_acl.c b/bacula/src/dird/ua_acl.c index 2cd63618bc..dcfc0e468a 100644 --- a/bacula/src/dird/ua_acl.c +++ b/bacula/src/dird/ua_acl.c @@ -8,7 +8,7 @@ */ /* - Copyright (C) 2004 Kern Sibbald and John Walker + Copyright (C) 2004-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -45,7 +45,7 @@ bool acl_access_ok(UAContext *ua, int acl, char *item, int len) /* If no console resource => default console and all is permitted */ if (!ua->cons) { - Dmsg0(400, "Root cons access OK.\n"); + Dmsg0(1400, "Root cons access OK.\n"); return true; /* No cons resource -> root console OK for everything */ } @@ -62,7 +62,7 @@ bool acl_access_ok(UAContext *ua, int acl, char *item, int len) /* Search list for item */ for (int i=0; isize(); i++) { if (strcasecmp(item, (char *)list->get(i)) == 0) { - Dmsg3(400, "Found %s in %d %s\n", item, acl, (char *)list->get(i)); + Dmsg3(1400, "ACL found %s in %d %s\n", item, acl, (char *)list->get(i)); return true; } } diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 3a5b0f03fb..b3c4279b28 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -149,7 +149,7 @@ int do_a_command(UAContext *ua, const char *cmd) stat = 1; - Dmsg1(200, "Command: %s\n", ua->UA_sock->msg); + Dmsg1(900, "Command: %s\n", ua->UA_sock->msg); if (ua->argc == 0) { return 1; } @@ -186,6 +186,7 @@ void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr) mr->MaxVolJobs = pr->MaxVolJobs; mr->MaxVolFiles = pr->MaxVolFiles; mr->MaxVolBytes = pr->MaxVolBytes; + mr->LabelType = pr->LabelType; } @@ -224,7 +225,7 @@ static int add_cmd(UAContext *ua, const char *cmd) while (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) { bsendmsg(ua, _("Pool already has maximum volumes = %d\n"), pr.MaxVols); for (;;) { - if (!get_pint(ua, _("Enter new maximum (zero for unlimited): "))) { + if (!get_pint(ua, _("Enter new maximum (zero for unlimited): "))) { return 1; } pr.MaxVols = ua->pint32_val; @@ -251,7 +252,7 @@ static int add_cmd(UAContext *ua, const char *cmd) } num = ua->pint32_val; if (num < 0 || num > max) { - bsendmsg(ua, _("The number must be between 0 and %d\n"), max); + bsendmsg(ua, _("The number must be between 0 and %d\n"), max); continue; } break; @@ -281,15 +282,15 @@ getVolName: bstrncpy(name, ua->cmd, sizeof(name)); if (num > 0) { - strcat(name, "%04d"); + bstrncat(name, "%04d", sizeof(name)); for (;;) { - if (!get_pint(ua, _("Enter the starting number: "))) { + if (!get_pint(ua, _("Enter the starting number: "))) { return 1; } startnum = ua->pint32_val; if (startnum < 1) { - bsendmsg(ua, _("Start number must be greater than zero.\n")); + bsendmsg(ua, _("Start number must be greater than zero.\n")); continue; } break; @@ -317,7 +318,7 @@ getVolName: mr.InChanger = InChanger; Dmsg1(200, "Create Volume %s\n", mr.VolumeName); if (!db_create_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); return 1; } if (i == startnum) { @@ -381,7 +382,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) } JobId = str_to_int64(ua->argv[i]); if (!(jcr=get_jcr_by_id(JobId))) { - bsendmsg(ua, _("JobId %d is not running.\n"), JobId); + bsendmsg(ua, _("JobId %d is not running.\n"), JobId); return 1; } break; @@ -390,7 +391,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) break; } if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) { - bsendmsg(ua, _("Job %s is not running.\n"), ua->argv[i]); + bsendmsg(ua, _("Job %s is not running.\n"), ua->argv[i]); return 1; } break; @@ -400,6 +401,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) * throw up a list and ask the user to select one. */ if (!jcr) { + char buf[1000]; /* Count Jobs running */ lock_jcr_chain(); foreach_jcr(jcr) { @@ -413,7 +415,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) unlock_jcr_chain(); if (njobs == 0) { - bsendmsg(ua, _("No Jobs running.\n")); + bsendmsg(ua, _("No Jobs running.\n")); return 1; } start_prompt(ua, _("Select Job:\n")); @@ -423,23 +425,25 @@ static int cancel_cmd(UAContext *ua, const char *cmd) free_locked_jcr(jcr); continue; } - add_prompt(ua, jcr->Job); + bsnprintf(buf, sizeof(buf), "JobId=%d Job=%s", jcr->JobId, jcr->Job); + add_prompt(ua, buf); free_locked_jcr(jcr); } unlock_jcr_chain(); - if (do_prompt(ua, _("Job"), _("Choose Job to cancel"), JobName, sizeof(JobName)) < 0) { + if (do_prompt(ua, _("Job"), _("Choose Job to cancel"), buf, sizeof(buf)) < 0) { return 1; } if (njobs == 1) { - if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) { + if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) { return 1; } } /* NOTE! This increments the ref_count */ + sscanf(buf, "JobId=%d Job=%127s", &njobs, JobName); jcr = get_jcr_by_full_name(JobName); if (!jcr) { - bsendmsg(ua, _("Job %s not found.\n"), JobName); + bsendmsg(ua, _("Job %s not found.\n"), JobName); return 1; } } @@ -459,7 +463,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd) */ static void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op) { - strcpy(pr->PoolType, pool->pool_type); + bstrncpy(pr->PoolType, pool->pool_type, sizeof(pr->PoolType)); if (op == POOL_OP_CREATE) { pr->MaxVols = pool->max_volumes; pr->NumVols = 0; @@ -471,6 +475,7 @@ static void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op) pr->MaxVols = pr->NumVols; } } + pr->LabelType = pool->LabelType; pr->UseOnce = pool->use_volume_once; pr->UseCatalog = pool->use_catalog; pr->AcceptAnyVolume = pool->accept_any_volume; @@ -483,9 +488,9 @@ static void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op) pr->AutoPrune = pool->AutoPrune; pr->Recycle = pool->Recycle; if (pool->label_format) { - strcpy(pr->LabelFormat, pool->label_format); + bstrncpy(pr->LabelFormat, pool->label_format, sizeof(pr->LabelFormat)); } else { - strcpy(pr->LabelFormat, "*"); /* none */ + bstrncpy(pr->LabelFormat, "*", sizeof(pr->LabelFormat)); /* none */ } } @@ -504,7 +509,7 @@ int create_pool(JCR *jcr, B_DB *db, POOL *pool, e_pool_op op) memset(&pr, 0, sizeof(POOL_DBR)); - strcpy(pr.Name, pool->hdr.name); + bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name)); if (db_get_pool_record(jcr, db, &pr)) { /* Pool Exists */ @@ -545,7 +550,7 @@ static int create_cmd(UAContext *ua, const char *cmd) switch (create_pool(ua->jcr, ua->db, pool, POOL_OP_CREATE)) { case 0: bsendmsg(ua, _("Error: Pool %s already exists.\n" - "Use update to change it.\n"), pool->hdr.name); + "Use update to change it.\n"), pool->hdr.name); break; case -1: @@ -571,7 +576,7 @@ static int python_cmd(UAContext *ua, const char *cmd) if (strcasecmp(ua->argk[1], _("restart")) == 0) { term_python_interpreter(); init_python_interpreter(director->hdr.name, director->scripts_directory ? - director->scripts_directory : "."); + director->scripts_directory : "."); bsendmsg(ua, _("Python interpreter restarted.\n")); } else { bsendmsg(ua, _("Nothing done.\n")); @@ -702,9 +707,9 @@ static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr) Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%u", mr->VolStatus, mr->MediaId); if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } else { - bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus); + bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus); } } free_pool_memory(query); @@ -817,7 +822,7 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) bsendmsg(ua, "%s", db_strerror(ua->db)); } else { bsendmsg(ua, _("New Recycle flag is: %s\n"), - mr->Recycle==1?_("yes"):_("no")); + mr->Recycle==1?_("yes"):_("no")); } free_pool_memory(query); } @@ -846,11 +851,11 @@ static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *o bsendmsg(ua, _("New Pool is: %s\n"), pr.Name); opr->NumVols--; if (!db_update_pool_record(ua->jcr, ua->db, opr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } pr.NumVols++; if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } db_make_inchanger_unique(ua->jcr, ua->db, mr); } @@ -963,7 +968,7 @@ static int update_volume(UAContext *ua) memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); break; } update_vol_pool(ua, ua->argv[j], &mr, &pr); @@ -1002,60 +1007,60 @@ static int update_volume(UAContext *ua) switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) { case 0: /* Volume Status */ /* Modify Volume Status */ - bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus); - start_prompt(ua, _("Possible Values are:\n")); - add_prompt(ua, "Append"); /* Better not translate these as */ - add_prompt(ua, "Archive"); /* They are known in the database code */ - add_prompt(ua, "Disabled"); - add_prompt(ua, "Full"); - add_prompt(ua, "Used"); - add_prompt(ua, "Cleaning"); - if (strcmp(mr.VolStatus, "Purged") == 0) { - add_prompt(ua, "Recycle"); + bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus); + start_prompt(ua, _("Possible Values are:\n")); + add_prompt(ua, "Append"); /* Better not translate these as */ + add_prompt(ua, "Archive"); /* They are known in the database code */ + add_prompt(ua, "Disabled"); + add_prompt(ua, "Full"); + add_prompt(ua, "Used"); + add_prompt(ua, "Cleaning"); + 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, sizeof(mr.VolStatus)) < 0) { + add_prompt(ua, "Read-Only"); + if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) { return 1; } update_volstatus(ua, ua->cmd, &mr); break; case 1: /* Retention */ - bsendmsg(ua, _("Current retention period is: %s\n"), + bsendmsg(ua, _("Current retention period is: %s\n"), edit_utime(mr.VolRetention, ed1, sizeof(ed1))); - if (!get_cmd(ua, _("Enter Volume Retention period: "))) { + if (!get_cmd(ua, _("Enter Volume Retention period: "))) { return 0; } update_volretention(ua, ua->cmd, &mr); break; case 2: /* Use Duration */ - bsendmsg(ua, _("Current use duration is: %s\n"), + bsendmsg(ua, _("Current use duration is: %s\n"), edit_utime(mr.VolUseDuration, ed1, sizeof(ed1))); - if (!get_cmd(ua, _("Enter Volume Use Duration: "))) { + if (!get_cmd(ua, _("Enter Volume Use Duration: "))) { return 0; } update_voluseduration(ua, ua->cmd, &mr); break; case 3: /* Max Jobs */ - bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs); - if (!get_pint(ua, _("Enter new Maximum Jobs: "))) { + bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs); + if (!get_pint(ua, _("Enter new Maximum Jobs: "))) { return 0; } update_volmaxjobs(ua, ua->cmd, &mr); break; case 4: /* Max Files */ - bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles); - if (!get_pint(ua, _("Enter new Maximum Files: "))) { + bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles); + if (!get_pint(ua, _("Enter new Maximum Files: "))) { return 0; } update_volmaxfiles(ua, ua->cmd, &mr); break; case 5: /* Max Bytes */ - bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1)); - if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) { + bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1)); + if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) { return 0; } update_volmaxbytes(ua, ua->cmd, &mr); @@ -1063,9 +1068,9 @@ static int update_volume(UAContext *ua) case 6: /* Recycle */ - bsendmsg(ua, _("Current recycle flag is: %s\n"), - mr.Recycle==1?_("yes"):_("no")); - if (!get_yesno(ua, _("Enter new Recycle status: "))) { + bsendmsg(ua, _("Current recycle flag is: %s\n"), + mr.Recycle==1?_("yes"):_("no")); + if (!get_yesno(ua, _("Enter new Recycle status: "))) { return 0; } update_volrecycle(ua, ua->cmd, &mr); @@ -1077,16 +1082,16 @@ static int update_volume(UAContext *ua) memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); return 0; } - bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot); - if (!get_pint(ua, _("Enter new Slot: "))) { + bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot); + if (!get_pint(ua, _("Enter new Slot: "))) { return 0; } Slot = ua->pint32_val; if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) { - bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), + bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), pr.MaxVols); break; } @@ -1096,15 +1101,15 @@ static int update_volume(UAContext *ua) * so that any Slot is handled correctly. */ if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); } else { - bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot); + bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot); } break; case 8: /* InChanger */ - bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); - if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { + bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); + if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { return 0; } mr.InChanger = ua->pint32_val; @@ -1113,35 +1118,35 @@ static int update_volume(UAContext *ua) * so that any Slot is handled correctly. */ if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); } else { - bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger); + bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger); } break; case 9: /* Volume Files */ int32_t VolFiles; - bsendmsg(ua, _("Warning changing Volume Files can result\n" - "in loss of data on your Volume\n\n")); - bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles); - if (!get_pint(ua, _("Enter new number of Files for Volume: "))) { + bsendmsg(ua, _("Warning changing Volume Files can result\n" + "in loss of data on your Volume\n\n")); + bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles); + if (!get_pint(ua, _("Enter new number of Files for Volume: "))) { return 0; } VolFiles = ua->pint32_val; if (VolFiles != (int)(mr.VolFiles + 1)) { - bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n")); - if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) { + bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n")); + if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) { break; } } query = get_pool_memory(PM_MESSAGE); - Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%u", + Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%u", VolFiles, mr.MediaId); if (!db_sql_query(ua->db, query, NULL, NULL)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } else { - bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles); + bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles); } free_pool_memory(query); break; @@ -1150,11 +1155,11 @@ static int update_volume(UAContext *ua) memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); return 0; } - bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name); - if (!get_cmd(ua, _("Enter new Pool name: "))) { + bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name); + if (!get_cmd(ua, _("Enter new Pool name: "))) { return 0; } update_vol_pool(ua, ua->cmd, &mr, &pr); @@ -1167,7 +1172,7 @@ static int update_volume(UAContext *ua) update_all_vols_from_pool(ua); return 1; default: /* Done or error */ - bsendmsg(ua, "Selection done.\n"); + bsendmsg(ua, "Selection done.\n"); return 1; } } @@ -1190,7 +1195,7 @@ static int update_pool(UAContext *ua) } memset(&pr, 0, sizeof(pr)); - strcpy(pr.Name, pool->hdr.name); + bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name)); if (!get_pool_dbr(ua, &pr)) { return 0; } @@ -1295,7 +1300,7 @@ static void do_all_setdebug(UAContext *ua, int level, int trace_flag) } if (!found) { unique_store[i++] = store; - Dmsg2(140, "Stuffing: %s:%d\n", store->address, store->SDport); + Dmsg2(140, "Stuffing: %s:%d\n", store->address, store->SDport); } } UnlockRes(); @@ -1329,7 +1334,7 @@ static void do_all_setdebug(UAContext *ua, int level, int trace_flag) } if (!found) { unique_client[i++] = client; - Dmsg2(140, "Stuffing: %s:%d\n", client->address, client->FDport); + Dmsg2(140, "Stuffing: %s:%d\n", client->address, client->FDport); } } UnlockRes(); @@ -1385,13 +1390,13 @@ static int setdebug_cmd(UAContext *ua, const char *cmd) return 1; } if (strcasecmp(ua->argk[i], _("dir")) == 0 || - strcasecmp(ua->argk[i], _("director")) == 0) { + strcasecmp(ua->argk[i], _("director")) == 0) { debug_level = level; set_trace(trace_flag); return 1; } if (strcasecmp(ua->argk[i], _("client")) == 0 || - strcasecmp(ua->argk[i], _("fd")) == 0) { + strcasecmp(ua->argk[i], _("fd")) == 0) { client = NULL; if (ua->argv[i]) { client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]); @@ -1408,8 +1413,8 @@ static int setdebug_cmd(UAContext *ua, const char *cmd) } if (strcasecmp(ua->argk[i], _("store")) == 0 || - strcasecmp(ua->argk[i], _("storage")) == 0 || - strcasecmp(ua->argk[i], _("sd")) == 0) { + strcasecmp(ua->argk[i], _("storage")) == 0 || + strcasecmp(ua->argk[i], _("sd")) == 0) { store = NULL; if (ua->argv[i]) { store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]); @@ -1515,7 +1520,7 @@ static int estimate_cmd(UAContext *ua, const char *cmd) jcr->JobLevel = L_FULL; for (int i=1; iargc; i++) { if (strcasecmp(ua->argk[i], _("client")) == 0 || - strcasecmp(ua->argk[i], _("fd")) == 0) { + strcasecmp(ua->argk[i], _("fd")) == 0) { if (ua->argv[i]) { client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]); continue; @@ -1539,7 +1544,7 @@ static int estimate_cmd(UAContext *ua, const char *cmd) } if (strcasecmp(ua->argk[i], _("level")) == 0) { if (!get_level_from_name(ua->jcr, ua->argv[i])) { - bsendmsg(ua, _("Level %s not valid.\n"), ua->argv[i]); + bsendmsg(ua, _("Level %s not valid.\n"), ua->argv[i]); } continue; } @@ -1552,7 +1557,7 @@ static int estimate_cmd(UAContext *ua, const char *cmd) if (!job) { job = (JOB *)GetResWithName(R_JOB, ua->argk[1]); if (!job) { - bsendmsg(ua, _("No job specified.\n")); + bsendmsg(ua, _("No job specified.\n")); return 1; } } @@ -1725,26 +1730,26 @@ static void delete_job(UAContext *ua) s = bstrdup(ua->argv[i]); tok = s; /* - * We could use strtok() here. But we're not going to, because: + * We could use strtok() here. But we're not going to, because: * (a) strtok() is deprecated, having been replaced by strsep(); * (b) strtok() is broken in significant ways. - * we could use strsep() instead, but it's not universally available. + * we could use strsep() instead, but it's not universally available. * so we grow our own using strchr(). */ - sep = strchr(tok, ','); + sep = strchr(tok, ','); while (sep != NULL) { - *sep = '\0'; - if (strchr(tok, '-')) { + *sep = '\0'; + if (strchr(tok, '-')) { delete_job_id_range(ua, tok); } else { JobId = str_to_int64(tok); do_job_delete(ua, JobId); } tok = ++sep; - sep = strchr(tok, ','); + sep = strchr(tok, ','); } /* pick up the last token */ - if (strchr(tok, '-')) { + if (strchr(tok, '-')) { delete_job_id_range(ua, tok); } else { JobId = str_to_int64(tok); @@ -1864,7 +1869,7 @@ static void do_mount_cmd(UAContext *ua, const char *command) } Dmsg2(120, "Found storage, MediaType=%s DevName=%s\n", - store->media_type, store->dev_name); + store->media_type, store->dev_name()); set_storage(jcr, store); if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) { @@ -1872,7 +1877,7 @@ static void do_mount_cmd(UAContext *ua, const char *command) return; } sd = jcr->store_bsock; - bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); bnet_fsend(sd, "%s %s", command, dev_name); while (bnet_recv(sd) >= 0) { @@ -2013,10 +2018,10 @@ int open_db(UAContext *ua) ua->catalog = (CAT *)GetNextRes(R_CATALOG, NULL); UnlockRes(); if (!ua->catalog) { - bsendmsg(ua, _("Could not find a Catalog resource\n")); + bsendmsg(ua, _("Could not find a Catalog resource\n")); return 0; } else { - bsendmsg(ua, _("Using default Catalog name=%s DB=%s\n"), + bsendmsg(ua, _("Using default Catalog name=%s DB=%s\n"), ua->catalog->hdr.name, ua->catalog->db_name); } } @@ -2032,7 +2037,7 @@ int open_db(UAContext *ua) bsendmsg(ua, _("Could not open database \"%s\".\n"), ua->catalog->db_name); if (ua->db) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } close_db(ua); return 0; diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index aa18973a42..e2be84ffc0 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -92,7 +92,7 @@ int do_a_dot_command(UAContext *ua, const char *cmd) stat = 1; - Dmsg1(400, "Dot command: %s\n", ua->UA_sock->msg); + Dmsg1(1400, "Dot command: %s\n", ua->UA_sock->msg); if (ua->argc == 0) { return 1; } @@ -254,16 +254,16 @@ static int defaultscmd(UAContext *ua, const char *cmd) job = (JOB *)GetResWithName(R_JOB, ua->argv[1]); if (job) { STORE *store; - bsendmsg(ua, "job=%s", job->hdr.name); - bsendmsg(ua, "pool=%s", job->pool->hdr.name); - bsendmsg(ua, "messages=%s", job->messages->hdr.name); - bsendmsg(ua, "client=%s", job->client->hdr.name); - store = (STORE *)job->storage[0]->first(); - bsendmsg(ua, "storage=%s", store->hdr.name); - bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:""); - bsendmsg(ua, "level=%s", level_to_str(job->JobLevel)); - bsendmsg(ua, "type=%s", job_type_to_str(job->JobType)); - bsendmsg(ua, "fileset=%s", job->fileset->hdr.name); + bsendmsg(ua, "job=%s", job->hdr.name); + bsendmsg(ua, "pool=%s", job->pool->hdr.name); + bsendmsg(ua, "messages=%s", job->messages->hdr.name); + bsendmsg(ua, "client=%s", job->client->hdr.name); + store = (STORE *)job->storage->first(); + bsendmsg(ua, "storage=%s", store->hdr.name); + bsendmsg(ua, "where=%s", job->RestoreWhere?job->RestoreWhere:""); + bsendmsg(ua, "level=%s", level_to_str(job->JobLevel)); + bsendmsg(ua, "type=%s", job_type_to_str(job->JobType)); + bsendmsg(ua, "fileset=%s", job->fileset->hdr.name); } } return 1; diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index a6d9396889..6343ca2366 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -85,47 +85,47 @@ static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) strip_trailing_junk(ua->argv[i]); for (p=ua->argv[i]; p && *p; p=e) { /* Check for list */ - e = strchr(p, ','); + e = strchr(p, ','); if (e) { *e++ = 0; } /* Check for range */ - h = strchr(p, '-'); /* range? */ + h = strchr(p, '-'); /* range? */ if (h == p) { - msg = _("Negative numbers not permitted\n"); + msg = _("Negative numbers not permitted\n"); goto bail_out; } if (h) { *h++ = 0; if (!is_an_integer(h)) { - msg = _("Range end is not integer.\n"); + msg = _("Range end is not integer.\n"); goto bail_out; } skip_spaces(&p); if (!is_an_integer(p)) { - msg = _("Range start is not an integer.\n"); + msg = _("Range start is not an integer.\n"); goto bail_out; } beg = atoi(p); end = atoi(h); if (end < beg) { - msg = _("Range end not bigger than start.\n"); + msg = _("Range end not bigger than start.\n"); goto bail_out; } } else { skip_spaces(&p); if (!is_an_integer(p)) { - msg = _("Input value is not an integer.\n"); + msg = _("Input value is not an integer.\n"); goto bail_out; } beg = end = atoi(p); } if (beg <= 0 || end <= 0) { - msg = _("Values must be be greater than zero.\n"); + msg = _("Values must be be greater than zero.\n"); goto bail_out; } if (end >= num_slots) { - msg = _("Slot too large.\n"); + msg = _("Slot too large.\n"); goto bail_out; } for (i=beg; i<=end; i++) { @@ -142,7 +142,7 @@ static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) printf("Slots turned on:\n"); for (i=1; inext) { if (vl->Slot >= max_slots) { - bsendmsg(ua, _("Slot %d larger than max %d ignored.\n")); + bsendmsg(ua, _("Slot %d larger than max %d ignored.\n")); continue; } /* Check if user wants us to look at this slot */ if (!slot_list[vl->Slot]) { - Dmsg1(100, "Skipping slot=%d\n", vl->Slot); + Dmsg1(100, "Skipping slot=%d\n", vl->Slot); continue; } /* If scanning, we read the label rather than the barcode */ @@ -205,11 +205,11 @@ int update_slots(UAContext *ua) vl->VolName = NULL; } vl->VolName = get_volume_name_from_SD(ua, vl->Slot); - Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot); + Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot); } slot_list[vl->Slot] = 0; /* clear Slot */ if (!vl->VolName) { - Dmsg1(100, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot); + Dmsg1(100, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot); memset(&mr, 0, sizeof(mr)); mr.Slot = vl->Slot; mr.InChanger = 1; @@ -217,7 +217,7 @@ int update_slots(UAContext *ua) db_lock(ua->db); db_make_inchanger_unique(ua->jcr, ua->db, &mr); db_unlock(ua->db); - bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), vl->Slot); + bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), vl->Slot); continue; } memset(&mr, 0, sizeof(mr)); @@ -228,20 +228,20 @@ int update_slots(UAContext *ua) mr.Slot = vl->Slot; mr.InChanger = 1; if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } else { bsendmsg(ua, _( - "Catalog record for Volume \"%s\" updated to reference slot %d.\n"), + "Catalog record for Volume \"%s\" updated to reference slot %d.\n"), mr.VolumeName, mr.Slot); } } else { - bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"), + bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"), mr.VolumeName); } db_unlock(ua->db); continue; } else { - bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"), + bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"), mr.VolumeName); } db_unlock(ua->db); @@ -313,7 +313,7 @@ static int do_label(UAContext *ua, const char *cmd, int relabel) if (db_get_media_record(ua->jcr, ua->db, &omr)) { goto checkVol; } - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } /* No keyword or Vol not found, ask user to select */ if (!select_media_dbr(ua, &omr)) { @@ -323,7 +323,7 @@ static int do_label(UAContext *ua, const char *cmd, int relabel) /* Require Volume to be Purged or Recycled */ checkVol: if (strcmp(omr.VolStatus, "Purged") != 0 && strcmp(omr.VolStatus, "Recycle") != 0) { - bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"), + bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"), omr.VolumeName, omr.VolStatus); return 1; } @@ -352,7 +352,7 @@ checkName: /* If VolBytes are zero the Volume is not labeled */ if (db_get_media_record(ua->jcr, ua->db, &mr)) { if (mr.VolBytes != 0) { - bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), + bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), mr.VolumeName); continue; } @@ -392,34 +392,34 @@ checkName: if (relabel) { /* Delete the old media record */ if (!db_delete_media_record(ua->jcr, ua->db, &omr)) { - bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"), + bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"), omr.VolumeName, db_strerror(ua->db)); } else { - bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"), + bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"), omr.VolumeName); /* Update the number of Volumes in the pool */ pr.NumVols--; if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } } } if (ua->automount) { - bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); - bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name); + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); + bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name); bash_spaces(dev_name); - bnet_fsend(sd, "mount %s", dev_name); + bnet_fsend(sd, "mount %s", dev_name); unbash_spaces(dev_name); while (bnet_recv(sd) >= 0) { - bsendmsg(ua, "%s", sd->msg); + bsendmsg(ua, "%s", sd->msg); /* Here we can get * 3001 OK mount. Device=xxx or * 3001 Mounted Volume vvvv * 3906 is cannot mount non-tape * So for those, no need to print a reminder */ - if (strncmp(sd->msg, "3001 ", 5) == 0 || - strncmp(sd->msg, "3906 ", 5) == 0) { + if (strncmp(sd->msg, "3001 ", 5) == 0 || + strncmp(sd->msg, "3906 ", 5) == 0) { print_reminder = false; } } @@ -460,8 +460,8 @@ static void label_from_barcodes(UAContext *ua) /* Display list of Volumes and ask if he really wants to proceed */ bsendmsg(ua, _("The following Volumes will be labeled:\n" - "Slot Volume\n" - "==============\n")); + "Slot Volume\n" + "==============\n")); for (vl=vol_list; vl; vl=vl->next) { if (!vl->VolName || !slot_list[vl->Slot]) { continue; @@ -489,12 +489,12 @@ static void label_from_barcodes(UAContext *ua) media_record_exists = false; if (db_get_media_record(ua->jcr, ua->db, &mr)) { if (mr.VolBytes != 0) { - bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), + bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), vl->Slot, mr.VolumeName); if (!mr.InChanger) { mr.InChanger = 1; if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db)); + bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db)); } } continue; @@ -510,19 +510,19 @@ static void label_from_barcodes(UAContext *ua) if (media_record_exists) { /* we update it */ mr.VolBytes = 1; if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } } else { /* create the media record */ set_pool_dbr_defaults_in_media_dbr(&mr, &pr); if (db_create_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"), + bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"), mr.VolumeName); pr.NumVols++; /* this is a bit suspect */ if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } } else { - bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db)); + bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db)); } } continue; /* done, go handle next volume */ @@ -558,20 +558,20 @@ bool is_volume_name_legal(UAContext *ua, const char *name) continue; } if (ua) { - bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p); + bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p); } return 0; } len = strlen(name); if (len >= MAX_NAME_LENGTH) { if (ua) { - bsendmsg(ua, _("Volume name too long.\n")); + bsendmsg(ua, _("Volume name too long.\n")); } return 0; } if (len == 0) { if (ua) { - bsendmsg(ua, _("Volume name must be at least one character long.\n")); + bsendmsg(ua, _("Volume name must be at least one character long.\n")); } return 0; } @@ -591,7 +591,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (!(sd=open_sd_bsock(ua))) { return false; } - bstrncpy(dev_name, ua->jcr->store->dev_name, sizeof(dev_name)); + bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); bash_spaces(mr->VolumeName); bash_spaces(mr->MediaType); @@ -626,7 +626,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, mr->VolBytes = 1; mr->InChanger = 1; if (!db_update_media_record(ua->jcr, ua->db, mr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); ok = false; } } else { /* create the media record */ @@ -634,15 +634,15 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, mr->VolBytes = 1; /* flag indicating Volume labeled */ mr->InChanger = 1; if (db_create_media_record(ua->jcr, ua->db, mr)) { - bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), + bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), mr->VolumeName, mr->Slot); /* Update number of volumes in pool */ pr->NumVols++; if (!db_update_pool_record(ua->jcr, ua->db, pr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } } else { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); ok = false; } } @@ -660,7 +660,7 @@ static BSOCK *open_sd_bsock(UAContext *ua) bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), store->hdr.name, store->address, store->SDport); if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); + bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); return NULL; } } @@ -688,7 +688,7 @@ static char *get_volume_name_from_SD(UAContext *ua, int Slot) bsendmsg(ua, _("Could not open SD socket.\n")); return NULL; } - bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger list of volumes */ bnet_fsend(sd, _("readlabel %s Slot=%d\n"), dev_name, Slot); @@ -700,7 +700,7 @@ static char *get_volume_name_from_SD(UAContext *ua, int Slot) Dmsg1(100, "Got: %s", sd->msg); if (strncmp(sd->msg, "3001 Volume=", 12) == 0) { VolName = (char *)malloc(sd->msglen); - if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) { + if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) { break; } free(VolName); @@ -730,7 +730,7 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) return NULL; } - bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger list of volumes */ bnet_fsend(sd, _("autochanger list %s \n"), dev_name); @@ -744,8 +744,8 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) /* Check for returned SD messages */ if (sd->msg[0] == '3' && B_ISDIGIT(sd->msg[1]) && B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) && - sd->msg[4] == ' ') { - bsendmsg(ua, "%s\n", sd->msg); /* pass them on to user */ + sd->msg[4] == ' ') { + bsendmsg(ua, "%s\n", sd->msg); /* pass them on to user */ continue; } @@ -756,8 +756,8 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) Slot = atoi(sd->msg); if (Slot <= 0) { p--; - *p = ':'; - bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); + *p = ':'; + bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); continue; } } else { @@ -766,8 +766,8 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) *p++ = 0; if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) { p--; - *p = ':'; - bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); + *p = ':'; + bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); continue; } } else { @@ -775,8 +775,8 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) } if (!is_volume_name_legal(ua, p)) { p--; - *p = ':'; - bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg); + *p = ':'; + bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg); continue; } } @@ -785,7 +785,7 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) vl = (vol_list_t *)malloc(sizeof(vol_list_t)); vl->Slot = Slot; if (p) { - if (*p == ':') { + if (*p == ':') { p++; /* skip separator */ } vl->VolName = bstrdup(p); diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 41ad6b3cc2..5542066280 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -105,6 +105,7 @@ static struct showstruct reses[] = { {N_("directors"), R_DIRECTOR}, {N_("clients"), R_CLIENT}, {N_("counters"), R_COUNTER}, + {N_("devices"), R_DEVICE}, {N_("jobs"), R_JOB}, {N_("storages"), R_STORAGE}, {N_("catalogs"), R_CATALOG}, @@ -149,7 +150,6 @@ int show_cmd(UAContext *ua, const char *cmd) type = reses[j].type; if (type > 0) { res = res_head[type-r_first]; -// res = resources[type-r_first].res_head; } else { res = NULL; } @@ -177,20 +177,19 @@ int show_cmd(UAContext *ua, const char *cmd) case -1: /* all */ for (j=r_first; j<=r_last; j++) { dump_resource(j, res_head[j-r_first], bsendmsg, ua); -// dump_resource(j, resources[j-r_first].res_head, bsendmsg, ua); } break; case -2: - bsendmsg(ua, _("Keywords for the show command are:\n")); + bsendmsg(ua, _("Keywords for the show command are:\n")); for (j=0; reses[j].res_name; j++) { - bsendmsg(ua, "%s\n", _(reses[j].res_name)); + bsendmsg(ua, "%s\n", _(reses[j].res_name)); } goto bail_out; case -3: - bsendmsg(ua, _("%s resource %s not found.\n"), res_name, ua->argv[i]); + bsendmsg(ua, _("%s resource %s not found.\n"), res_name, ua->argv[i]); goto bail_out; case 0: - bsendmsg(ua, _("Resource %s not found\n"), res_name); + bsendmsg(ua, _("Resource %s not found\n"), res_name); goto bail_out; default: dump_resource(recurse?type:-type, res, bsendmsg, ua); @@ -272,7 +271,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) /* List JOBID */ } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) { if (ua->argv[i]) { - jobid = atoi(ua->argv[i]); + jobid = str_to_int64(ua->argv[i]); if (jobid > 0) { jr.JobId = jobid; db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist); @@ -289,13 +288,13 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } else if (strcasecmp(ua->argk[i], _("files")) == 0) { for (j=i+1; jargc; j++) { - if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { + if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; db_get_job_record(ua->jcr, ua->db, &jr); jobid = jr.JobId; - } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { - jobid = atoi(ua->argv[j]); + } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { + jobid = str_to_int64(ua->argv[j]); } else { continue; } @@ -308,13 +307,13 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } else if (strcasecmp(ua->argk[i], _("jobmedia")) == 0) { int done = FALSE; for (j=i+1; jargc; j++) { - if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { + if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; db_get_job_record(ua->jcr, ua->db, &jr); jobid = jr.JobId; - } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { - jobid = atoi(ua->argv[j]); + } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { + jobid = str_to_int64(ua->argv[j]); } else { continue; } @@ -336,22 +335,22 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) /* List MEDIA or VOLUMES */ } else if (strcasecmp(ua->argk[i], _("media")) == 0 || - strcasecmp(ua->argk[i], _("volumes")) == 0) { + strcasecmp(ua->argk[i], _("volumes")) == 0) { bool done = false; for (j=i+1; jargc; j++) { - if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { + if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); jr.JobId = 0; db_get_job_record(ua->jcr, ua->db, &jr); jobid = jr.JobId; - } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { - jobid = atoi(ua->argv[j]); + } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { + jobid = str_to_int64(ua->argv[j]); } else { continue; } VolumeName = get_pool_memory(PM_FNAME); n = db_get_job_volume_names(ua->jcr, ua->db, jobid, &VolumeName); - bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName); + bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName); free_pool_memory(VolumeName); done = true; } @@ -361,9 +360,9 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) uint32_t *ids; /* Is a specific pool wanted? */ for (i=1; iargc; i++) { - if (strcasecmp(ua->argk[i], _("pool")) == 0) { + if (strcasecmp(ua->argk[i], _("pool")) == 0) { if (!get_pool_dbr(ua, &pr)) { - bsendmsg(ua, _("No Pool specified.\n")); + bsendmsg(ua, _("No Pool specified.\n")); return 1; } mr.PoolId = pr.PoolId; @@ -373,7 +372,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) } /* List Volumes in all pools */ if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) { - bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), + bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db)); return 1; } @@ -383,7 +382,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) for (i=0; i < num_pools; i++) { pr.PoolId = ids[i]; if (db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsendmsg(ua, _("Pool: %s\n"), pr.Name); + bsendmsg(ua, _("Pool: %s\n"), pr.Name); } mr.PoolId = ids[i]; db_list_media_records(ua->jcr, ua->db, &mr, prtit, ua, llist); @@ -394,7 +393,7 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) /* List a specific volume */ } else if (strcasecmp(ua->argk[i], _("volume")) == 0) { if (!ua->argv[i]) { - bsendmsg(ua, _("No Volume Name specified.\n")); + bsendmsg(ua, _("No Volume Name specified.\n")); return 1; } bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName)); @@ -402,10 +401,10 @@ static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) return 1; /* List next volume */ } else if (strcasecmp(ua->argk[i], _("nextvol")) == 0 || - strcasecmp(ua->argk[i], _("nextvolume")) == 0) { + strcasecmp(ua->argk[i], _("nextvolume")) == 0) { list_nextvol(ua); } else { - bsendmsg(ua, _("Unknown list keyword: %s\n"), NPRT(ua->argk[i])); + bsendmsg(ua, _("Unknown list keyword: %s\n"), NPRT(ua->argk[i])); } } return 1; @@ -430,7 +429,7 @@ static bool list_nextvol(UAContext *ua) } else { job = (JOB *)GetResWithName(R_JOB, ua->argv[i]); if (!job) { - Jmsg(jcr, M_ERROR, 0, _("%s is not a job name.\n"), ua->argv[i]); + Jmsg(jcr, M_ERROR, 0, _("%s is not a job name.\n"), ua->argv[i]); if ((job = select_job_resource(ua)) == NULL) { return false; } @@ -443,9 +442,9 @@ static bool list_nextvol(UAContext *ua) } if (!find_next_volume_for_append(jcr, &mr, 0)) { - bsendmsg(ua, _("Could not find next Volume.\n")); + bsendmsg(ua, _("Could not find next Volume.\n")); } else { - bsendmsg(ua, _("The next Volume to be used by Job \"%s\" will be %s\n"), + bsendmsg(ua, _("The next Volume to be used by Job \"%s\" will be %s\n"), job->hdr.name, mr.VolumeName); found = true; } @@ -525,15 +524,15 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) if (tod) { /* Jobs scheduled today (next 24 hours) */ #ifdef xxx char buf[300], num[10]; - bsnprintf(buf, sizeof(buf), "tm.hour=%d hour=", tm.tm_hour); + bsnprintf(buf, sizeof(buf), "tm.hour=%d hour=", tm.tm_hour); for (i=0; i<24; i++) { if (bit_is_set(i, run->hour)) { - bsnprintf(num, sizeof(num), "%d ", i); + bsnprintf(num, sizeof(num), "%d ", i); bstrncat(buf, num, sizeof(buf)); } } - bstrncat(buf, "\n", sizeof(buf)); - Dmsg1(000, "%s", buf); + bstrncat(buf, "\n", sizeof(buf)); + Dmsg1(000, "%s", buf); #endif /* find time (time_t) job is to be run */ localtime_r(&now, &tm); @@ -543,9 +542,9 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) tm.tm_min = run->minute; tm.tm_sec = 0; runtime = mktime(&tm); - Dmsg2(200, "now=%d runtime=%d\n", now, runtime); + Dmsg2(200, "now=%d runtime=%d\n", now, runtime); if (runtime > now) { - Dmsg2(200, "Found it level=%d %c\n", run->level, run->level); + Dmsg2(200, "Found it level=%d %c\n", run->level, run->level); return run; /* found it, return run resource */ } } @@ -561,9 +560,9 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) tm.tm_min = run->minute; tm.tm_sec = 0; runtime = mktime(&tm); - Dmsg2(200, "now=%d runtime=%d\n", now, runtime); + Dmsg2(200, "now=%d runtime=%d\n", now, runtime); if (runtime < tomorrow) { - Dmsg2(200, "Found it level=%d %c\n", run->level, run->level); + Dmsg2(200, "Found it level=%d %c\n", run->level, run->level); return run; /* found it, return run resource */ } } @@ -594,7 +593,7 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"), jcr->catalog->db_name); if (jcr->db) { - Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); + Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); } return 0; } @@ -602,7 +601,7 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */ /* Try to create the pool */ if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) { - Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, + Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, db_strerror(jcr->db)); if (jcr->db) { db_close_database(jcr, jcr->db); @@ -610,7 +609,7 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) } return 0; } else { - Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); + Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); } } jcr->PoolId = pr.PoolId; diff --git a/bacula/src/dird/ua_query.c b/bacula/src/dird/ua_query.c index 9b18ac9406..8c22b60204 100644 --- a/bacula/src/dird/ua_query.c +++ b/bacula/src/dird/ua_query.c @@ -106,16 +106,16 @@ int querycmd(UAContext *ua, const char *cmd) len = strlen(line); if (line[0] == '*') { /* prompt */ if (nprompt >= 9) { - bsendmsg(ua, _("Too many prompts in query, max is 9.\n")); + bsendmsg(ua, _("Too many prompts in query, max is 9.\n")); } else { - line[len++] = ' '; + line[len++] = ' '; line[len] = 0; prompt[nprompt++] = bstrdup(line+1); continue; } } if (*query != 0) { - pm_strcat(query, " "); + pm_strcat(query, " "); } pm_strcat(query, line); if (line[len-1] != ';') { @@ -124,11 +124,11 @@ int querycmd(UAContext *ua, const char *cmd) line[len-1] = 0; /* zap ; */ if (query[0] != 0) { query = substitute_prompts(ua, query, prompt, nprompt); - Dmsg1(100, "Query2=%s\n", query); - if (query[0] == '!') { + Dmsg1(100, "Query2=%s\n", query); + if (query[0] == '!') { db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST); } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) { - bsendmsg(ua, "%s\n", query); + bsendmsg(ua, "%s\n", query); } query[0] = 0; } @@ -137,10 +137,10 @@ int querycmd(UAContext *ua, const char *cmd) if (query[0] != 0) { query = substitute_prompts(ua, query, prompt, nprompt); Dmsg1(100, "Query2=%s\n", query); - if (query[0] == '!') { + if (query[0] == '!') { db_list_sql_query(ua->jcr, ua->db, query+1, prtit, ua, 0, VERT_LIST); } else if (!db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST)) { - bsendmsg(ua, "%s\n", query); + bsendmsg(ua, "%s\n", query); } } @@ -181,16 +181,16 @@ static POOLMEM *substitute_prompts(UAContext *ua, } p++; switch (*p) { - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - n = (int)(*p) - (int)'1'; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = (int)(*p) - (int)'1'; if (prompt[n]) { if (!subst[n]) { if (!get_cmd(ua, prompt[n])) { @@ -209,16 +209,16 @@ static POOLMEM *substitute_prompts(UAContext *ua, *o++ = *p++; } } else { - bsendmsg(ua, _("Warning prompt %d missing.\n"), n+1); + bsendmsg(ua, _("Warning prompt %d missing.\n"), n+1); } q += 2; break; - case '%': - *o++ = '%'; + case '%': + *o++ = '%'; q += 2; break; default: - *o++ = '%'; + *o++ = '%'; q++; break; } @@ -267,17 +267,17 @@ int sqlquerycmd(UAContext *ua, const char *cmd) } query = check_pool_memory_size(query, len + 1); if (*query != 0) { - strcat(query, " "); + pm_strcat(query, " "); } - strcat(query, ua->cmd); + pm_strcat(query, ua->cmd); if (ua->cmd[len-1] == ';') { ua->cmd[len-1] = 0; /* zap ; */ /* Submit query */ db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST); *query = 0; /* start new query */ - msg = _("Enter SQL query: "); + msg = _("Enter SQL query: "); } else { - msg = _("Add to SQL query: "); + msg = _("Add to SQL query: "); } } free_pool_memory(query); diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index a62b4ec961..d4ca3b1b2a 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -14,7 +14,7 @@ */ /* - Copyright (C) 2002-2004 Kern Sibbald and John Walker + Copyright (C) 2002-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -149,8 +149,8 @@ int restore_cmd(UAContext *ua, const char *cmd) UnlockRes(); if (!rx.restore_jobs) { bsendmsg(ua, _( - "No Restore Job Resource found. You must create at least\n" - "one before running this command.\n")); + "No Restore Job Resource found. You must create at least\n" + "one before running this command.\n")); goto bail_out; } @@ -165,7 +165,7 @@ int restore_cmd(UAContext *ua, const char *cmd) goto bail_out; case 1: /* select by jobid */ if (!build_directory_tree(ua, &rx)) { - bsendmsg(ua, _("Restore not done.\n")); + bsendmsg(ua, _("Restore not done.\n")); goto bail_out; } break; @@ -175,14 +175,14 @@ int restore_cmd(UAContext *ua, const char *cmd) if (rx.bsr->JobId) { if (!complete_bsr(ua, rx.bsr)) { /* find Vol, SessId, SessTime from JobIds */ - bsendmsg(ua, _("Unable to construct a valid BSR. Cannot continue.\n")); + bsendmsg(ua, _("Unable to construct a valid BSR. Cannot continue.\n")); goto bail_out; } if (!write_bsr_file(ua, rx.bsr)) { goto bail_out; } bsendmsg(ua, _("\n%u file%s selected to be restored.\n\n"), rx.selected_files, - rx.selected_files==1?"":"s"); + rx.selected_files==1?"":"s"); } else { bsendmsg(ua, _("No files selected to be restored.\n")); goto bail_out; @@ -206,15 +206,15 @@ int restore_cmd(UAContext *ua, const char *cmd) /* Build run command */ if (rx.where) { Mmsg(ua->cmd, - "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"" - " where=\"%s\" files=%d catalog=\"%s\"", - job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", + "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"" + " where=\"%s\" files=%d catalog=\"%s\"", + job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", working_directory, rx.where, rx.selected_files, ua->catalog->hdr.name); } else { Mmsg(ua->cmd, - "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"" - " files=%d catalog=\"%s\"", - job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", + "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"" + " files=%d catalog=\"%s\"", + job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", working_directory, rx.selected_files, ua->catalog->hdr.name); } if (find_arg(ua, _("yes")) > 0) { @@ -329,14 +329,14 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) } } if (!found_kw) { - bsendmsg(ua, _("Unknown keyword: %s\n"), ua->argk[i]); + bsendmsg(ua, _("Unknown keyword: %s\n"), ua->argk[i]); return 0; } /* Found keyword in kw[] list, process it */ switch (j) { case 0: /* jobid */ if (*rx->JobIds != 0) { - pm_strcat(rx->JobIds, ","); + pm_strcat(rx->JobIds, ","); } pm_strcat(rx->JobIds, ua->argv[i]); done = true; @@ -347,7 +347,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) break; case 2: /* before */ if (str_to_utime(ua->argv[i]) == 0) { - bsendmsg(ua, _("Improper date format: %s\n"), ua->argv[i]); + bsendmsg(ua, _("Improper date format: %s\n"), ua->argv[i]); return 0; } bstrncpy(date, ua->argv[i], sizeof(date)); @@ -380,12 +380,12 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) case 5: /* pool specified */ rx->pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]); if (!rx->pool) { - bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]); + bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]); return 0; } if (!acl_access_ok(ua, Pool_ACL, ua->argv[i])) { rx->pool = NULL; - bsendmsg(ua, _("Error: Pool resource \"%s\" access not allowed.\n"), ua->argv[i]); + bsendmsg(ua, _("Error: Pool resource \"%s\" access not allowed.\n"), ua->argv[i]); return 0; } break; @@ -405,9 +405,9 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) if (!done) { bsendmsg(ua, _("\nFirst you select one or more JobIds that contain files\n" - "to be restored. You will be presented several methods\n" - "of specifying the JobIds. Then you will be allowed to\n" - "select which files from those JobIds are to be restored.\n\n")); + "to be restored. You will be presented several methods\n" + "of specifying the JobIds. Then you will be allowed to\n" + "select which files from those JobIds are to be restored.\n\n")); } /* If choice not already made above, prompt */ @@ -432,7 +432,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) done = false; break; case 1: /* list where a file is saved */ - if (!get_cmd(ua, _("Enter Filename (no path):"))) { + if (!get_cmd(ua, _("Enter Filename (no path):"))) { return 0; } len = strlen(ua->cmd); @@ -447,13 +447,13 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) done = false; break; case 2: /* enter a list of JobIds */ - if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) { + if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) { return 0; } pm_strcpy(rx->JobIds, ua->cmd); break; case 3: /* Enter an SQL list command */ - if (!get_cmd(ua, _("Enter SQL list command: "))) { + if (!get_cmd(ua, _("Enter SQL list command: "))) { return 0; } gui_save = ua->jcr->gui; @@ -481,11 +481,11 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) if (!get_client_name(ua, rx)) { return 0; } - bsendmsg(ua, _("Enter file names with paths, or < to enter a filename\n" - "containg a list of file names with paths, and terminate\n" - "them with a blank line.\n")); + bsendmsg(ua, _("Enter file names with paths, or < to enter a filename\n" + "containg a list of file names with paths, and terminate\n" + "them with a blank line.\n")); for ( ;; ) { - if (!get_cmd(ua, _("Enter full filename: "))) { + if (!get_cmd(ua, _("Enter full filename: "))) { return 0; } len = strlen(ua->cmd); @@ -506,11 +506,11 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) if (!get_client_name(ua, rx)) { return 0; } - bsendmsg(ua, _("Enter file names with paths, or < to enter a filename\n" - "containg a list of file names with paths, and terminate\n" - "them with a blank line.\n")); + bsendmsg(ua, _("Enter file names with paths, or < to enter a filename\n" + "containg a list of file names with paths, and terminate\n" + "them with a blank line.\n")); for ( ;; ) { - if (!get_cmd(ua, _("Enter full filename: "))) { + if (!get_cmd(ua, _("Enter full filename: "))) { return 0; } len = strlen(ua->cmd); @@ -544,7 +544,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) for (p=rx->JobIds; ; ) { int stat = get_next_jobid_from_list(&p, &JobId); if (stat < 0) { - bsendmsg(ua, _("Invalid JobId in list.\n")); + bsendmsg(ua, _("Invalid JobId in list.\n")); return 0; } if (stat == 0) { @@ -555,12 +555,12 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) } jr.JobId = JobId; if (!db_get_job_record(ua->jcr, ua->db, &jr)) { - bsendmsg(ua, _("Unable to get Job record for JobId=%u: ERR=%s\n"), + bsendmsg(ua, _("Unable to get Job record for JobId=%u: ERR=%s\n"), JobId, db_strerror(ua->db)); return 0; } if (!acl_access_ok(ua, Job_ACL, jr.Name)) { - bsendmsg(ua, _("No authorization. Job \"%s\" not selected.\n"), + bsendmsg(ua, _("No authorization. Job \"%s\" not selected.\n"), jr.Name); continue; } @@ -575,7 +575,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) static int get_date(UAContext *ua, char *date, int date_len) { bsendmsg(ua, _("The restored files will the most current backup\n" - "BEFORE the date you specify below.\n\n")); + "BEFORE the date you specify below.\n\n")); for ( ;; ) { if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) { return 0; @@ -603,14 +603,15 @@ static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date) case '<': p++; if ((ffd = fopen(p, "r")) == NULL) { - bsendmsg(ua, _("Cannot open file %s: ERR=%s\n"), - p, strerror(errno)); + berrno be; + bsendmsg(ua, _("Cannot open file %s: ERR=%s\n"), + p, be.strerror()); break; } while (fgets(file, sizeof(file), ffd)) { line++; if (!insert_file_into_findex_list(ua, rx, file, date)) { - bsendmsg(ua, _("Error occurred on line %d of %s\n"), line, p); + bsendmsg(ua, _("Error occurred on line %d of %s\n"), line, p); } } fclose(ffd); @@ -734,7 +735,7 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) /* Use first JobId as estimate of the number of files to restore */ Mmsg(rx->query, uar_count_files, JobId); if (!db_sql_query(ua->db, rx->query, count_handler, (void *)rx)) { - bsendmsg(ua, "%s\n", db_strerror(ua->db)); + bsendmsg(ua, "%s\n", db_strerror(ua->db)); } if (rx->found) { /* Add about 25% more than this job for over estimate */ @@ -755,14 +756,14 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) */ Mmsg(rx->query, uar_sel_files, JobId); if (!db_sql_query(ua->db, rx->query, insert_tree_handler, (void *)&tree)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } /* * Find the MediaTypes for this JobId and add to the name_list */ Mmsg(rx->query, uar_mediatype, JobId); if (!db_sql_query(ua->db, rx->query, unique_name_list_handler, (void *)&rx->name_list)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); + bsendmsg(ua, "%s", db_strerror(ua->db)); } } char ec1[50]; @@ -784,9 +785,9 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) */ if (OK) { for (TREE_NODE *node=first_tree_node(tree.root); node; node=next_tree_node(node)) { - Dmsg2(400, "FI=%d node=0x%x\n", node->FileIndex, node); + Dmsg2(400, "FI=%d node=0x%x\n", node->FileIndex, node); if (node->extract || node->extract_dir) { - Dmsg2(400, "type=%d FI=%d\n", node->type, node->FileIndex); + Dmsg2(400, "type=%d FI=%d\n", node->type, node->FileIndex); add_findex(rx->bsr, node->JobId, node->FileIndex); if (node->extract && node->type != TN_NEWDIR) { rx->selected_files++; /* count only saved files */ @@ -841,7 +842,7 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date if (i >= 0) { bstrncpy(fsr.FileSet, ua->argv[i], sizeof(fsr.FileSet)); if (!db_get_fileset_record(ua->jcr, ua->db, &fsr)) { - bsendmsg(ua, _("Error getting FileSet \"%s\": ERR=%s\n"), fsr.FileSet, + bsendmsg(ua, _("Error getting FileSet \"%s\": ERR=%s\n"), fsr.FileSet, db_strerror(ua->db)); i = -1; } @@ -850,7 +851,7 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date Mmsg(rx->query, uar_sel_fileset, cr.ClientId, cr.ClientId); start_prompt(ua, _("The defined FileSet resources are:\n")); if (!db_sql_query(ua->db, rx->query, fileset_handler, (void *)ua)) { - bsendmsg(ua, "%s\n", db_strerror(ua->db)); + bsendmsg(ua, "%s\n", db_strerror(ua->db)); } if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), fileset_name, sizeof(fileset_name)) < 0) { @@ -859,9 +860,9 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date bstrncpy(fsr.FileSet, fileset_name, sizeof(fsr.FileSet)); if (!db_get_fileset_record(ua->jcr, ua->db, &fsr)) { - bsendmsg(ua, _("Error getting FileSet record: %s\n"), db_strerror(ua->db)); - bsendmsg(ua, _("This probably means you modified the FileSet.\n" - "Continuing anyway.\n")); + bsendmsg(ua, _("Error getting FileSet record: %s\n"), db_strerror(ua->db)); + bsendmsg(ua, _("This probably means you modified the FileSet.\n" + "Continuing anyway.\n")); } } @@ -872,9 +873,9 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date memset(&pr, 0, sizeof(pr)); bstrncpy(pr.Name, rx->pool->hdr.name, sizeof(pr.Name)); if (db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsnprintf(pool_select, sizeof(pool_select), "AND Media.PoolId=%u ", pr.PoolId); + bsnprintf(pool_select, sizeof(pool_select), "AND Media.PoolId=%u ", pr.PoolId); } else { - bsendmsg(ua, _("Pool \"%s\" not found, using any pool.\n"), pr.Name); + bsendmsg(ua, _("Pool \"%s\" not found, using any pool.\n"), pr.Name); } } @@ -968,14 +969,14 @@ static int get_next_jobid_from_list(char **p, uint32_t *JobId) return 0; } *p = q; - *JobId = strtoul(jobid, NULL, 10); + *JobId = str_to_int64(jobid); return 1; } static int count_handler(void *ctx, int num_fields, char **row) { RESTORE_CTX *rx = (RESTORE_CTX *)ctx; - rx->JobId = atoi(row[0]); + rx->JobId = str_to_int64(row[0]); rx->found = true; return 0; } @@ -986,8 +987,8 @@ static int count_handler(void *ctx, int num_fields, char **row) static int jobid_fileindex_handler(void *ctx, int num_fields, char **row) { RESTORE_CTX *rx = (RESTORE_CTX *)ctx; - rx->JobId = atoi(row[0]); - add_findex(rx->bsr, rx->JobId, atoi(row[1])); + rx->JobId = str_to_int64(row[0]); + add_findex(rx->bsr, rx->JobId, str_to_int64(row[1])); rx->found = true; return 0; } @@ -1100,7 +1101,7 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST if (name_list->num_ids > 1) { bsendmsg(ua, _("Warning, the JobIds that you selected refer to more than one MediaType.\n" - "Restore is not possible. The MediaTypes used are:\n")); + "Restore is not possible. The MediaTypes used are:\n")); print_name_list(ua, name_list); rx->store = select_storage_resource(ua); return; @@ -1139,7 +1140,7 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST } } if (store && (store != rx->store)) { - bsendmsg(ua, _("Warning default storage overridden by %s on command line.\n"), + bsendmsg(ua, _("Warning default storage overridden by %s on command line.\n"), store->hdr.name); rx->store = store; } @@ -1151,8 +1152,8 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST if (!rx->store) { bsendmsg(ua, _("\nWarning. Unable to find Storage resource for\n" - "MediaType \"%s\", needed by the Jobs you selected.\n" - "You will be allowed to select a Storage device later.\n"), + "MediaType \"%s\", needed by the Jobs you selected.\n" + "You will be allowed to select a Storage device later.\n"), name_list->name[0]); } } diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index f9e61a47bd..2b770e173a 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -126,7 +126,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 1: /* JobId */ if (jid) { - bsendmsg(ua, _("JobId specified twice.\n")); + bsendmsg(ua, _("JobId specified twice.\n")); return 0; } jid = ua->argv[i]; @@ -135,7 +135,7 @@ int run_cmd(UAContext *ua, const char *cmd) case 2: /* client */ case 3: /* fd */ if (client_name) { - bsendmsg(ua, _("Client specified twice.\n")); + bsendmsg(ua, _("Client specified twice.\n")); return 0; } client_name = ua->argv[i]; @@ -143,7 +143,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 4: /* fileset */ if (fileset_name) { - bsendmsg(ua, _("FileSet specified twice.\n")); + bsendmsg(ua, _("FileSet specified twice.\n")); return 0; } fileset_name = ua->argv[i]; @@ -151,7 +151,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 5: /* level */ if (level_name) { - bsendmsg(ua, _("Level specified twice.\n")); + bsendmsg(ua, _("Level specified twice.\n")); return 0; } level_name = ua->argv[i]; @@ -160,7 +160,7 @@ int run_cmd(UAContext *ua, const char *cmd) case 6: /* storage */ case 7: /* sd */ if (store_name) { - bsendmsg(ua, _("Storage specified twice.\n")); + bsendmsg(ua, _("Storage specified twice.\n")); return 0; } store_name = ua->argv[i]; @@ -168,7 +168,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 8: /* pool */ if (pool_name) { - bsendmsg(ua, _("Pool specified twice.\n")); + bsendmsg(ua, _("Pool specified twice.\n")); return 0; } pool_name = ua->argv[i]; @@ -176,7 +176,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 9: /* where */ if (where) { - bsendmsg(ua, _("Where specified twice.\n")); + bsendmsg(ua, _("Where specified twice.\n")); return 0; } where = ua->argv[i]; @@ -184,7 +184,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 10: /* bootstrap */ if (bootstrap) { - bsendmsg(ua, _("Bootstrap specified twice.\n")); + bsendmsg(ua, _("Bootstrap specified twice.\n")); return 0; } bootstrap = ua->argv[i]; @@ -192,7 +192,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 11: /* replace */ if (replace) { - bsendmsg(ua, _("Replace specified twice.\n")); + bsendmsg(ua, _("Replace specified twice.\n")); return 0; } replace = ua->argv[i]; @@ -200,7 +200,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 12: /* When */ if (when) { - bsendmsg(ua, _("When specified twice.\n")); + bsendmsg(ua, _("When specified twice.\n")); return 0; } when = ua->argv[i]; @@ -208,12 +208,12 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 13: /* Priority */ if (Priority) { - bsendmsg(ua, _("Priority specified twice.\n")); + bsendmsg(ua, _("Priority specified twice.\n")); return 0; } Priority = atoi(ua->argv[i]); if (Priority <= 0) { - bsendmsg(ua, _("Priority must be positive nonzero setting it to 10.\n")); + bsendmsg(ua, _("Priority must be positive nonzero setting it to 10.\n")); Priority = 10; } kw_ok = true; @@ -223,7 +223,7 @@ int run_cmd(UAContext *ua, const char *cmd) break; case 15: /* Verify Job */ if (verify_job_name) { - bsendmsg(ua, _("Verify Job specified twice.\n")); + bsendmsg(ua, _("Verify Job specified twice.\n")); return 0; } verify_job_name = ua->argv[i]; @@ -248,16 +248,16 @@ int run_cmd(UAContext *ua, const char *cmd) * End of keyword for loop -- if not found, we got a bogus keyword */ if (!kw_ok) { - Dmsg1(200, "%s not found\n", ua->argk[i]); + Dmsg1(800, "%s not found\n", ua->argk[i]); /* * Special case for Job Name, it can be the first * keyword that has no value. */ if (!job_name && !ua->argv[i]) { job_name = ua->argk[i]; /* use keyword as job name */ - Dmsg1(200, "Set jobname=%s\n", job_name); + Dmsg1(800, "Set jobname=%s\n", job_name); } else { - bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]); + bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]); return 0; } } @@ -269,22 +269,22 @@ int run_cmd(UAContext *ua, const char *cmd) if (catalog_name != NULL) { catalog = (CAT *)GetResWithName(R_CATALOG, catalog_name); if (catalog == NULL) { - bsendmsg(ua, _("Catalog \"%s\" not found\n"), catalog_name); + bsendmsg(ua, _("Catalog \"%s\" not found\n"), catalog_name); return 0; } } - Dmsg1(200, "Using catalog=%s\n", catalog_name); + Dmsg1(800, "Using catalog=%s\n", catalog_name); if (job_name) { /* Find Job */ job = (JOB *)GetResWithName(R_JOB, job_name); if (!job) { if (*job_name != 0) { - bsendmsg(ua, _("Job \"%s\" not found\n"), job_name); + bsendmsg(ua, _("Job \"%s\" not found\n"), job_name); } job = select_job_resource(ua); } else { - Dmsg1(200, "Found job=%s\n", job_name); + Dmsg1(800, "Found job=%s\n", job_name); } } else { bsendmsg(ua, _("A job name must be specified.\n")); @@ -302,12 +302,12 @@ int run_cmd(UAContext *ua, const char *cmd) store = (STORE *)GetResWithName(R_STORAGE, store_name); if (!store) { if (*store_name != 0) { - bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name); + bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name); } store = select_storage_resource(ua); } } else { - store = (STORE *)job->storage[0]->first(); /* use default */ + store = (STORE *)job->storage->first(); /* use default */ } if (!store) { return 1; @@ -316,13 +316,13 @@ int run_cmd(UAContext *ua, const char *cmd) store->hdr.name); return 0; } - Dmsg1(200, "Using storage=%s\n", store->hdr.name); + Dmsg1(800, "Using storage=%s\n", store->hdr.name); if (pool_name) { pool = (POOL *)GetResWithName(R_POOL, pool_name); if (!pool) { if (*pool_name != 0) { - bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name); + bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name); } pool = select_pool_resource(ua); } @@ -336,13 +336,13 @@ int run_cmd(UAContext *ua, const char *cmd) pool->hdr.name); return 0; } - Dmsg1(200, "Using pool\n", pool->hdr.name); + Dmsg1(800, "Using pool\n", pool->hdr.name); if (client_name) { client = (CLIENT *)GetResWithName(R_CLIENT, client_name); if (!client) { if (*client_name != 0) { - bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name); + bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name); } client = select_client_resource(ua); } @@ -356,12 +356,12 @@ int run_cmd(UAContext *ua, const char *cmd) client->hdr.name); return 0; } - Dmsg1(200, "Using client=%s\n", client->hdr.name); + Dmsg1(800, "Using client=%s\n", client->hdr.name); if (fileset_name) { fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name); if (!fileset) { - bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name); + bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name); fileset = select_fileset_resource(ua); } } else { @@ -378,7 +378,7 @@ int run_cmd(UAContext *ua, const char *cmd) if (verify_job_name) { verify_job = (JOB *)GetResWithName(R_JOB, verify_job_name); if (!verify_job) { - bsendmsg(ua, _("Verify Job \"%s\" not found.\n"), verify_job_name); + bsendmsg(ua, _("Verify Job \"%s\" not found.\n"), verify_job_name); verify_job = select_job_resource(ua); } } else { @@ -411,7 +411,7 @@ int run_cmd(UAContext *ua, const char *cmd) if (when) { jcr->sched_time = str_to_utime(when); if (jcr->sched_time == 0) { - bsendmsg(ua, _("Invalid time, using current time.\n")); + bsendmsg(ua, _("Invalid time, using current time.\n")); jcr->sched_time = time(NULL); } } @@ -431,7 +431,7 @@ int run_cmd(UAContext *ua, const char *cmd) } } if (!jcr->replace) { - bsendmsg(ua, _("Invalid replace option: %s\n"), replace); + bsendmsg(ua, _("Invalid replace option: %s\n"), replace); goto bail_out; } } else if (job->replace) { @@ -458,7 +458,7 @@ try_again: } if (level_name) { if (!get_level_from_name(jcr, level_name)) { - bsendmsg(ua, _("Level %s not valid.\n"), level_name); + bsendmsg(ua, _("Level %s not valid.\n"), level_name); goto bail_out; } } @@ -475,19 +475,19 @@ try_again: * Prompt User to see if all run job parameters are correct, and * allow him to modify them. */ - Dmsg1(20, "JobType=%c\n", jcr->JobType); + Dmsg1(800, "JobType=%c\n", jcr->JobType); switch (jcr->JobType) { char ec1[30]; char dt[MAX_TIME_LENGTH]; case JT_ADMIN: - bsendmsg(ua, _("Run %s job\n" + bsendmsg(ua, _("Run %s job\n" "JobName: %s\n" "FileSet: %s\n" "Client: %s\n" "Storage: %s\n" "When: %s\n" "Priority: %d\n"), - _("Admin"), + _("Admin"), job->hdr.name, jcr->fileset->hdr.name, NPRT(jcr->client->hdr.name), @@ -499,7 +499,7 @@ try_again: case JT_BACKUP: case JT_VERIFY: if (jcr->JobType == JT_BACKUP) { - bsendmsg(ua, _("Run %s job\n" + bsendmsg(ua, _("Run %s job\n" "JobName: %s\n" "FileSet: %s\n" "Level: %s\n" @@ -508,7 +508,7 @@ try_again: "Pool: %s\n" "When: %s\n" "Priority: %d\n"), - _("Backup"), + _("Backup"), job->hdr.name, jcr->fileset->hdr.name, level_to_str(jcr->JobLevel), @@ -522,9 +522,9 @@ try_again: if (jcr->verify_job) { Name = jcr->verify_job->hdr.name; } else { - Name = ""; + Name = ""; } - bsendmsg(ua, _("Run %s job\n" + bsendmsg(ua, _("Run %s job\n" "JobName: %s\n" "FileSet: %s\n" "Level: %s\n" @@ -534,7 +534,7 @@ try_again: "Verify Job: %s\n" "When: %s\n" "Priority: %d\n"), - _("Verify"), + _("Verify"), job->hdr.name, jcr->fileset->hdr.name, level_to_str(jcr->JobLevel), @@ -551,26 +551,26 @@ try_again: if (jid) { jcr->RestoreJobId = atoi(jid); } else { - if (!get_pint(ua, _("Please enter a JobId for restore: "))) { + if (!get_pint(ua, _("Please enter a JobId for restore: "))) { goto bail_out; } jcr->RestoreJobId = ua->pint32_val; } } jcr->JobLevel = L_FULL; /* default level */ - Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId); + Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId); if (jcr->RestoreJobId == 0) { - bsendmsg(ua, _("Run Restore job\n" - "JobName: %s\n" - "Bootstrap: %s\n" - "Where: %s\n" - "Replace: %s\n" - "FileSet: %s\n" - "Client: %s\n" - "Storage: %s\n" - "When: %s\n" - "Catalog: %s\n" - "Priority: %d\n"), + bsendmsg(ua, _("Run Restore job\n" + "JobName: %s\n" + "Bootstrap: %s\n" + "Where: %s\n" + "Replace: %s\n" + "FileSet: %s\n" + "Client: %s\n" + "Storage: %s\n" + "When: %s\n" + "Catalog: %s\n" + "Priority: %d\n"), job->hdr.name, NPRT(jcr->RestoreBootstrap), jcr->where?jcr->where:NPRT(job->RestoreWhere), @@ -582,24 +582,24 @@ try_again: jcr->catalog->hdr.name, jcr->JobPriority); } else { - bsendmsg(ua, _("Run Restore job\n" - "JobName: %s\n" - "Bootstrap: %s\n" - "Where: %s\n" - "Replace: %s\n" - "Client: %s\n" - "Storage: %s\n" - "JobId: %s\n" - "When: %s\n" - "Catalog: %s\n" - "Priority: %d\n"), + bsendmsg(ua, _("Run Restore job\n" + "JobName: %s\n" + "Bootstrap: %s\n" + "Where: %s\n" + "Replace: %s\n" + "Client: %s\n" + "Storage: %s\n" + "JobId: %s\n" + "When: %s\n" + "Catalog: %s\n" + "Priority: %d\n"), job->hdr.name, NPRT(jcr->RestoreBootstrap), jcr->where?jcr->where:NPRT(job->RestoreWhere), replace, jcr->client->hdr.name, jcr->store->hdr.name, - jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1), + jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1), bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->catalog->hdr.name, jcr->JobPriority); @@ -633,27 +633,27 @@ try_again: add_prompt(ua, _("Priority")); /* 6 */ if (jcr->JobType == JT_BACKUP || jcr->JobType == JT_VERIFY) { - add_prompt(ua, _("Pool")); /* 7 */ + add_prompt(ua, _("Pool")); /* 7 */ if (jcr->JobType == JT_VERIFY) { - add_prompt(ua, _("Verify Job")); /* 8 */ + add_prompt(ua, _("Verify Job")); /* 8 */ } } else if (jcr->JobType == JT_RESTORE) { - add_prompt(ua, _("Bootstrap")); /* 7 */ - add_prompt(ua, _("Where")); /* 8 */ - add_prompt(ua, _("Replace")); /* 9 */ - add_prompt(ua, _("JobId")); /* 10 */ + add_prompt(ua, _("Bootstrap")); /* 7 */ + add_prompt(ua, _("Where")); /* 8 */ + add_prompt(ua, _("Replace")); /* 9 */ + add_prompt(ua, _("JobId")); /* 10 */ } switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) { case 0: /* Level */ if (jcr->JobType == JT_BACKUP) { - start_prompt(ua, _("Levels:\n")); - add_prompt(ua, _("Base")); - add_prompt(ua, _("Full")); - add_prompt(ua, _("Incremental")); - add_prompt(ua, _("Differential")); - add_prompt(ua, _("Since")); - switch (do_prompt(ua, "", _("Select level"), NULL, 0)) { + start_prompt(ua, _("Levels:\n")); + add_prompt(ua, _("Base")); + add_prompt(ua, _("Full")); + add_prompt(ua, _("Incremental")); + add_prompt(ua, _("Differential")); + add_prompt(ua, _("Since")); + switch (do_prompt(ua, "", _("Select level"), NULL, 0)) { case 0: jcr->JobLevel = L_BASE; break; @@ -674,13 +674,13 @@ try_again: } goto try_again; } else if (jcr->JobType == JT_VERIFY) { - start_prompt(ua, _("Levels:\n")); - add_prompt(ua, _("Initialize Catalog")); - add_prompt(ua, _("Verify Catalog")); - add_prompt(ua, _("Verify Volume to Catalog")); - add_prompt(ua, _("Verify Disk to Catalog")); - add_prompt(ua, _("Verify Volume Data (not yet implemented)")); - switch (do_prompt(ua, "", _("Select level"), NULL, 0)) { + start_prompt(ua, _("Levels:\n")); + add_prompt(ua, _("Initialize Catalog")); + add_prompt(ua, _("Verify Catalog")); + add_prompt(ua, _("Verify Volume to Catalog")); + add_prompt(ua, _("Verify Disk to Catalog")); + add_prompt(ua, _("Verify Volume Data (not yet implemented)")); + switch (do_prompt(ua, "", _("Select level"), NULL, 0)) { case 0: jcr->JobLevel = L_VERIFY_INIT; break; @@ -701,7 +701,7 @@ try_again: } goto try_again; } else { - bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n")); + bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n")); } goto try_again; case 1: @@ -739,7 +739,7 @@ try_again: break; case 5: /* When */ - if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) { + if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) { break; } if (ua->cmd[0] == 0) { @@ -747,18 +747,18 @@ try_again: } else { jcr->sched_time = str_to_utime(ua->cmd); if (jcr->sched_time == 0) { - bsendmsg(ua, _("Invalid time, using current time.\n")); + bsendmsg(ua, _("Invalid time, using current time.\n")); jcr->sched_time = time(NULL); } } goto try_again; case 6: /* Priority */ - if (!get_pint(ua, _("Enter new Priority: "))) { + if (!get_pint(ua, _("Enter new Priority: "))) { break; } if (ua->pint32_val == 0) { - bsendmsg(ua, _("Priority must be a positive integer.\n")); + bsendmsg(ua, _("Priority must be a positive integer.\n")); } else { jcr->JobPriority = ua->pint32_val; } @@ -776,7 +776,7 @@ try_again: } /* Bootstrap */ - if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) { + if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) { break; } if (jcr->RestoreBootstrap) { @@ -785,9 +785,9 @@ try_again: } if (ua->cmd[0] != 0) { jcr->RestoreBootstrap = bstrdup(ua->cmd); - fd = fopen(jcr->RestoreBootstrap, "r"); + fd = fopen(jcr->RestoreBootstrap, "r"); if (!fd) { - bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"), + bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"), jcr->RestoreBootstrap, strerror(errno)); free(jcr->RestoreBootstrap); jcr->RestoreBootstrap = NULL; @@ -806,25 +806,25 @@ try_again: goto try_again; } /* Where */ - if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) { + if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) { break; } if (jcr->where) { free(jcr->where); jcr->where = NULL; } - if (ua->cmd[0] == '/' && ua->cmd[1] == 0) { + if (ua->cmd[0] == '/' && ua->cmd[1] == 0) { ua->cmd[0] = 0; } jcr->where = bstrdup(ua->cmd); goto try_again; case 9: /* Replace */ - start_prompt(ua, _("Replace:\n")); + start_prompt(ua, _("Replace:\n")); for (i=0; ReplaceOptions[i].name; i++) { add_prompt(ua, ReplaceOptions[i].name); } - opt = do_prompt(ua, "", _("Select replace option"), NULL, 0); + opt = do_prompt(ua, "", _("Select replace option"), NULL, 0); if (opt >= 0) { jcr->replace = ReplaceOptions[opt].token; } @@ -834,7 +834,7 @@ try_again: jid = NULL; /* force reprompt */ jcr->RestoreJobId = 0; if (jcr->RestoreBootstrap) { - bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n")); + bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n")); } goto try_again; default: @@ -845,14 +845,14 @@ try_again: if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) { JobId_t JobId; - Dmsg1(200, "Calling run_job job=%x\n", jcr->job); + Dmsg1(800, "Calling run_job job=%x\n", jcr->job); start_job: JobId = run_job(jcr); free_jcr(jcr); /* release jcr */ if (JobId == 0) { - bsendmsg(ua, _("Job failed.\n")); + bsendmsg(ua, _("Job failed.\n")); } else { - bsendmsg(ua, _("Job started. JobId=%u\n"), JobId); + bsendmsg(ua, _("Job started. JobId=%u\n"), JobId); } return JobId; } diff --git a/bacula/src/dird/ua_server.c b/bacula/src/dird/ua_server.c index 3e4adef377..4b70ba82a8 100644 --- a/bacula/src/dird/ua_server.c +++ b/bacula/src/dird/ua_server.c @@ -8,7 +8,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -30,8 +30,6 @@ #include "bacula.h" #include "dird.h" -/* Imported subroutines */ - /* Imported variables */ extern int r_first; extern int r_last; @@ -39,17 +37,9 @@ extern struct s_res resources[]; extern int console_msg_pending; extern char my_name[]; -/* Static variables */ - -/* Exported variables */ -int quit_cmd_thread = 0; - -/* Imported functions */ /* Forward referenced functions */ - extern "C" void *connect_thread(void *arg); - static void *handle_UA_client_request(void *arg); @@ -74,8 +64,7 @@ void start_UA_server(dlist *addrs) if ((status=pthread_create(&thid, NULL, connect_thread, (void *)myaddrs)) != 0) { berrno be; - be.set_errno(status); - Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.strerror()); + Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.strerror(status)); } started = TRUE; return; @@ -86,7 +75,7 @@ void *connect_thread(void *arg) { pthread_detach(pthread_self()); - /* ****FIXME**** put # 10 (timeout) on config parameter */ + /* Permit 10 console connections */ bnet_thread_server((dlist*)arg, 10, &ua_workq, handle_UA_client_request); return NULL; } @@ -127,14 +116,13 @@ static void *handle_UA_client_request(void *arg) int stat; UAContext *ua; JCR *jcr; - BSOCK *UA_sock = (BSOCK *)arg; pthread_detach(pthread_self()); jcr = new_control_jcr("*Console*", JT_CONSOLE); ua = new_ua_context(jcr); - ua->UA_sock = UA_sock; + ua->UA_sock = (BSOCK *)arg; bnet_recv(ua->UA_sock); /* Get first message */ if (!authenticate_user_agent(ua)) { @@ -146,18 +134,18 @@ static void *handle_UA_client_request(void *arg) if (stat >= 0) { pm_strcpy(ua->cmd, ua->UA_sock->msg); parse_ua_args(ua); - if (ua->argc > 0 && ua->argk[0][0] == '.') { + if (ua->argc > 0 && ua->argk[0][0] == '.') { do_a_dot_command(ua, ua->cmd); } else { do_a_command(ua, ua->cmd); } if (!ua->quit) { if (ua->auto_display_messages) { - strcpy(ua->cmd, "messages"); + pm_strcpy(ua->cmd, "messages"); qmessagescmd(ua, ua->cmd); ua->user_notified_msg_pending = FALSE; } else if (!ua->user_notified_msg_pending && console_msg_pending) { - bsendmsg(ua, _("You have messages.\n")); + bsendmsg(ua, _("You have messages.\n")); ua->user_notified_msg_pending = TRUE; } bnet_sig(ua->UA_sock, BNET_EOD); /* send end of command */ @@ -213,6 +201,7 @@ void free_ua_context(UAContext *ua) if (ua->UA_sock) { bnet_close(ua->UA_sock); + ua->UA_sock = NULL; } free(ua); } @@ -226,5 +215,4 @@ void term_ua_server() if (!started) { return; } - quit_cmd_thread = TRUE; } diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index 533e0ae86b..5023002e54 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -10,7 +10,7 @@ */ /* - Copyright (C) 2002-2004 Kern Sibbald and John Walker + Copyright (C) 2002-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -126,7 +126,7 @@ bool user_select_files_from_tree(TREE_CTX *tree) break; } if (!found) { - bsendmsg(tree->ua, _("Illegal command. Enter \"done\" to exit.\n")); + bsendmsg(tree->ua, _("Illegal command. Enter \"done\" to exit.\n")); continue; } if (!stat) { @@ -208,7 +208,7 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) if (node->inserted) { tree->FileCount++; if (tree->DeltaCount > 0 && (tree->FileCount-tree->LastCount) > tree->DeltaCount) { - bsendmsg(tree->ua, "+"); + bsendmsg(tree->ua, "+"); tree->LastCount = tree->FileCount; } } @@ -311,7 +311,7 @@ static int markcmd(UAContext *ua, TREE_CTX *tree) bsendmsg(ua, _("No files marked.\n")); } else { bsendmsg(ua, _("%s file%s marked.\n"), - edit_uint64_with_commas(count, ec1), count==0?"":"s"); + edit_uint64_with_commas(count, ec1), count==0?"":"s"); } return 1; } @@ -340,7 +340,7 @@ static int markdircmd(UAContext *ua, TREE_CTX *tree) bsendmsg(ua, _("No directories marked.\n")); } else { bsendmsg(ua, _("%s director%s marked.\n"), - edit_uint64_with_commas(count, ec1), count==1?"y":"ies"); + edit_uint64_with_commas(count, ec1), count==1?"y":"ies"); } return 1; } @@ -381,13 +381,13 @@ static int findcmd(UAContext *ua, TREE_CTX *tree) const char *tag; tree_getpath(node, cwd, sizeof(cwd)); if (node->extract) { - tag = "*"; + tag = "*"; } else if (node->extract_dir) { - tag = "+"; + tag = "+"; } else { - tag = ""; + tag = ""; } - bsendmsg(ua, "%s%s\n", tag, cwd); + bsendmsg(ua, "%s%s\n", tag, cwd); } } } @@ -407,13 +407,13 @@ static int lscmd(UAContext *ua, TREE_CTX *tree) if (ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) { const char *tag; if (node->extract) { - tag = "*"; + tag = "*"; } else if (node->extract_dir) { - tag = "+"; + tag = "+"; } else { - tag = ""; + tag = ""; } - bsendmsg(ua, "%s%s%s\n", tag, node->fname, tree_node_has_child(node)?"/":""); + bsendmsg(ua, "%s%s%s\n", tag, node->fname, tree_node_has_child(node)?"/":""); } } return 1; @@ -433,13 +433,13 @@ static void rlsmark(UAContext *ua, TREE_NODE *tnode) (node->extract || node->extract_dir)) { const char *tag; if (node->extract) { - tag = "*"; + tag = "*"; } else if (node->extract_dir) { - tag = "+"; + tag = "+"; } else { - tag = ""; + tag = ""; } - bsendmsg(ua, "%s%s%s\n", tag, node->fname, tree_node_has_child(node)?"/":""); + bsendmsg(ua, "%s%s%s\n", tag, node->fname, tree_node_has_child(node)?"/":""); if (tree_node_has_child(node)) { rlsmark(ua, node); } @@ -507,11 +507,11 @@ static int dircmd(UAContext *ua, TREE_CTX *tree) const char *tag; if (ua->argc == 1 || fnmatch(ua->argk[1], node->fname, 0) == 0) { if (node->extract) { - tag = "*"; + tag = "*"; } else if (node->extract_dir) { - tag = "+"; + tag = "+"; } else { - tag = " "; + tag = " "; } tree_getpath(node, cwd, sizeof(cwd)); fdbr.FileId = 0; @@ -541,7 +541,7 @@ static int dircmd(UAContext *ua, TREE_CTX *tree) memset(&statp, 0, sizeof(statp)); } ls_output(buf, cwd, tag, &statp); - bsendmsg(ua, "%s\n", buf); + bsendmsg(ua, "%s\n", buf); } } return 1; @@ -617,12 +617,12 @@ static int cdcmd(UAContext *ua, TREE_CTX *tree) if (!node) { /* Try once more if Win32 drive -- make absolute */ if (ua->argk[1][1] == ':') { /* win32 drive */ - bstrncpy(cwd, "/", sizeof(cwd)); + bstrncpy(cwd, "/", sizeof(cwd)); bstrncat(cwd, ua->argk[1], sizeof(cwd)); node = tree_cwd(cwd, tree->root, tree->node); } if (!node) { - bsendmsg(ua, _("Invalid path given.\n")); + bsendmsg(ua, _("Invalid path given.\n")); } else { tree->node = node; } diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 6e0019da22..9f3082d4d4 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -15,7 +15,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -74,9 +74,6 @@ bool do_verify(JCR *jcr) if (!jcr->verify_jr) { jcr->verify_jr = &verify_jr; } - if (!get_or_create_client_record(jcr)) { - goto bail_out; - } Dmsg1(9, "bdird: created client %s record\n", jcr->client->hdr.name); @@ -119,10 +116,6 @@ bool do_verify(JCR *jcr) goto bail_out; } - if (!jcr->fname) { - jcr->fname = get_pool_memory(PM_FNAME); - } - /* Print Job Start message */ Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%d Level=%s Job=%s\n"), jcr->JobId, level_to_str(jcr->JobLevel), jcr->Job); @@ -190,7 +183,7 @@ bool do_verify(JCR *jcr) /* * Now start a job with the Storage daemon */ - if (!start_storage_daemon_job(jcr)) { + if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) { goto bail_out; } /* diff --git a/bacula/src/filed/acl.c b/bacula/src/filed/acl.c index 2e5a85a692..e9e093f286 100644 --- a/bacula/src/filed/acl.c +++ b/bacula/src/filed/acl.c @@ -97,7 +97,7 @@ JCR jcr; * with what we have and give all ACL streams a new number/type. */ #endif -#if !defined(HAVE_ACL) || ! defined(HAVE_LINUX_OS) +#if !defined(HAVE_ACL) || !defined(HAVE_LINUX_OS) /* bacl_get() returns the lenght of the string, or -1 on error. */ int bacl_get(JCR *jcr, int acltype) @@ -181,7 +181,7 @@ int bacl_get(JCR *jcr, int acltype) } /***** Do we really want to silently ignore errors from acl_get_file and acl_to_text? *****/ - return -1; + return 0; } int bacl_set(JCR *jcr, int acltype) @@ -418,7 +418,7 @@ int aclcp(char *src, char *dst) if (S_ISDIR(st.st_mode) && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) { jcr.last_fname = src; if (bacl_get(&jcr, BACL_TYPE_DEFAULT) < 0) { - Dmsg1(200, "aclcp: could not read default ACLs for %s\n", jcr.last_fname); + Dmsg1(200, "aclcp: could not read default ACLs for %s\n", jcr.last_fname); return EXIT_FAILURE; } else { jcr.last_fname = dst; diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index f0a0e0c890..d6faeadaa3 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -533,8 +533,8 @@ static void add_fname_to_list(JCR *jcr, char *fname, int list) /* Copy File options */ if (list == INC_LIST) { *q = 0; /* terminate options */ - strcpy(buf, fname); - strcat(buf, " "); + bstrncpy(buf, fname, sizeof(buf)); + bstrncat(buf, " ", sizeof(buf)); optlen = strlen(buf); } else { optlen = 0; @@ -564,8 +564,8 @@ static void add_fname_to_list(JCR *jcr, char *fname, int list) /* Copy File options */ if (list == INC_LIST) { *q = 0; /* terminate options */ - strcpy(buf, fname); - strcat(buf, " "); + bstrncpy(buf, fname, sizeof(buf)); + bstrncat(buf, " ", sizeof(buf)); optlen = strlen(buf); } else { optlen = 0; diff --git a/bacula/src/filed/verify_vol.c b/bacula/src/filed/verify_vol.c index 99e296d09b..23940b0920 100644 --- a/bacula/src/filed/verify_vol.c +++ b/bacula/src/filed/verify_vol.c @@ -87,7 +87,7 @@ void do_verify_volume(JCR *jcr) */ if (sscanf(sd->msg, rec_header, &VolSessionId, &VolSessionTime, &file_index, &stream, &size) != 5) { - Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg); + Jmsg1(jcr, M_FATAL, 0, _("Record header scan error: %s\n"), sd->msg); goto bail_out; } Dmsg2(30, "Got hdr: FilInx=%d Stream=%d.\n", file_index, stream); @@ -96,11 +96,11 @@ void do_verify_volume(JCR *jcr) * Now we expect the Stream Data */ if (bget_msg(sd) < 0) { - Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd)); + Jmsg1(jcr, M_FATAL, 0, _("Data record error. ERR=%s\n"), bnet_strerror(sd)); goto bail_out; } if (size != ((uint32_t)sd->msglen)) { - Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size); + Jmsg2(jcr, M_FATAL, 0, _("Actual data size %d not same as header %d\n"), sd->msglen, size); goto bail_out; } Dmsg1(30, "Got stream data, len=%d\n", sd->msglen); @@ -111,7 +111,7 @@ void do_verify_volume(JCR *jcr) case STREAM_UNIX_ATTRIBUTES_EX: char *ap, *lp, *fp; - Dmsg0(400, "Stream=Unix Attributes.\n"); + Dmsg0(400, "Stream=Unix Attributes.\n"); if ((int)sizeof_pool_memory(fname) < sd->msglen) { fname = realloc_pool_memory(fname, sd->msglen + 1); @@ -132,22 +132,22 @@ void do_verify_volume(JCR *jcr) * Link name (if file linked i.e. FT_LNK) * Extended Attributes (if Win32) */ - if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) { - Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg); - Dmsg0(0, "\nError scanning header\n"); + if (sscanf(sd->msg, "%d %d", &record_file_index, &type) != 2) { + Jmsg(jcr, M_FATAL, 0, _("Error scanning record header: %s\n"), sd->msg); + Dmsg0(0, "\nError scanning header\n"); goto bail_out; } - Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type); + Dmsg2(30, "Got Attr: FilInx=%d type=%d\n", record_file_index, type); if (record_file_index != file_index) { - Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"), + Jmsg(jcr, M_FATAL, 0, _("Record header file index %ld not equal record index %ld\n"), file_index, record_file_index); - Dmsg0(0, "File index error\n"); + Dmsg0(0, "File index error\n"); goto bail_out; } ap = sd->msg; - while (*ap++ != ' ') /* skip record file index */ + while (*ap++ != ' ') /* skip record file index */ ; - while (*ap++ != ' ') /* skip type */ + while (*ap++ != ' ') /* skip type */ ; /* Save filename and position to attributes */ fp = fname; @@ -156,21 +156,21 @@ void do_verify_volume(JCR *jcr) } *fp = *ap++; /* terminate filename & point to attribs */ - Dmsg1(200, "Attr=%s\n", ap); + Dmsg1(200, "Attr=%s\n", ap); /* Skip to Link name */ if (type == FT_LNK || type == FT_LNKSAVED) { lp = ap; while (*lp++ != 0) { ; } - strcat(lname, lp); /* "save" link name */ + pm_strcat(lname, lp); /* "save" link name */ } else { *lname = 0; } P(jcr->mutex); jcr->JobFiles++; jcr->num_files_examined++; - pm_strcpy(&jcr->last_fname, fname); /* last file examined */ + pm_strcpy(jcr->last_fname, fname); /* last file examined */ V(jcr->mutex); /* @@ -185,19 +185,19 @@ void do_verify_volume(JCR *jcr) * slash. For a linked file, link is the link. */ /* Send file attributes to Director */ - Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname); + Dmsg2(200, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, fname); if (type == FT_LNK || type == FT_LNKSAVED) { - stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles, - STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, + stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles, + STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, 0, ap, 0, lname, 0); } else { - stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles, - STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, + stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles, + STREAM_UNIX_ATTRIBUTES, "pinsug5", fname, 0, ap, 0, 0); } - Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg); + Dmsg2(200, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg); if (!stat) { - Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir)); + Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir)); goto bail_out; } break; @@ -216,23 +216,23 @@ void do_verify_volume(JCR *jcr) case STREAM_MD5_SIGNATURE: char MD5buf[30]; bin_to_base64(MD5buf, (char *)sd->msg, 16); /* encode 16 bytes */ - 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, + 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); + Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg); break; case STREAM_SHA1_SIGNATURE: char SHA1buf[30]; bin_to_base64(SHA1buf, (char *)sd->msg, 20); /* encode 20 bytes */ - Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf); - bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE, + Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf); + bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE, SHA1buf, jcr->JobFiles); - Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg); + Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg); break; default: - Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); + Pmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); break; } /* end switch */ } /* end while bnet_get */ diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 38a9cd7b5a..085e720c30 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -86,6 +86,8 @@ #define foreach_jcr(jcr) \ for ((jcr)=NULL; ((jcr)=get_next_jcr(jcr)); ) +#define SD_APPEND 1 +#define SD_READ 0 struct JCR; @@ -141,7 +143,6 @@ struct JCR { /* This should be empty in the library */ #ifdef DIRECTOR_DAEMON -#define MAX_STORE 2 /* Director Daemon specific part of JCR */ pthread_t SD_msg_chan; /* Message channel thread id */ pthread_cond_t term_wait; /* Wait for job termination */ @@ -150,7 +151,7 @@ struct JCR { BSOCK *ua; /* User agent */ JOB *job; /* Job resource */ JOB *verify_job; /* Job resource of verify target job */ - alist *storage[MAX_STORE]; /* Storage possibilities */ + alist *storage; /* Storage possibilities */ STORE *store; /* Storage daemon selected */ CLIENT *client; /* Client resource */ POOL *pool; /* Pool resource */ @@ -224,7 +225,8 @@ struct JCR { pthread_cond_t job_start_wait; /* Wait for FD to start Job */ int type; DCR *dcr; /* device context record */ - DEVRES *device; /* device resource to use */ + alist *dcrs; /* list of dcrs open */ +// DEVRES *device; /* device resource to use */ POOLMEM *job_name; /* base Job name (not unique) */ POOLMEM *fileset_name; /* FileSet */ POOLMEM *fileset_md5; /* MD5 for FileSet */ diff --git a/bacula/src/lib/alist.h b/bacula/src/lib/alist.h index 2a1a26d182..f02be3d5c0 100644 --- a/bacula/src/lib/alist.h +++ b/bacula/src/lib/alist.h @@ -3,7 +3,7 @@ */ /* - Copyright (C) 2003-2004 Kern Sibbald and John Walker + Copyright (C) 2003-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -32,11 +32,13 @@ * Loop var through each member of list */ #define foreach_alist(var, list) \ - for((*((void **)&(var))=(void*)((list)->first())); (var); (*((void **)&(var))=(void*)((list)->next()))) + for((*((void **)&(var))=(void*)((list)->first())); \ + (var); \ + (*((void **)&(var))=(void*)((list)->next()))) #ifdef the_easy_way #define foreach_alist(var, list) \ - for((void*(var))=(list)->first(); (var); (void *(var))=(list)->next(var)); ) + for((void*(var))=(list)->first(); (var); (void *(var))=(list)->next(var)); ) #endif diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index cc7b2fb92c..10657394f1 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -370,7 +370,7 @@ bool bnet_send(BSOCK * bsock) if (rc < 0) { if (!bsock->suppress_error_msgs && !bsock->timed_out) { Qmsg4(bsock->jcr, M_ERROR, 0, - _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who, + _("Write error sending len to %s:%s:%d: ERR=%s\n"), bsock->who, bsock->host, bsock->port, bnet_strerror(bsock)); } } else { @@ -400,8 +400,9 @@ bool bnet_send(BSOCK * bsock) } if (rc < 0) { if (!bsock->suppress_error_msgs) { - Qmsg4(bsock->jcr, M_ERROR, 0, - _("Write error sending to %s:%s:%d: ERR=%s\n"), bsock->who, + Qmsg5(bsock->jcr, M_ERROR, 0, + _("Write error sending %d bytes to %s:%s:%d: ERR=%s\n"), + bsock->msglen, bsock->who, bsock->host, bsock->port, bnet_strerror(bsock)); } } else { diff --git a/bacula/src/lib/bpipe.c b/bacula/src/lib/bpipe.c index 4350de4c05..4778b84aad 100644 --- a/bacula/src/lib/bpipe.c +++ b/bacula/src/lib/bpipe.c @@ -195,38 +195,38 @@ int close_bpipe(BPIPE *bpipe) /* wait for worker child to exit */ for ( ;; ) { - Dmsg2(200, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option); + Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option); do { wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option); } while (wpid == -1 && (errno == EINTR || errno == EAGAIN)); if (wpid == bpipe->worker_pid || wpid == -1) { stat = errno; - Dmsg3(200, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus, - wpid==-1?strerror(errno):"none"); + Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus, + wpid==-1?strerror(errno):"none"); break; } - Dmsg3(200, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus, - wpid==-1?strerror(errno):"none"); + Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus, + wpid==-1?strerror(errno):"none"); if (remaining_wait > 0) { bmicrosleep(1, 0); /* wait one second */ remaining_wait--; } else { stat = ETIME; /* set error status */ wpid = -1; - break; /* don't wait any longer */ + break; /* don't wait any longer */ } } if (wpid > 0) { if (WIFEXITED(chldstatus)) { /* process exit()ed */ stat = WEXITSTATUS(chldstatus); if (stat != 0) { - Dmsg1(200, "Non-zero status %d returned from child.\n", stat); + Dmsg1(800, "Non-zero status %d returned from child.\n", stat); stat |= b_errno_exit; /* exit status returned */ } - Dmsg1(200, "child status=%d\n", stat & ~b_errno_exit); + Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit); } else if (WIFSIGNALED(chldstatus)) { /* process died */ stat = WTERMSIG(chldstatus); - Dmsg1(200, "Child died from signale %d\n", stat); + Dmsg1(800, "Child died from signale %d\n", stat); stat |= b_errno_signal; /* exit signal returned */ } } @@ -234,7 +234,7 @@ int close_bpipe(BPIPE *bpipe) stop_child_timer(bpipe->timer_id); } free(bpipe); - Dmsg1(200, "returning stat = %d\n", stat); + Dmsg1(800, "returning stat = %d\n", stat); return stat; } @@ -269,9 +269,9 @@ int run_program(char *prog, int wait, POOLMEM *results) stat1 = ferror(bpipe->rfd); } if (stat1 < 0) { - Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno)); + Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno)); } else if (stat1 != 0) { - Dmsg1(100, "Run program fgets stat=%d\n", stat1); + Dmsg1(100, "Run program fgets stat=%d\n", stat1); } } else { stat1 = 0; @@ -317,18 +317,18 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results) while (1) { fgets(tmp, sizeof_pool_memory(tmp), bpipe->rfd); - Dmsg1(200, "Run program fgets=%s", tmp); + Dmsg1(800, "Run program fgets=%s", tmp); pm_strcat(results, tmp); if (feof(bpipe->rfd)) { - stat1 = 0; + stat1 = 0; Dmsg1(100, "Run program fgets stat=%d\n", stat1); - break; + break; } else { - stat1 = ferror(bpipe->rfd); + stat1 = ferror(bpipe->rfd); } if (stat1 < 0) { Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno)); - break; + break; } else if (stat1 != 0) { Dmsg1(100, "Run program fgets stat=%d\n", stat1); } @@ -371,16 +371,16 @@ static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv) q++; quote = 0; } else { - while (*q && *q != ' ') + while (*q && *q != ' ') q++; } if (*q) - *(q++) = '\0'; + *(q++) = '\0'; bargv[argc++] = p; p = q; - while (*p && (*p == ' ' || *p == '\t')) + while (*p && (*p == ' ' || *p == '\t')) p++; - if (*p == '\"' || *p == '\'') { + if (*p == '\"' || *p == '\'') { quote = *p; p++; } diff --git a/bacula/src/lib/daemon.c b/bacula/src/lib/daemon.c index 177ffe7c3d..cd0545a61c 100644 --- a/bacula/src/lib/daemon.c +++ b/bacula/src/lib/daemon.c @@ -53,7 +53,7 @@ daemon_start() * Become a daemon. */ - Dmsg0(200, "Enter daemon_start\n"); + Dmsg0(900, "Enter daemon_start\n"); if ( (cpid = fork() ) < 0) Emsg1(M_ABORT, 0, "Cannot fork to become daemon: %s\n", strerror(errno)); else if (cpid > 0) @@ -106,5 +106,5 @@ daemon_start() } #endif /* HAVE_CYGWIN */ - Dmsg0(200, "Exit daemon_start\n"); + Dmsg0(900, "Exit daemon_start\n"); } diff --git a/bacula/src/lib/edit.c b/bacula/src/lib/edit.c index 97cdb810da..526af060f8 100644 --- a/bacula/src/lib/edit.c +++ b/bacula/src/lib/edit.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -94,7 +94,7 @@ char *edit_uint64_with_commas(uint64_t val, char *buf) mbuf[i--] = '0'; } else { while (val != 0) { - mbuf[i--] = "0123456789"[val%10]; + mbuf[i--] = "0123456789"[val%10]; val /= 10; } } @@ -119,7 +119,7 @@ char *edit_uint64(uint64_t val, char *buf) mbuf[i--] = '0'; } else { while (val != 0) { - mbuf[i--] = "0123456789"[val%10]; + mbuf[i--] = "0123456789"[val%10]; val /= 10; } } @@ -127,6 +127,35 @@ char *edit_uint64(uint64_t val, char *buf) return buf; } +char *edit_int64(int64_t val, char *buf) +{ + /* + * Replacement for sprintf(buf, "%" llu, val) + */ + char mbuf[50]; + bool negative = false; + mbuf[sizeof(mbuf)-1] = 0; + int i = sizeof(mbuf)-2; /* edit backward */ + if (val == 0) { + mbuf[i--] = '0'; + } else { + if (val < 0) { + negative = true; + val = -val; + } + while (val != 0) { + mbuf[i--] = "0123456789"[val%10]; + val /= 10; + } + } + if (negative) { + mbuf[i--] = '-'; + } + strcpy(buf, &mbuf[i+1]); + return buf; +} + + /* * Given a string "str", separate the integer part into * str, and the modifier into mod. @@ -206,7 +235,7 @@ int duration_to_utime(char *str, utime_t *value) * Baculas. */ static const char *mod[] = {"n", "seconds", "months", "minutes", - "hours", "days", "weeks", "quarters", "years", NULL}; + "hours", "days", "weeks", "quarters", "years", NULL}; static const int32_t mult[] = {60, 1, 60*60*24*30, 60, 60*60, 60*60*24, 60*60*24*7, 60*60*24*91, 60*60*24*365}; @@ -256,7 +285,7 @@ char *edit_utime(utime_t val, char *buf, int buf_len) times = (uint32_t)(val / mult[i]); if (times > 0) { val = val - (utime_t)times * mult[i]; - bsnprintf(mybuf, sizeof(mybuf), "%d %s%s ", times, mod[i], times>1?"s":""); + bsnprintf(mybuf, sizeof(mybuf), "%d %s%s ", times, mod[i], times>1?"s":""); bstrncat(buf, mybuf, buf_len); } } @@ -372,20 +401,20 @@ bool is_name_valid(char *name, POOLMEM **msg) continue; } if (msg) { - Mmsg(msg, _("Illegal character \"%c\" in name.\n"), *p); + Mmsg(msg, _("Illegal character \"%c\" in name.\n"), *p); } return false; } len = strlen(name); if (len >= MAX_NAME_LENGTH) { if (msg) { - Mmsg(msg, _("Name too long.\n")); + Mmsg(msg, _("Name too long.\n")); } return false; } if (len == 0) { if (msg) { - Mmsg(msg, _("Volume name must be at least one character long.\n")); + Mmsg(msg, _("Volume name must be at least one character long.\n")); } return false; } @@ -437,7 +466,7 @@ int main(int argc, char *argv[]) for (int i=0; i<8; i++) { strcpy(buf, str[i]); if (!duration_to_utime(buf, &val)) { - printf("Error return from duration_to_utime for in=%s\n", str[i]); + printf("Error return from duration_to_utime for in=%s\n", str[i]); continue; } edit_utime(val, outval); diff --git a/bacula/src/lib/htable.c b/bacula/src/lib/htable.c index 1d440c40fa..0af1101356 100644 --- a/bacula/src/lib/htable.c +++ b/bacula/src/lib/htable.c @@ -8,10 +8,10 @@ * the randomness. In this program, the hash table can grow when * it gets too full, so the table size here is a binary number. The * hashing is provided using an idea from Tcl where the initial - * hash code is then "randomized" using a simple calculation from + * hash code is "randomized" using a simple calculation from * a random number generator that multiplies by a big number * (I multiply by a prime number, while Tcl did not) - * then shifts the results down and does the binary division + * then shifts the result down and does the binary division * by masking. Increasing the size of the hash table is simple. * Just create a new larger table, walk the old table and * re-hash insert each entry into the new table. @@ -23,7 +23,7 @@ * */ /* - Copyright (C) 2003-2004 Kern Sibbald and John Walker + Copyright (C) 2003-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -90,33 +90,30 @@ void htable::init(void *item, void *link, int tsize) walk_index = 0; } -#ifdef xxx -void * htable::operator new(size_t) -{ - return malloc(sizeof(htable)); -} - -void htable::operator delete(void *tbl) -{ - ((htable *)tbl)->destroy(); - free(tbl); -} -#endif - uint32_t htable::size() { return num_items; } +/* + * Take each hash link and walk down the chain of items + * that hash there counting them (i.e. the hits), + * then report that number. + * Obiously, the more hits in a chain, the more time + * it takes to reference them. Empty chains are not so + * hot either -- as it means unused or wasted space. + */ +#define MAX_COUNT 20 void htable::stats() { - int count[10]; + int hits[MAX_COUNT]; int max = 0; int i, j; hlink *p; - printf("\n\nNumItems=%d\nBuckets=%d\n", num_items, buckets); - for (i=0; i<10; i++) { - count[i] = 0; + printf("\n\nNumItems=%d\nTotal buckets=%d\n", num_items, buckets); + printf("Hits/bucket: buckets\n"); + for (i=0; i < MAX_COUNT; i++) { + hits[i] = 0; } for (i=0; i<(int)buckets; i++) { p = table[i]; @@ -128,14 +125,14 @@ void htable::stats() if (j > max) { max = j; } - if (j < 10) { - count[j]++; + if (j < MAX_COUNT) { + hits[j]++; } } - for (i=0; i<10; i++) { - printf("%2d: %d\n",i, count[i]); + for (i=0; i < MAX_COUNT; i++) { + printf("%2d: %d\n",i, hits[i]); } - printf("max = %d\n", max); + printf("max hits in a bucket = %d\n", max); } void htable::grow_table() @@ -217,7 +214,7 @@ void *htable::lookup(char *key) for (hlink *hp=table[index]; hp; hp=(hlink *)hp->next) { // Dmsg2(100, "hp=0x%x key=%s\n", (long)hp, hp->key); if (hash == hp->hash && strcmp(key, hp->key) == 0) { - Dmsg1(100, "lookup return %x\n", ((char *)hp)-loffset); + Dmsg1(100, "lookup return %x\n", ((char *)hp)-loffset); return ((char *)hp)-loffset; } } @@ -233,7 +230,7 @@ void *htable::next() while (!walkptr && walk_index < buckets) { walkptr = table[walk_index++]; if (walkptr) { - Dmsg3(100, "new walkptr=0x%x next=0x%x inx=%d\n", (unsigned)walkptr, + Dmsg3(100, "new walkptr=0x%x next=0x%x inx=%d\n", (unsigned)walkptr, (unsigned)(walkptr->next), walk_index-1); } } @@ -254,7 +251,7 @@ void *htable::first() while (!walkptr && walk_index < buckets) { walkptr = table[walk_index++]; /* go to next bucket */ if (walkptr) { - Dmsg3(100, "first new walkptr=0x%x next=0x%x inx=%d\n", (unsigned)walkptr, + Dmsg3(100, "first new walkptr=0x%x next=0x%x inx=%d\n", (unsigned)walkptr, (unsigned)(walkptr->next), walk_index-1); } } diff --git a/bacula/src/lib/htable.h b/bacula/src/lib/htable.h index 1573f22338..cb18c8fd30 100644 --- a/bacula/src/lib/htable.h +++ b/bacula/src/lib/htable.h @@ -3,7 +3,7 @@ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2003-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -32,9 +32,9 @@ * Loop var through each member of table */ #define foreach_htable(var, tbl) \ - for(((void *)(var))=(tbl)->first(); \ - (var); \ - ((void *)(var))=(tbl)->next()) + for((*((void **)&(var))=(void *)((tbl)->first())); \ + (var); \ + (*((void **)&(var))=(void *)((tbl)->next()))) struct hlink { void *next; /* next hash item */ diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index 5b61b5da92..6b95c32167 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -9,7 +9,7 @@ * */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -53,7 +53,7 @@ void init_last_jobs_list() if (!last_jobs) { last_jobs = New(dlist(job_entry, &job_entry->link)); if ((errstat=rwl_init(&lock)) != 0) { - Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"), + Emsg1(M_ABORT, 0, _("Unable to initialize jcr_chain lock. ERR=%s\n"), strerror(errstat)); } } @@ -92,7 +92,7 @@ void read_last_jobs_list(int fd, uint64_t addr) } for ( ; num; num--) { if (read(fd, &job, sizeof(job)) != sizeof(job)) { - Dmsg1(000, "Read job entry. ERR=%s\n", strerror(errno)); + Dmsg1(000, "Read job entry. ERR=%s\n", strerror(errno)); return; } if (job.JobId > 0) { @@ -124,12 +124,12 @@ uint64_t write_last_jobs_list(int fd, uint64_t addr) /* First record is number of entires */ num = last_jobs->size(); if (write(fd, &num, sizeof(num)) != sizeof(num)) { - Dmsg1(000, "Error writing num_items: ERR=%s\n", strerror(errno)); + Dmsg1(000, "Error writing num_items: ERR=%s\n", strerror(errno)); return 0; } foreach_dlist(je, last_jobs) { if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) { - Dmsg1(000, "Error writing job: ERR=%s\n", strerror(errno)); + Dmsg1(000, "Error writing job: ERR=%s\n", strerror(errno)); return 0; } } @@ -188,7 +188,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) MQUEUE_ITEM *item = NULL; struct sigaction sigtimer; - Dmsg0(400, "Enter new_jcr\n"); + Dmsg0(3400, "Enter new_jcr\n"); jcr = (JCR *)malloc(size); memset(jcr, 0, size); jcr->my_thread_id = pthread_self(); @@ -234,7 +234,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) */ static void remove_jcr(JCR *jcr) { - Dmsg0(400, "Enter remove_jcr\n"); + Dmsg0(3400, "Enter remove_jcr\n"); if (!jcr) { Emsg0(M_ABORT, 0, "NULL jcr.\n"); } @@ -246,7 +246,7 @@ static void remove_jcr(JCR *jcr) if (jcr->next) { jcr->next->prev = jcr->prev; } - Dmsg0(400, "Leave remove_jcr\n"); + Dmsg0(3400, "Leave remove_jcr\n"); } /* @@ -342,14 +342,14 @@ static void free_common_jcr(JCR *jcr) #ifdef DEBUG void b_free_jcr(const char *file, int line, JCR *jcr) { - Dmsg3(400, "Enter free_jcr 0x%x from %s:%d\n", jcr, file, line); + Dmsg3(3400, "Enter free_jcr 0x%x from %s:%d\n", jcr, file, line); #else void free_jcr(JCR *jcr) { - Dmsg1(400, "Enter free_jcr 0x%x\n", jcr); + Dmsg1(3400, "Enter free_jcr 0x%x\n", jcr); #endif @@ -360,10 +360,10 @@ void free_jcr(JCR *jcr) Emsg2(M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"), jcr->use_count, jcr->JobId); } - Dmsg3(400, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId); + Dmsg3(3400, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId); if (jcr->use_count > 0) { /* if in use */ unlock_jcr_chain(); - Dmsg2(400, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); return; } remove_jcr(jcr); /* remove Jcr from chain */ @@ -371,13 +371,13 @@ void free_jcr(JCR *jcr) job_end_pop(jcr); /* pop and call hooked routines */ - Dmsg1(400, "End job=%d\n", jcr->JobId); + Dmsg1(3400, "End job=%d\n", jcr->JobId); if (jcr->daemon_free_jcr) { jcr->daemon_free_jcr(jcr); /* call daemon free routine */ } free_common_jcr(jcr); close_msg(NULL); /* flush any daemon messages */ - Dmsg0(400, "Exit free_jcr\n"); + Dmsg0(3400, "Exit free_jcr\n"); } @@ -388,7 +388,7 @@ void free_jcr(JCR *jcr) void free_locked_jcr(JCR *jcr) { jcr->use_count--; /* decrement use count */ - Dmsg2(400, "Dec free_locked_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "Dec free_locked_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); if (jcr->use_count > 0) { /* if in use */ return; } @@ -414,7 +414,7 @@ JCR *get_jcr_by_id(uint32_t JobId) P(jcr->mutex); jcr->use_count++; V(jcr->mutex); - Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); break; } } @@ -438,7 +438,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime) P(jcr->mutex); jcr->use_count++; V(jcr->mutex); - Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); break; } } @@ -469,7 +469,7 @@ JCR *get_jcr_by_partial_name(char *Job) P(jcr->mutex); jcr->use_count++; V(jcr->mutex); - Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); break; } } @@ -497,7 +497,7 @@ JCR *get_jcr_by_full_name(char *Job) P(jcr->mutex); jcr->use_count++; V(jcr->mutex); - Dmsg2(400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); break; } } @@ -538,7 +538,7 @@ void lock_jcr_chain() { int errstat; #ifdef TRACE_JCR_CHAIN - Dmsg3(400, "Lock jcr chain %d from %s:%d\n", ++lock_count, + Dmsg3(3400, "Lock jcr chain %d from %s:%d\n", ++lock_count, fname, line); #endif if ((errstat=rwl_writelock(&lock)) != 0) { @@ -558,7 +558,7 @@ void unlock_jcr_chain() { int errstat; #ifdef TRACE_JCR_CHAIN - Dmsg3(400, "Unlock jcr chain %d from %s:%d\n", lock_count--, + Dmsg3(3400, "Unlock jcr chain %d from %s:%d\n", lock_count--, fname, line); #endif if ((errstat=rwl_writeunlock(&lock)) != 0) { @@ -581,7 +581,7 @@ JCR *get_next_jcr(JCR *prev_jcr) P(jcr->mutex); jcr->use_count++; V(jcr->mutex); - Dmsg2(400, "Inc get_next_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); + Dmsg2(3400, "Inc get_next_jcr 0x%x use_count=%d\n", jcr, jcr->use_count); } return jcr; } @@ -606,7 +606,7 @@ static void jcr_timeout_check(watchdog_t *self) BSOCK *fd; time_t timer_start; - Dmsg0(400, "Start JCR timeout checks\n"); + Dmsg0(3400, "Start JCR timeout checks\n"); /* Walk through all JCRs checking if any one is * blocked for more than specified max time. @@ -657,7 +657,7 @@ static void jcr_timeout_check(watchdog_t *self) } unlock_jcr_chain(); - Dmsg0(400, "Finished JCR timeout checks\n"); + Dmsg0(3400, "Finished JCR timeout checks\n"); } /* diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index b1e653cce4..d86280278c 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -115,7 +115,7 @@ void my_name_is(int argc, char *argv[], const char *name) if (argc>0 && argv && argv[0]) { /* strip trailing filename and save exepath */ for (l=p=argv[0]; *p; p++) { - if (*p == '/') { + if (*p == '/') { l = p; /* set pos of last slash */ } } @@ -125,7 +125,7 @@ void my_name_is(int argc, char *argv[], const char *name) l = argv[0]; #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) /* On Windows allow c: junk */ - if (l[1] == ':') { + if (l[1] == ':') { l += 2; } #endif @@ -297,7 +297,7 @@ void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mai for (d=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", + Dmsg4(850, "Add to existing d=%x msgtype=%d destcode=%d where=%s\n", d, msg_type, dest_code, NPRT(where)); set_bit(msg_type, d->msg_types); set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */ @@ -317,7 +317,7 @@ void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mai if (mail_cmd) { d->mail_cmd = bstrdup(mail_cmd); } - Dmsg5(200, "add new d=%x msgtype=%d destcode=%d where=%s mailcmd=%s\n", + Dmsg5(850, "add new d=%x msgtype=%d destcode=%d where=%s mailcmd=%s\n", d, msg_type, dest_code, NPRT(where), NPRT(d->mail_cmd)); msg->dest_chain = d; } @@ -332,14 +332,14 @@ void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where) DEST *d; for (d=msg->dest_chain; d; d=d->next) { - Dmsg2(200, "Remove_msg_dest d=%x where=%s\n", d, NPRT(d->where)); + Dmsg2(850, "Remove_msg_dest d=%x where=%s\n", d, NPRT(d->where)); if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) && ((where == NULL && d->where == NULL) || (strcmp(where, d->where) == 0))) { - Dmsg3(200, "Found for remove d=%x msgtype=%d destcode=%d\n", + Dmsg3(850, "Found for remove d=%x msgtype=%d destcode=%d\n", d, msg_type, dest_code); clear_bit(msg_type, d->msg_types); - Dmsg0(200, "Return rem_msg_dest\n"); + Dmsg0(850, "Return rem_msg_dest\n"); return; } } @@ -358,7 +358,7 @@ static void make_unique_mail_filename(JCR *jcr, POOLMEM *&name, DEST *d) Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name, my_name, (int)(long)d); } - Dmsg1(200, "mailname=%s\n", name); + Dmsg1(850, "mailname=%s\n", name); } /* @@ -401,7 +401,7 @@ void close_msg(JCR *jcr) POOLMEM *cmd, *line; int len, stat; - Dmsg1(350, "Close_msg jcr=0x%x\n", jcr); + Dmsg1(850, "Close_msg jcr=0x%x\n", jcr); if (jcr == NULL) { /* NULL -> global chain */ msgs = daemon_msgs; @@ -413,7 +413,7 @@ void close_msg(JCR *jcr) if (msgs == NULL) { return; } - Dmsg1(350, "===Begin close msg resource at 0x%x\n", msgs); + Dmsg1(850, "===Begin close msg resource at 0x%x\n", msgs); cmd = get_pool_memory(PM_MESSAGE); for (d=msgs->dest_chain; d; ) { if (d->fd) { @@ -426,7 +426,7 @@ void close_msg(JCR *jcr) break; case MD_MAIL: case MD_MAIL_ON_ERROR: - Dmsg0(350, "Got MD_MAIL or MD_MAIL_ON_ERROR\n"); + Dmsg0(850, "Got MD_MAIL or MD_MAIL_ON_ERROR\n"); if (!d->fd) { break; } @@ -436,10 +436,10 @@ void close_msg(JCR *jcr) } if (!(bpipe=open_mail_pipe(jcr, cmd, d))) { - Pmsg0(000, "open mail pipe failed.\n"); + Pmsg0(000, "open mail pipe failed.\n"); goto rem_temp_file; } - Dmsg0(350, "Opened mail pipe\n"); + Dmsg0(850, "Opened mail pipe\n"); len = d->max_len+10; line = get_memory(len); rewind(d->fd); @@ -448,18 +448,18 @@ void close_msg(JCR *jcr) } if (!close_wpipe(bpipe)) { /* close write pipe sending mail */ berrno be; - Pmsg1(000, "close error: ERR=%s\n", be.strerror()); + Pmsg1(000, "close error: ERR=%s\n", be.strerror()); } /* - * Since we are closing all messages, before "recursing" + * Since we are closing all messages, before "recursing" * make sure we are not closing the daemon messages, otherwise * kaboom. */ if (msgs != daemon_msgs) { /* read what mail prog returned -- should be nothing */ while (fgets(line, len, bpipe->rfd)) { - Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line); + Jmsg1(jcr, M_INFO, 0, _("Mail prog: %s"), line); } } @@ -467,10 +467,10 @@ void close_msg(JCR *jcr) if (stat != 0 && msgs != daemon_msgs) { berrno be; be.set_errno(stat); - Dmsg1(350, "Calling emsg. CMD=%s\n", cmd); - Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n" - "CMD=%s\n" - "ERR=%s\n"), cmd, be.strerror()); + Dmsg1(850, "Calling emsg. CMD=%s\n", cmd); + Jmsg2(jcr, M_ERROR, 0, _("Mail program terminated in error.\n" + "CMD=%s\n" + "ERR=%s\n"), cmd, be.strerror()); } free_memory(line); rem_temp_file: @@ -479,7 +479,7 @@ rem_temp_file: unlink(d->mail_filename); free_pool_memory(d->mail_filename); d->mail_filename = NULL; - Dmsg0(350, "end mail or mail on error\n"); + Dmsg0(850, "end mail or mail on error\n"); break; default: break; @@ -489,14 +489,14 @@ rem_temp_file: d = d->next; /* point to next buffer */ } free_pool_memory(cmd); - Dmsg0(350, "Done walking message chain.\n"); + Dmsg0(850, "Done walking message chain.\n"); if (jcr) { free_msgs_res(msgs); msgs = NULL; } else { V(mutex); } - Dmsg0(350, "===End close msg resource\n"); + Dmsg0(850, "===End close msg resource\n"); } /* @@ -532,7 +532,7 @@ void free_msgs_res(MSGS *msgs) */ void term_msg() { - Dmsg0(300, "Enter term_msg\n"); + Dmsg0(850, "Enter term_msg\n"); close_msg(NULL); /* close global chain */ free_msgs_res(daemon_msgs); /* free the resources */ daemon_msgs = NULL; @@ -570,7 +570,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) MSGS *msgs; BPIPE *bpipe; - Dmsg2(800, "Enter dispatch_msg type=%d msg=%s\n", type, msg); + Dmsg2(850, "Enter dispatch_msg type=%d msg=%s\n", type, msg); /* * Most messages are prefixed by a date and time. If mtime is @@ -601,7 +601,7 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) /* If we don't exit on error, error messages are parsed by UA */ if (exit_on_error) { - MessageBox(NULL, msg, "Bacula", MB_OK); + MessageBox(NULL, msg, "Bacula", MB_OK); } #endif #endif @@ -619,10 +619,10 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) if (bit_is_set(type, d->msg_types)) { switch (d->dest_code) { case MD_CONSOLE: - Dmsg1(800, "CONSOLE for following msg: %s", msg); + Dmsg1(850, "CONSOLE for following msg: %s", msg); if (!con_fd) { - con_fd = fopen(con_fname, "a+"); - Dmsg0(800, "Console file not open.\n"); + con_fd = fopen(con_fname, "a+"); + Dmsg0(850, "Console file not open.\n"); } if (con_fd) { Pw(con_lock); /* get write lock on console message file */ @@ -633,11 +633,11 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) len = strlen(msg); if (len > 0) { fwrite(msg, len, 1, con_fd); - if (msg[len-1] != '\n') { - fwrite("\n", 2, 1, con_fd); + if (msg[len-1] != '\n') { + fwrite("\n", 2, 1, con_fd); } } else { - fwrite("\n", 2, 1, con_fd); + fwrite("\n", 2, 1, con_fd); } fflush(con_fd); console_msg_pending = TRUE; @@ -645,14 +645,14 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) } break; case MD_SYSLOG: - Dmsg1(800, "SYSLOG for collowing msg: %s\n", msg); + Dmsg1(850, "SYSLOG for collowing msg: %s\n", msg); /* * We really should do an openlog() here. */ - syslog(LOG_DAEMON|LOG_ERR, "%s", msg); + syslog(LOG_DAEMON|LOG_ERR, "%s", msg); break; case MD_OPERATOR: - Dmsg1(800, "OPERATOR for following msg: %s\n", msg); + Dmsg1(850, "OPERATOR for following msg: %s\n", msg); mcmd = get_pool_memory(PM_MESSAGE); if ((bpipe=open_mail_pipe(jcr, mcmd, d))) { int stat; @@ -663,24 +663,24 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) if (stat != 0) { berrno be; be.set_errno(stat); - Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n" - "CMD=%s\n" - "ERR=%s\n"), mcmd, be.strerror()); + Qmsg2(jcr, M_ERROR, 0, _("Operator mail program terminated in error.\n" + "CMD=%s\n" + "ERR=%s\n"), mcmd, be.strerror()); } } free_pool_memory(mcmd); break; case MD_MAIL: case MD_MAIL_ON_ERROR: - Dmsg1(800, "MAIL for following msg: %s", msg); + Dmsg1(850, "MAIL for following msg: %s", msg); if (!d->fd) { POOLMEM *name = get_pool_memory(PM_MESSAGE); make_unique_mail_filename(jcr, name, d); - d->fd = fopen(name, "w+"); + d->fd = fopen(name, "w+"); if (!d->fd) { berrno be; d->fd = stdout; - Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", name, + Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", name, be.strerror()); d->fd = NULL; free_pool_memory(name); @@ -696,13 +696,13 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) fputs(msg, d->fd); break; case MD_FILE: - Dmsg1(800, "FILE for following msg: %s", msg); + Dmsg1(850, "FILE for following msg: %s", msg); if (!d->fd) { - d->fd = fopen(d->where, "w+"); + d->fd = fopen(d->where, "w+"); if (!d->fd) { berrno be; d->fd = stdout; - Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where, + Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where, be.strerror()); d->fd = NULL; break; @@ -712,13 +712,13 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) fputs(msg, d->fd); break; case MD_APPEND: - Dmsg1(800, "APPEND for following msg: %s", msg); + Dmsg1(850, "APPEND for following msg: %s", msg); if (!d->fd) { - d->fd = fopen(d->where, "a"); + d->fd = fopen(d->where, "a"); if (!d->fd) { berrno be; d->fd = stdout; - Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where, + Qmsg2(jcr, M_ERROR, 0, "fopen %s failed: ERR=%s\n", d->where, be.strerror()); d->fd = NULL; break; @@ -728,21 +728,21 @@ void dispatch_message(JCR *jcr, int type, time_t mtime, char *msg) fputs(msg, d->fd); break; case MD_DIRECTOR: - Dmsg1(800, "DIRECTOR for following msg: %s", msg); + Dmsg1(850, "DIRECTOR for following msg: %s", msg); if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) { - bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s", + bnet_fsend(jcr->dir_bsock, "Jmsg Job=%s type=%d level=%d %s", jcr->Job, type, mtime, msg); } break; case MD_STDOUT: - Dmsg1(800, "STDOUT for following msg: %s", msg); + Dmsg1(850, "STDOUT for following msg: %s", msg); if (type != M_ABORT && type != M_ERROR_TERM) { /* already printed */ fputs(dt, stdout); fputs(msg, stdout); } break; case MD_STDERR: - Dmsg1(800, "STDERR for following msg: %s", msg); + Dmsg1(850, "STDERR for following msg: %s", msg); fputs(dt, stderr); fputs(msg, stderr); break; @@ -783,9 +783,9 @@ d_msg(const char *file, int line, int level, const char *fmt,...) /* visual studio passes the whole path to the file as well * which makes for very long lines */ - const char *f = strrchr(file, '\\'); + const char *f = strrchr(file, '\\'); if (f) file = f + 1; - len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); } else { len = 0; } @@ -797,13 +797,13 @@ d_msg(const char *file, int line, int level, const char *fmt,...) va_end(arg_ptr); /* - * Used the "trace on" command in the console to turn on - * output to the trace file. "trace off" will close the file. + * Used the "trace on" command in the console to turn on + * output to the trace file. "trace off" will close the file. */ if (trace) { if (!trace_fd) { - bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory ? working_directory : "."); - trace_fd = fopen(buf, "a+"); + bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory ? working_directory : "."); + trace_fd = fopen(buf, "a+"); } if (trace_fd) { fputs(buf, trace_fd); @@ -895,13 +895,13 @@ t_msg(const char *file, int line, int level, const char *fmt,...) if (level <= debug_level) { if (!trace_fd) { - bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory); - trace_fd = fopen(buf, "a+"); + bsnprintf(buf, sizeof(buf), "%s/bacula.trace", working_directory); + trace_fd = fopen(buf, "a+"); } #ifdef FULL_LOCATION if (details) { - len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line); } else { len = 0; } @@ -951,15 +951,15 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...) break; case M_FATAL: if (level == -1) /* skip details */ - len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error because: ", my_name); + len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error because: ", my_name); else - len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error at %s:%d because:\n", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: Fatal Error at %s:%d because:\n", my_name, file, line); break; case M_ERROR: if (level == -1) /* skip details */ - len = bsnprintf(buf, sizeof(buf), "%s: ERROR: ", my_name); + len = bsnprintf(buf, sizeof(buf), "%s: ERROR: ", my_name); else - len = bsnprintf(buf, sizeof(buf), "%s: ERROR in %s:%d ", my_name, file, line); + len = bsnprintf(buf, sizeof(buf), "%s: ERROR in %s:%d ", my_name, file, line); break; case M_WARNING: len = bsnprintf(buf, sizeof(buf), "%s: Warning: ", my_name); @@ -1002,7 +1002,7 @@ Jmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...) const char *job; - Dmsg1(800, "Enter Jmsg type=%d\n", type); + Dmsg1(850, "Enter Jmsg type=%d\n", type); /* Special case for the console, which has a dir_bsock and JobId==0, * in that case, we send the message directly back to the diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index f79e1b8fa2..f8670f67b9 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -176,7 +176,7 @@ void init_resource(int type, RES_ITEM *items, int pass) for (i=0; items[i].name; i++) { Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name, - (items[i].flags & ITEM_DEFAULT) ? "yes" : "no", + (items[i].flags & ITEM_DEFAULT) ? "yes" : "no", items[i].default_value); if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) { if (items[i].handler == store_yesno) { @@ -196,7 +196,7 @@ void init_resource(int type, RES_ITEM *items, int pass) } /* If this triggers, take a look at lib/parse_conf.h */ if (i >= MAX_RES_ITEMS) { - Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]); + Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]); } } } @@ -236,25 +236,25 @@ void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass) token = lex_get_token(lc, T_NAME); /* scan destination */ dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2); if (dest[0] != 0) { - pm_strcat(dest, " "); /* separate multiple destinations with space */ + pm_strcat(dest, " "); /* separate multiple destinations with space */ dest_len++; } pm_strcat(dest, lc->str); dest_len += lc->str_len; - Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest)); + Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest)); token = lex_get_token(lc, T_SKIP_EOL); if (token == T_COMMA) { continue; /* get another destination */ } if (token != T_EQUALS) { - scan_err1(lc, _("expected an =, got: %s"), lc->str); + scan_err1(lc, _("expected an =, got: %s"), lc->str); } break; } - Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd)); + Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd)); scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd); free_pool_memory(dest); - Dmsg0(900, "done with dest codes\n"); + Dmsg0(900, "done with dest codes\n"); break; case MD_FILE: /* file */ case MD_APPEND: /* append */ @@ -264,17 +264,17 @@ void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass) pm_strcpy(dest, lc->str); dest_len = lc->str_len; token = lex_get_token(lc, T_SKIP_EOL); - Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest)); + Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest)); if (token != T_EQUALS) { - scan_err1(lc, _("expected an =, got: %s"), lc->str); + scan_err1(lc, _("expected an =, got: %s"), lc->str); } scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL); free_pool_memory(dest); - Dmsg0(900, "done with dest codes\n"); + Dmsg0(900, "done with dest codes\n"); break; default: - scan_err1(lc, _("Unknown item code: %d\n"), item->code); + scan_err1(lc, _("Unknown item code: %d\n"), item->code); break; } } @@ -313,7 +313,7 @@ static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd } } if (!found) { - scan_err1(lc, _("message type: %s not found"), str); + scan_err1(lc, _("message type: %s not found"), str); /* NOT REACHED */ } @@ -421,7 +421,7 @@ void store_password(LEX *lc, RES_ITEM *item, int index, int pass) MD5Update(&md5c, (unsigned char *) (lc->str), lc->str_len); MD5Final(signature, &md5c); for (i = j = 0; i < sizeof(signature); i++) { - sprintf(&sig[j], "%02x", signature[i]); + sprintf(&sig[j], "%02x", signature[i]); j += 2; } *(item->value) = bstrdup(sig); @@ -443,11 +443,11 @@ void store_res(LEX *lc, RES_ITEM *item, int index, int pass) if (pass == 2) { res = GetResWithName(item->code, lc->str); if (res == NULL) { - scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"), + scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"), lc->str, lc->line_no, lc->line); } if (*(item->value)) { - scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"), + scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"), item->name, lc->line_no, lc->line); } *(item->value) = (char *)res; @@ -457,7 +457,7 @@ void store_res(LEX *lc, RES_ITEM *item, int index, int pass) } /* - * Store a resource in an alist. default_value indicates how many + * Store a resource pointer in an alist. default_value indicates how many * times this routine can be called -- i.e. how many alists * there are. * If we are in pass 2, do a lookup of the @@ -471,24 +471,35 @@ void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass) alist *list; if (pass == 2) { - /* Find empty place to store this directive */ - while ((item->value)[i] != NULL && i++ < count) { } - if (i >= count) { - scan_err3(lc, _("Too many Storage directives. Max. is %d. line %d: %s\n"), - count, lc->line_no, lc->line); + if (count == 0) { /* always store in item->value */ + i = 0; + if ((item->value)[i] == NULL) { + list = New(alist(10, not_owned_by_alist)); + } else { + list = (alist *)(item->value)[i]; + } + } else { + /* Find empty place to store this directive */ + while ((item->value)[i] != NULL && i++ < count) { } + if (i >= count) { + scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"), + lc->str, count, lc->line_no, lc->line); + } + list = New(alist(10, not_owned_by_alist)); } - list = New(alist(10, not_owned_by_alist)); for (;;) { lex_get_token(lc, T_NAME); /* scan next item */ res = GetResWithName(item->code, lc->str); if (res == NULL) { - scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"), - lc->str, lc->line_no, lc->line); + scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"), + item->name, lc->line_no, lc->line); } + Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n", + res, list, list->size(), i, item->name); list->append(res); (item->value)[i] = (char *)list; - if (lc->ch != ',') { /* if no other item follows */ + if (lc->ch != ',') { /* if no other item follows */ break; /* get out */ } lex_get_token(lc, T_ALL); /* eat comma */ @@ -517,16 +528,16 @@ void store_defs(LEX *lc, RES_ITEM *item, int index, int pass) Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str); res = GetResWithName(item->code, lc->str); if (res == NULL) { - scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"), + scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"), lc->str, lc->line_no, lc->line); } /* for each item not set, we copy the field from res */ #ifdef xxx for (int i=0; item->name;; i++, item++) { if (bit_is_set(i, res->item_present)) { - Dmsg2(900, "Item %d is present in %s\n", i, res->name); + Dmsg2(900, "Item %d is present in %s\n", i, res->name); } else { - Dmsg2(900, "Item %d is not present in %s\n", i, res->name); + Dmsg2(900, "Item %d is not present in %s\n", i, res->name); } } /* ***FIXME **** add code */ @@ -579,7 +590,7 @@ void store_size(LEX *lc, RES_ITEM *item, int index, int pass) case T_IDENTIFIER: case T_UNQUOTED_STRING: if (!size_to_uint64(lc->str, lc->str_len, &uvalue)) { - scan_err1(lc, _("expected a size number, got: %s"), lc->str); + scan_err1(lc, _("expected a size number, got: %s"), lc->str); } *(uint64_t *)(item->value) = uvalue; break; @@ -617,7 +628,7 @@ void store_time(LEX *lc, RES_ITEM *item, int index, int pass) } } if (!duration_to_utime(period, &utime)) { - scan_err1(lc, _("expected a time period, got: %s"), period); + scan_err1(lc, _("expected a time period, got: %s"), period); } *(utime_t *)(item->value) = utime; break; @@ -654,7 +665,7 @@ void b_LockRes(const char *file, int line) { int errstat; #ifdef TRACE_RES - Dmsg4(000, "LockRes %d,%d at %s:%d\n", res_locked, res_lock.w_active, + Pmsg4(000, "LockRes %d,%d at %s:%d\n", res_locked, res_lock.w_active, file, line); #endif if ((errstat=rwl_writelock(&res_lock)) != 0) { @@ -669,7 +680,7 @@ void b_UnlockRes(const char *file, int line) int errstat; res_locked--; #ifdef TRACE_RES - Dmsg4(000, "UnLockRes %d,%d at %s:%d\n", res_locked, res_lock.w_active, + Pmsg4(000, "UnLockRes %d,%d at %s:%d\n", res_locked, res_lock.w_active, file, line); #endif if ((errstat=rwl_writeunlock(&res_lock)) != 0) { @@ -758,14 +769,14 @@ parse_config(const char *cf, int exit_on_error) return 0; } while ((token=lex_get_token(lc, T_ALL)) != T_EOF) { - Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token)); + Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token)); switch (state) { case p_none: if (token == T_EOL) { break; } if (token != T_IDENTIFIER) { - scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str); + scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } @@ -778,7 +789,7 @@ parse_config(const char *cf, int exit_on_error) break; } if (state == p_none) { - scan_err1(lc, _("expected resource name, got: %s"), lc->str); + scan_err1(lc, _("expected resource name, got: %s"), lc->str); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } @@ -790,7 +801,7 @@ parse_config(const char *cf, int exit_on_error) break; case T_IDENTIFIER: if (level != 1) { - scan_err1(lc, _("not in resource definition: %s"), lc->str); + scan_err1(lc, _("not in resource definition: %s"), lc->str); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } @@ -800,14 +811,14 @@ parse_config(const char *cf, int exit_on_error) * scan for = after the keyword */ if (!(items[i].flags & ITEM_NO_EQUALS)) { token = lex_get_token(lc, T_SKIP_EOL); - Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); + Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); if (token != T_EQUALS) { - scan_err1(lc, _("expected an equals, got: %s"), lc->str); + scan_err1(lc, _("expected an equals, got: %s"), lc->str); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } } - Dmsg1(900, "calling handler for %s\n", items[i].name); + Dmsg1(900, "calling handler for %s\n", items[i].name); /* Call item handler */ items[i].handler(lc, &items[i], i, pass); i = -1; @@ -815,10 +826,10 @@ parse_config(const char *cf, int exit_on_error) } } if (i >= 0) { - Dmsg2(900, "level=%d id=%s\n", level, lc->str); - Dmsg1(900, "Keyword = %s\n", lc->str); - scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n" - "Perhaps you left the trailing brace off of the previous resource."), lc->str); + Dmsg2(900, "level=%d id=%s\n", level, lc->str); + Dmsg1(900, "Keyword = %s\n", lc->str); + scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n" + "Perhaps you left the trailing brace off of the previous resource."), lc->str); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } @@ -827,7 +838,7 @@ parse_config(const char *cf, int exit_on_error) case T_EOB: level--; state = p_none; - Dmsg0(900, "T_EOB => define new resource\n"); + Dmsg0(900, "T_EOB => define new resource\n"); save_resource(res_type, items, pass); /* save resource */ break; @@ -835,20 +846,20 @@ parse_config(const char *cf, int exit_on_error) break; default: - scan_err2(lc, _("unexpected token %d %s in resource definition"), + scan_err2(lc, _("unexpected token %d %s in resource definition"), token, lex_tok_to_str(token)); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } break; default: - scan_err1(lc, _("Unknown parser state %d\n"), state); + scan_err1(lc, _("Unknown parser state %d\n"), state); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } } if (state != p_none) { - scan_err0(lc, _("End of conf file reached with unclosed resource.")); + scan_err0(lc, _("End of conf file reached with unclosed resource.")); set_exit_on_error(1); /* Never reached if exit_on_error == 1 */ return 0; } diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index d1cc5cc99b..f73f1a395e 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -4,7 +4,7 @@ * Version $Id$ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -73,11 +73,11 @@ bool bnet_sig (BSOCK *bs, int sig); int bnet_ssl_server (BSOCK *bsock, char *password, int ssl_need, int ssl_has); int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need); BSOCK * bnet_connect (JCR *jcr, int retry_interval, - int max_retry_time, const char *name, char *host, char *service, - int port, int verbose); + int max_retry_time, const char *name, char *host, char *service, + int port, int verbose); void bnet_close (BSOCK *bsock); BSOCK * init_bsock (JCR *jcr, int sockfd, const char *who, const char *ip, - int port, struct sockaddr *client_addr); + int port, struct sockaddr *client_addr); BSOCK * dup_bsock (BSOCK *bsock); void term_bsock (BSOCK *bsock); const char *bnet_strerror (BSOCK *bsock); @@ -102,7 +102,7 @@ int close_bpipe(BPIPE *bpipe); int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need); int cram_md5_auth(BSOCK *bs, char *password, int ssl_need); void hmac_md5(uint8_t* text, int text_len, uint8_t* key, - int key_len, uint8_t *hmac); + int key_len, uint8_t *hmac); /* crc32.c */ @@ -117,6 +117,7 @@ int64_t str_to_int64(char *str); char * edit_uint64_with_commas (uint64_t val, char *buf); char * add_commas (char *val, char *buf); char * edit_uint64 (uint64_t val, char *buf); +char * edit_int64 (int64_t val, char *buf); int duration_to_utime (char *str, utime_t *value); int size_to_uint64(char *str, int str_len, uint64_t *rtn_value); char *edit_utime (utime_t val, char *buf, int buf_len); @@ -160,7 +161,7 @@ void set_exit_on_error (int value); /* bnet_server.c */ void bnet_thread_server(dlist *addr, int max_clients, workq_t *client_wq, - void *handle_client_request(void *bsock)); + void *handle_client_request(void *bsock)); void bnet_stop_thread_server(pthread_t tid); void bnet_server (int port, void handle_client_request(BSOCK *bsock)); int net_connect (int port); @@ -191,9 +192,9 @@ bool skip_nonspaces (char **msg); int fstrsch (const char *a, const char *b); char *next_arg(char **s); int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc, - char **argk, char **argv, int max_args); + char **argk, char **argv, int max_args); void split_path_and_filename(const char *fname, POOLMEM **path, - int *pnl, POOLMEM **file, int *fnl); + int *pnl, POOLMEM **file, int *fnl); int bsscanf(const char *buf, const char *fmt, ...); diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c index 70d567fc33..1e54ec95af 100644 --- a/bacula/src/lib/scan.c +++ b/bacula/src/lib/scan.c @@ -135,7 +135,7 @@ char *next_arg(char **s) for (p=*s; *p && B_ISSPACE(*p); ) { p++; } - Dmsg1(400, "Next arg=%s\n", p); + Dmsg1(900, "Next arg=%s\n", p); for (n = q = p; *p ; ) { if (*p == '\\') { p++; @@ -164,7 +164,7 @@ char *next_arg(char **s) } *q = 0; *s = p; - Dmsg2(400, "End arg=%s next=%s\n", n, p); + Dmsg2(900, "End arg=%s next=%s\n", n, p); return n; } @@ -213,9 +213,9 @@ int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc, if (p) { *p++ = 0; /* terminate keyword and point to value */ /* Unquote quoted values */ - if (*p == '"') { - for (n = q = ++p; *p && *p != '"'; ) { - if (*p == '\\') { + if (*p == '"') { + for (n = q = ++p; *p && *p != '"'; ) { + if (*p == '\\') { p++; } *q++ = *p++; @@ -314,11 +314,11 @@ int bsscanf(const char *buf, const char *fmt, ...) // Dmsg1(000, "Got %% nxt=%c\n", *fmt); switch_top: switch (*fmt++) { - case 'u': - case 'd': + case 'u': + case 'd': value = 0; while (B_ISDIGIT(*buf)) { - value = B_TIMES10(value) + *buf++ - '0'; + value = B_TIMES10(value) + *buf++ - '0'; } vp = (void *)va_arg(ap, void *); // Dmsg2(000, "val=%lld at 0x%lx\n", value, (long unsigned)vp); @@ -332,28 +332,28 @@ switch_top: count++; l = 0; break; - case 'l': + case 'l': // Dmsg0(000, "got l\n"); l = 1; - if (*fmt == 'l') { + if (*fmt == 'l') { l++; fmt++; } - if (*fmt == 'd' || *fmt == 'u') { + if (*fmt == 'd' || *fmt == 'u') { goto switch_top; } // Dmsg1(000, "fmt=%c !=d,u\n", *fmt); error = true; break; - case 'q': + case 'q': l = 2; - if (*fmt == 'd' || *fmt == 'u') { + if (*fmt == 'd' || *fmt == 'u') { goto switch_top; } // Dmsg1(000, "fmt=%c !=d,u\n", *fmt); error = true; break; - case 's': + case 's': // Dmsg1(000, "Store string max_len=%d\n", max_len); cp = (char *)va_arg(ap, char *); while (*buf && !B_ISSPACE(*buf) && max_len-- > 0) { @@ -363,13 +363,13 @@ switch_top: count++; max_len = BIG; break; - case 'c': + case 'c': cp = (char *)va_arg(ap, char *); *cp = *buf++; count++; break; - case '%': - if (*buf++ != '%') { + case '%': + if (*buf++ != '%') { error = true; } break; @@ -377,10 +377,10 @@ switch_top: fmt--; max_len = 0; while (B_ISDIGIT(*fmt)) { - max_len = B_TIMES10(max_len) + *fmt++ - '0'; + max_len = B_TIMES10(max_len) + *fmt++ - '0'; } // Dmsg1(000, "Default max_len=%d\n", max_len); - if (*fmt == 's') { + if (*fmt == 's') { goto switch_top; } // Dmsg1(000, "Default c=%c\n", *fmt); diff --git a/bacula/src/lib/watchdog.c b/bacula/src/lib/watchdog.c index ec6bc848a5..a08e51ed55 100755 --- a/bacula/src/lib/watchdog.c +++ b/bacula/src/lib/watchdog.c @@ -68,7 +68,7 @@ int start_watchdog(void) if (wd_is_init) { return 0; } - Dmsg0(400, "Initialising NicB-hacked watchdog thread\n"); + Dmsg0(800, "Initialising NicB-hacked watchdog thread\n"); watchdog_time = time(NULL); if ((errstat=rwl_init(&lock)) != 0) { @@ -180,8 +180,8 @@ bool register_watchdog(watchdog_t *wd) wd_lock(); wd->next_fire = watchdog_time + wd->interval; wd_queue->append(wd); - Dmsg3(400, "Registered watchdog %p, interval %d%s\n", - wd, wd->interval, wd->one_shot ? " one shot" : ""); + Dmsg3(800, "Registered watchdog %p, interval %d%s\n", + wd, wd->interval, wd->one_shot ? " one shot" : ""); wd_unlock(); ping_watchdog(); @@ -201,7 +201,7 @@ bool unregister_watchdog(watchdog_t *wd) foreach_dlist(p, wd_queue) { if (wd == p) { wd_queue->remove(wd); - Dmsg1(400, "Unregistered watchdog %p\n", wd); + Dmsg1(800, "Unregistered watchdog %p\n", wd); ok = true; goto get_out; } @@ -210,13 +210,13 @@ bool unregister_watchdog(watchdog_t *wd) foreach_dlist(p, wd_inactive) { if (wd == p) { wd_inactive->remove(wd); - Dmsg1(400, "Unregistered inactive watchdog %p\n", wd); + Dmsg1(800, "Unregistered inactive watchdog %p\n", wd); ok = true; goto get_out; } } - Dmsg1(400, "Failed to unregister watchdog %p\n", wd); + Dmsg1(800, "Failed to unregister watchdog %p\n", wd); get_out: wd_unlock(); @@ -231,7 +231,7 @@ extern "C" void *watchdog_thread(void *arg) struct timezone tz; time_t next_time; - Dmsg0(400, "NicB-reworked watchdog thread entered\n"); + Dmsg0(800, "NicB-reworked watchdog thread entered\n"); while (!quit) { watchdog_t *p; @@ -256,7 +256,7 @@ walk_list: /* Run the callback */ p->callback(p); - /* Reschedule (or move to inactive list if it's a one-shot timer) */ + /* Reschedule (or move to inactive list if it's a one-shot timer) */ if (p->one_shot) { wd_queue->remove(p); wd_inactive->append(p); @@ -290,7 +290,7 @@ walk_list: V(timer_mutex); } - Dmsg0(400, "NicB-reworked watchdog thread exited\n"); + Dmsg0(800, "NicB-reworked watchdog thread exited\n"); return NULL; } diff --git a/bacula/src/lib/workq.c b/bacula/src/lib/workq.c index 4611e6ce54..91f812bc5f 100755 --- a/bacula/src/lib/workq.c +++ b/bacula/src/lib/workq.c @@ -149,7 +149,7 @@ int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority) workq_ele_t *item; pthread_t id; - Dmsg0(400, "workq_add\n"); + Dmsg0(1400, "workq_add\n"); if (wq->valid != WORKQ_VALID) { return EINVAL; } @@ -164,7 +164,7 @@ int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority) return stat; } - Dmsg0(400, "add item to queue\n"); + Dmsg0(1400, "add item to queue\n"); if (priority) { /* Add to head of queue */ if (wq->first == NULL) { @@ -186,13 +186,13 @@ int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority) /* if any threads are idle, wake one */ if (wq->idle_workers > 0) { - Dmsg0(400, "Signal worker\n"); + Dmsg0(1400, "Signal worker\n"); if ((stat = pthread_cond_signal(&wq->work)) != 0) { pthread_mutex_unlock(&wq->mutex); return stat; } } else if (wq->num_workers < wq->max_workers) { - Dmsg0(400, "Create worker thread\n"); + Dmsg0(1400, "Create worker thread\n"); /* No idle threads so create a new one */ set_thread_concurrency(wq->max_workers + 1); if ((stat = pthread_create(&id, &wq->attr, workq_server, (void *)wq)) != 0) { @@ -202,7 +202,7 @@ int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority) wq->num_workers++; } pthread_mutex_unlock(&wq->mutex); - Dmsg0(400, "Return workq_add\n"); + Dmsg0(1400, "Return workq_add\n"); /* Return work_item if requested */ if (work_item) { *work_item = item; @@ -225,7 +225,7 @@ int workq_remove(workq_t *wq, workq_ele_t *work_item) pthread_t id; workq_ele_t *item, *prev; - Dmsg0(400, "workq_remove\n"); + Dmsg0(1400, "workq_remove\n"); if (wq->valid != WORKQ_VALID) { return EINVAL; } @@ -257,13 +257,13 @@ int workq_remove(workq_t *wq, workq_ele_t *work_item) /* if any threads are idle, wake one */ if (wq->idle_workers > 0) { - Dmsg0(400, "Signal worker\n"); + Dmsg0(1400, "Signal worker\n"); if ((stat = pthread_cond_signal(&wq->work)) != 0) { pthread_mutex_unlock(&wq->mutex); return stat; } } else { - Dmsg0(400, "Create worker thread\n"); + Dmsg0(1400, "Create worker thread\n"); /* No idle threads so create a new one */ set_thread_concurrency(wq->max_workers + 1); if ((stat = pthread_create(&id, &wq->attr, workq_server, (void *)wq)) != 0) { @@ -273,7 +273,7 @@ int workq_remove(workq_t *wq, workq_ele_t *work_item) wq->num_workers++; } pthread_mutex_unlock(&wq->mutex); - Dmsg0(400, "Return workq_remove\n"); + Dmsg0(1400, "Return workq_remove\n"); return stat; } @@ -290,7 +290,7 @@ void *workq_server(void *arg) workq_ele_t *we; int stat, timedout; - Dmsg0(400, "Start workq_server\n"); + Dmsg0(1400, "Start workq_server\n"); if ((stat = pthread_mutex_lock(&wq->mutex)) != 0) { return NULL; } @@ -299,9 +299,9 @@ void *workq_server(void *arg) struct timeval tv; struct timezone tz; - Dmsg0(400, "Top of for loop\n"); + Dmsg0(1400, "Top of for loop\n"); timedout = 0; - Dmsg0(400, "gettimeofday()\n"); + Dmsg0(1400, "gettimeofday()\n"); gettimeofday(&tv, &tz); timeout.tv_nsec = 0; timeout.tv_sec = tv.tv_sec + 2; @@ -310,7 +310,7 @@ void *workq_server(void *arg) /* * Wait 2 seconds, then if no more work, exit */ - Dmsg0(400, "pthread_cond_timedwait()\n"); + Dmsg0(1400, "pthread_cond_timedwait()\n"); #ifdef xxxxxxxxxxxxxxxx_was_HAVE_CYGWIN /* CYGWIN dies with a page fault the second * time that pthread_cond_timedwait() is called @@ -321,13 +321,13 @@ void *workq_server(void *arg) #else stat = pthread_cond_timedwait(&wq->work, &wq->mutex, &timeout); #endif - Dmsg1(400, "timedwait=%d\n", stat); + Dmsg1(1400, "timedwait=%d\n", stat); if (stat == ETIMEDOUT) { timedout = 1; break; } else if (stat != 0) { - /* This shouldn't happen */ - Dmsg0(400, "This shouldn't happen\n"); + /* This shouldn't happen */ + Dmsg0(1400, "This shouldn't happen\n"); wq->num_workers--; pthread_mutex_unlock(&wq->mutex); return NULL; @@ -342,16 +342,16 @@ void *workq_server(void *arg) if ((stat = pthread_mutex_unlock(&wq->mutex)) != 0) { return NULL; } - /* Call user's routine here */ - Dmsg0(400, "Calling user engine.\n"); + /* Call user's routine here */ + Dmsg0(1400, "Calling user engine.\n"); wq->engine(we->data); - Dmsg0(400, "Back from user engine.\n"); + Dmsg0(1400, "Back from user engine.\n"); free(we); /* release work entry */ - Dmsg0(400, "relock mutex\n"); + Dmsg0(1400, "relock mutex\n"); if ((stat = pthread_mutex_lock(&wq->mutex)) != 0) { return NULL; } - Dmsg0(400, "Done lock mutex\n"); + Dmsg0(1400, "Done lock mutex\n"); } /* * If no more work request, and we are asked to quit, then do it @@ -359,31 +359,31 @@ void *workq_server(void *arg) if (wq->first == NULL && wq->quit) { wq->num_workers--; if (wq->num_workers == 0) { - Dmsg0(400, "Wake up destroy routine\n"); + Dmsg0(1400, "Wake up destroy routine\n"); /* Wake up destroy routine if he is waiting */ pthread_cond_broadcast(&wq->work); } - Dmsg0(400, "Unlock mutex\n"); + Dmsg0(1400, "Unlock mutex\n"); pthread_mutex_unlock(&wq->mutex); - Dmsg0(400, "Return from workq_server\n"); + Dmsg0(1400, "Return from workq_server\n"); return NULL; } - Dmsg0(400, "Check for work request\n"); + Dmsg0(1400, "Check for work request\n"); /* * If no more work requests, and we waited long enough, quit */ - Dmsg1(400, "wq->first==NULL = %d\n", wq->first==NULL); - Dmsg1(400, "timedout=%d\n", timedout); + Dmsg1(1400, "wq->first==NULL = %d\n", wq->first==NULL); + Dmsg1(1400, "timedout=%d\n", timedout); if (wq->first == NULL && timedout) { - Dmsg0(400, "break big loop\n"); + Dmsg0(1400, "break big loop\n"); wq->num_workers--; break; } - Dmsg0(400, "Loop again\n"); + Dmsg0(1400, "Loop again\n"); } /* end of big for loop */ - Dmsg0(400, "unlock mutex\n"); + Dmsg0(1400, "unlock mutex\n"); pthread_mutex_unlock(&wq->mutex); - Dmsg0(400, "End workq_server\n"); + Dmsg0(1400, "End workq_server\n"); return NULL; } diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 67a40872d8..94ddeb0976 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -28,8 +28,10 @@ #include "bacula.h" /* pull in global headers */ #include "stored.h" /* pull in Storage Deamon headers */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - +/* + * Create a new Device Control Record and attach + * it to the device (if this is a real job). + */ DCR *new_dcr(JCR *jcr, DEVICE *dev) { if (jcr && jcr->dcr) { @@ -42,6 +44,9 @@ DCR *new_dcr(JCR *jcr, DEVICE *dev) } dcr->jcr = jcr; dcr->dev = dev; + if (dev) { + dcr->device = dev->device; + } dcr->block = new_block(dev); dcr->rec = new_record(); dcr->spool_fd = -1; @@ -58,6 +63,16 @@ void free_dcr(DCR *dcr) JCR *jcr = dcr->jcr; DEVICE *dev = dcr->dev; + /* + * If we reserved the device, we must decrement the + * number of writers. + */ + if (dcr->reserved_device) { + lock_device(dev); + dev->num_writers--; + unlock_device(dev); + } + /* Detach this dcr only if the dev is initialized */ if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) { dcr->dev->attached_dcrs->remove(dcr); @@ -74,16 +89,58 @@ void free_dcr(DCR *dcr) free(dcr); } +/* + * We "reserve" the drive by setting the ST_READ bit. No one else + * should touch the drive until that is cleared. + * This allows the DIR to "reserve" the device before actually + * starting the job. If the device is not available, the DIR + * can wait (to be implemented 1/05). + */ +bool reserve_device_for_read(JCR *jcr, DEVICE *dev) +{ + DCR *dcr = jcr->dcr; + bool ok = false; + + ASSERT(dcr); + if (device_is_unmounted(dev)) { + Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), + dev_name(dev)); + return false; + } + lock_device(dev); + block_device(dev, BST_DOING_ACQUIRE); + unlock_device(dev); + + if (dev->can_read() || dev->num_writers > 0) { + Jmsg2(jcr, M_FATAL, 0, _("Device %s is busy. Job %d canceled.\n"), + dev_name(dev), jcr->JobId); + goto get_out; + } + if (!dcr) { + dcr = new_dcr(jcr, dev); + } + dev->state &= ~ST_APPEND; /* clear any previous append mode */ + dev->state |= ST_READ; /* set read mode */ + ok = true; + +get_out: + P(dev->mutex); + unblock_device(dev); + V(dev->mutex); + return ok; +} + /********************************************************************* - * Acquire device for reading. We permit (for the moment) - * only one reader. We read the Volume label from the block and + * Acquire device for reading. + * The drive should have previously been reserved by calling + * reserve_device_for_read(). We read the Volume label from the block and * leave the block pointers just after the label. * * Returns: NULL if failed for any reason * dcr if successful */ -DCR *acquire_device_for_read(JCR *jcr) +DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev) { bool vol_ok = false; bool tape_previously_mounted; @@ -92,32 +149,17 @@ DCR *acquire_device_for_read(JCR *jcr) bool try_autochanger = true; int i; DCR *dcr = jcr->dcr; - DEVICE *dev; int vol_label_status; - /* Called for each volume */ - if (!dcr) { - dcr = new_dcr(jcr, jcr->device->dev); - } - dev = dcr->dev; - if (device_is_unmounted(dev)) { - Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), - dev_name(dev)); - } lock_device(dev); block_device(dev, BST_DOING_ACQUIRE); unlock_device(dev); init_dev_wait_timers(dev); - if (dev_state(dev, ST_READ) || dev->num_writers > 0) { - Jmsg2(jcr, M_FATAL, 0, _("Device %s is busy. Job %d canceled.\n"), - dev_name(dev), jcr->JobId); - goto get_out; - } - tape_previously_mounted = dev_state(dev, ST_READ) || - dev_state(dev, ST_APPEND) || - dev_state(dev, ST_LABEL); + tape_previously_mounted = dev->can_read() || + dev->can_append() || + dev->is_labeled(); tape_initially_mounted = tape_previously_mounted; /* Find next Volume, if any */ @@ -138,10 +180,10 @@ DCR *acquire_device_for_read(JCR *jcr) Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); } - dcr->dev->num_parts = dcr->VolCatInfo.VolCatParts; + dev->num_parts = dcr->VolCatInfo.VolCatParts; for (i=0; i<5; i++) { - dcr->dev->state &= ~ST_LABEL; /* force reread of label */ + dev->state &= ~ST_LABEL; /* force reread of label */ if (job_canceled(jcr)) { Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId); goto get_out; /* error return */ @@ -151,17 +193,17 @@ DCR *acquire_device_for_read(JCR *jcr) * reading. If it is a file, it opens it. * If it is a tape, it checks the volume name */ - for ( ; !(dev->state & ST_OPENED); ) { + for ( ; !dev->is_open(); ) { Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName); if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) { if (dev->dev_errno == EIO) { /* no tape loaded */ goto default_path; } - /* If we have a device that requires mount, + /* If we have a dvd that requires mount, * we need to try to open the label, so the info can be reported * if a wrong volume has been mounted. */ - if (dev_cap(dev, CAP_REQMOUNT) && (dcr->VolCatInfo.VolCatParts > 0)) { + if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) { break; } @@ -172,10 +214,9 @@ DCR *acquire_device_for_read(JCR *jcr) Dmsg1(129, "open_dev %s OK\n", dev_name(dev)); } - if (dev_cap(dev, CAP_REQMOUNT)) { + if (dev->is_dvd()) { vol_label_status = read_dev_volume_label_guess(dcr, 0); - } - else { + } else { vol_label_status = read_dev_volume_label(dcr); } @@ -262,36 +303,115 @@ get_out: return dcr; } +/* + * We reserve the device for appending by incrementing the + * reserved_device. We do virtually all the same work that + * is done in acquire_device_for_append(), but we do + * not attempt to mount the device. This routine allows + * the DIR to reserve multiple devices before *really* + * starting the job. It also permits the SD to refuse + * certain devices (not up, ...). + */ +bool reserve_device_for_append(JCR *jcr, DEVICE *dev) +{ + DCR *dcr = jcr->dcr; + bool recycle; + bool ok = false; + + ASSERT(dcr); + + lock_device(dev); + block_device(dev, BST_DOING_ACQUIRE); + unlock_device(dev); + if (device_is_unmounted(dev)) { + Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), + dev_name(dev)); + goto get_out; + } + Dmsg1(190, "reserve_append device is %s\n", dev_is_tape(dev)?"tape":"disk"); + if (dev->can_append()) { + Dmsg0(190, "device already in append.\n"); + /* + * Device already in append mode + * + * Check if we have the right Volume mounted + * OK if current volume info OK + * OK if next volume matches current volume + */ + bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName)); + if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) && + !(dir_find_next_appendable_volume(dcr) && + strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */ + Dmsg0(190, "Wrong tape mounted.\n"); + if (dev->num_writers != 0 || dev->reserved_device) { + Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev)); + goto get_out; + } + } else { + /* + * At this point, the correct tape is already mounted, so + * we do not need to do mount_next_write_volume(), unless + * we need to recycle the tape. + */ + recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; + Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle); + if (recycle && dev->num_writers != 0) { + Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\"" + " because it is in use by another job.\n")); + goto get_out; + } + if (dev->num_writers == 0) { + memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); + } + } + } else { + if (dev->can_read()) { + Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev)); + goto get_out; + } + ASSERT(dev->num_writers == 0); + } + + dev->reserved_device++; + dcr->reserved_device = true; + ok = true; + +get_out: + P(dev->mutex); + unblock_device(dev); + V(dev->mutex); + return ok; +} + /* * Acquire device for writing. We permit multiple writers. * If this is the first one, we read the label. * * Returns: NULL if failed for any reason - * dev if successful (may change if new dev opened) - * This routine must be single threaded because we may create - * multiple devices (for files), thus we have our own mutex - * on top of the device mutex. + * dcr if successful. + * Note, normally reserve_device_for_append() is called + * before this routine. */ -DCR *acquire_device_for_append(JCR *jcr) +DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev) { bool release = false; bool recycle = false; bool do_mount = false; - DCR *dcr; - DEVICE *dev = jcr->device->dev; + DCR *dcr = jcr->dcr; - dcr = new_dcr(jcr, dev); - if (device_is_unmounted(dev)) { - Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"), - dev_name(dev)); + if (!dcr) { + dcr = new_dcr(jcr, dev); } lock_device(dev); block_device(dev, BST_DOING_ACQUIRE); unlock_device(dev); - P(mutex); /* lock all devices */ Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk"); - if (dev_state(dev, ST_APPEND)) { + if (dcr->reserved_device) { + dev->reserved_device--; + dcr->reserved_device = false; + } + if (dev->can_append()) { Dmsg0(190, "device already in append.\n"); /* * Device already in append mode @@ -307,32 +427,9 @@ DCR *acquire_device_for_append(JCR *jcr) !(dir_find_next_appendable_volume(dcr) && strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */ Dmsg0(190, "Wrong tape mounted.\n"); - if (dev->num_writers != 0) { - DEVICE *d = ((DEVRES *)dev->device)->dev; - uint32_t open_vols = 0; - for ( ; d; d=d->next) { - open_vols++; - } - if (dev_state(dev, ST_FILE) && dev->max_open_vols > open_vols) { - d = init_dev(NULL, (DEVRES *)dev->device); /* init new device */ - d->prev = dev; /* chain in new device */ - d->next = dev->next; - dev->next = d; - /* Release old device */ - P(dev->mutex); - unblock_device(dev); - V(dev->mutex); - free_dcr(dcr); /* release dcr pointing to old dev */ - /* Make new device current device and lock it */ - dev = d; - dcr = new_dcr(jcr, dev); /* get new dcr for new device */ - lock_device(dev); - block_device(dev, BST_DOING_ACQUIRE); - unlock_device(dev); - } else { - Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev)); - goto get_out; - } + if (dev->num_writers != 0 || dev->reserved_device) { + Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev_name(dev)); + goto get_out; } /* Wrong tape mounted, release it, then fall through to get correct one */ Dmsg0(190, "Wrong tape mounted, release and try mount.\n"); @@ -358,7 +455,7 @@ DCR *acquire_device_for_append(JCR *jcr) } else { /* Not already in append mode, so mount the device */ Dmsg0(190, "Not in append mode, try mount.\n"); - if (dev_state(dev, ST_READ)) { + if (dev->can_read()) { Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev)); goto get_out; } @@ -368,9 +465,7 @@ DCR *acquire_device_for_append(JCR *jcr) if (do_mount || recycle) { Dmsg0(190, "Do mount_next_write_vol\n"); - V(mutex); /* don't lock everything during mount */ bool mounted = mount_next_write_volume(dcr, release); - P(mutex); /* re-lock */ if (!mounted) { if (!job_canceled(jcr)) { /* Reduce "noise" -- don't print if job canceled */ @@ -385,8 +480,6 @@ DCR *acquire_device_for_append(JCR *jcr) if (jcr->NumVolumes == 0) { jcr->NumVolumes = 1; } - set_jcr_job_status(jcr, JS_Running); - dir_send_job_status(jcr); goto ok_out; /* @@ -400,7 +493,6 @@ ok_out: P(dev->mutex); unblock_device(dev); V(dev->mutex); - V(mutex); /* unlock other threads */ return dcr; } @@ -426,7 +518,7 @@ bool release_device(JCR *jcr) } else if (dev->num_writers > 0) { dev->num_writers--; Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers); - if (dev_state(dev, ST_LABEL)) { + if (dev->is_labeled()) { Dmsg0(100, "dir_create_jobmedia_record. Release\n"); if (!dir_create_jobmedia_record(dcr)) { Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), @@ -443,7 +535,7 @@ bool release_device(JCR *jcr) dir_update_volume_info(dcr, false); /* send Volume info to Director */ } - if (!dev->num_writers && (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN))) { + if (!dev->num_writers && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) { offline_or_rewind_dev(dev); close_dev(dev); } @@ -454,13 +546,13 @@ bool release_device(JCR *jcr) } /* Fire off Alert command and include any output */ - if (!job_canceled(jcr) && jcr->device->alert_command) { + if (!job_canceled(jcr) && dcr->device->alert_command) { POOLMEM *alert; int status = 1; BPIPE *bpipe; char line[MAXSTRING]; alert = get_pool_memory(PM_FNAME); - alert = edit_device_codes(jcr, alert, jcr->device->alert_command, ""); + alert = edit_device_codes(dcr, alert, ""); bpipe = open_bpipe(alert, 0, "r"); if (bpipe) { while (fgets(line, sizeof(line), bpipe->rfd)) { @@ -479,15 +571,7 @@ bool release_device(JCR *jcr) Dmsg1(400, "alert status=%d\n", status); free_pool_memory(alert); } - if (dev->prev && !dev_state(dev, ST_READ) && !dev->num_writers) { - P(mutex); - unlock_device(dev); - dev->prev->next = dev->next; /* dechain */ - term_dev(dev); - V(mutex); - } else { - unlock_device(dev); - } + unlock_device(dev); free_dcr(jcr->dcr); jcr->dcr = NULL; return true; diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index c188c4d409..59f8502d31 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -44,33 +44,31 @@ bool do_append_data(JCR *jcr) BSOCK *ds; BSOCK *fd_sock = jcr->file_bsock; bool ok = true; - DEVICE *dev; DEV_RECORD rec; - DCR *dcr; + DCR *dcr = jcr->dcr; + DEVICE *dev = dcr->dev; + Dmsg0(10, "Start append data.\n"); ds = fd_sock; - if (!bnet_set_buffer_size(ds, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { + if (!bnet_set_buffer_size(ds, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { set_jcr_job_status(jcr, JS_ErrorTerminated); Jmsg(jcr, M_FATAL, 0, _("Unable to set network buffer size.\n")); return false; } - /* - * Acquire output device for writing. Note, after acquiring a - * device, we MUST release it, which is done at the end of this - * subroutine. - */ - Dmsg0(100, "just before acquire_device\n"); - if (!(dcr=acquire_device_for_append(jcr))) { + if (!acquire_device_for_append(jcr, dev)) { set_jcr_job_status(jcr, JS_ErrorTerminated); return false; } - dev = dcr->dev; + memset(&rec, 0, sizeof(rec)); + set_jcr_job_status(jcr, JS_Running); + dir_send_job_status(jcr); + if (dev->VolCatInfo.VolCatName[0] == 0) { Dmsg0(000, "NULL Volume name. This shouldn't happen!!!\n"); } @@ -283,27 +281,27 @@ bool do_append_data(JCR *jcr) commit_data_spool(jcr); } - /* If the device is nor a tape, nor a fifo, and WritePartAfterJob + /* If the device is nor a dvd and WritePartAfterJob * is set to yes, open the next part, so, in case of a device * that requires mount, it will be written to the device. */ - if (!(dcr->dev->state & (ST_TAPE|ST_FIFO)) && (jcr->write_part_after_job) && (dcr->dev->part_size > 0)) { + if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) { Dmsg0(100, "Writing last part because write_part_after_job is set.\n"); - if (dcr->dev->part < dcr->dev->num_parts) { - Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"), + if (dev->part < dev->num_parts) { + Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"), dev->part, dev->num_parts, dev_name(dev)); - dcr->dev->dev_errno = EIO; + dev->dev_errno = EIO; ok = false; } - if (ok && (open_next_part(dcr->dev) < 0)) { + if (ok && (open_next_part(dev) < 0)) { Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"), - dev_name(dcr->dev), strerror_dev(dcr->dev)); - dcr->dev->dev_errno = EIO; + dev_name(dev), strerror_dev(dev)); + dev->dev_errno = EIO; ok = false; } - dcr->dev->VolCatInfo.VolCatParts = dcr->dev->num_parts; + dev->VolCatInfo.VolCatParts = dev->num_parts; } Dmsg1(200, "calling release device JobStatus=%d\n", jcr->JobStatus); diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 645993c72c..7706e0458a 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -41,7 +41,7 @@ static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" " FirstIndex=%u LastIndex=%u StartFile=%u EndFile=%u" " StartBlock=%u EndBlock=%u\n"; static char FileAttributes[] = "UpdCat Job=%s FileAttributes "; -static char Job_status[] = "3012 Job %s jobstatus %d\n"; +static char Job_status[] = "Status Job=%s JobStatus=%d\n"; /* Responses received from the Director */ @@ -49,7 +49,8 @@ static char OK_media[] = "1000 OK VolName=%127s VolJobs=%u VolFiles=%u" " VolBlocks=%u VolBytes=%" lld " VolMounts=%u VolErrors=%u VolWrites=%u" " MaxVolBytes=%" lld " VolCapacityBytes=%" lld " VolStatus=%20s" " Slot=%d MaxVolJobs=%u MaxVolFiles=%u InChanger=%d" - " VolReadTime=%" lld " VolWriteTime=%" lld " EndFile=%u EndBlock=%u VolParts=%u"; + " VolReadTime=%" lld " VolWriteTime=%" lld " EndFile=%u EndBlock=%u" + " VolParts=%u LabelType=%d"; static char OK_create[] = "1000 OK CreateJobMedia\n"; @@ -98,8 +99,9 @@ static bool do_get_volume_info(DCR *dcr) &vol.VolCatCapacityBytes, vol.VolCatStatus, &vol.Slot, &vol.VolCatMaxJobs, &vol.VolCatMaxFiles, &InChanger, &vol.VolReadTime, &vol.VolWriteTime, - &vol.EndFile, &vol.EndBlock, &vol.VolCatParts); - if (n != 20) { + &vol.EndFile, &vol.EndBlock, &vol.VolCatParts, + &vol.LabelType); + if (n != 21) { Dmsg2(100, "Bad response from Dir fields=%d: %s\n", n, dir->msg); Mmsg(jcr->errmsg, _("Error getting Volume info: %s\n"), dir->msg); return false; @@ -215,13 +217,14 @@ bool dir_update_volume_info(DCR *dcr, bool label) char ed1[50], ed2[50], ed3[50], ed4[50]; VOLUME_CAT_INFO *vol = &dev->VolCatInfo; int InChanger; + POOL_MEM VolumeName; if (vol->VolCatName[0] == 0) { Jmsg0(jcr, M_FATAL, 0, _("NULL Volume name. This shouldn't happen!!!\n")); Dmsg0(000, "NULL Volume name. This shouldn't happen!!!\n"); return false; } - if (dev_state(dev, ST_READ)) { + if (dev->can_read()) { Jmsg0(jcr, M_FATAL, 0, _("Attempt to update_volume_info in read mode!!!\n")); Dmsg0(000, "Attempt to update_volume_info in read mode!!!\n"); return false; @@ -233,10 +236,11 @@ bool dir_update_volume_info(DCR *dcr, bool label) bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); vol->VolCatBytes = 1; /* indicates tape labeled */ } - bash_spaces(vol->VolCatName); + pm_strcpy(VolumeName, vol->VolCatName); + bash_spaces(VolumeName); InChanger = vol->InChanger; bnet_fsend(dir, Update_media, jcr->Job, - vol->VolCatName, vol->VolCatJobs, vol->VolCatFiles, + VolumeName.c_str(), vol->VolCatJobs, vol->VolCatFiles, vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1), vol->VolCatMounts, vol->VolCatErrors, vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), @@ -244,14 +248,14 @@ bool dir_update_volume_info(DCR *dcr, bool label) InChanger, /* bool in structure */ edit_uint64(vol->VolReadTime, ed3), edit_uint64(vol->VolWriteTime, ed4), - vol->VolCatParts ); + vol->VolCatParts); Dmsg1(300, "update_volume_info(): %s", dir->msg); - unbash_spaces(vol->VolCatName); if (!do_get_volume_info(dcr)) { Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg); - Dmsg1(000, "Didn't get vol info: %s", jcr->errmsg); + Dmsg2(000, "Didn't get vol info vol=%s: ERR=%s", + vol->VolCatName, jcr->errmsg); return false; } Dmsg1(420, "get_volume_info(): %s", dir->msg); diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 9eee899b6c..b9d4779e9d 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -30,8 +30,8 @@ #include "stored.h" /* pull in Storage Deamon headers */ /* Forward referenced functions */ -char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd); -static int get_autochanger_loaded_slot(JCR *jcr); +char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd); +static int get_autochanger_loaded_slot(DCR *dcr); /* @@ -53,7 +53,7 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) JCR *jcr = dcr->jcr; DEVICE *dev = dcr->dev; int slot; - int drive = jcr->device->drive_index; + int drive = dev->device->drive_index; int rtn_stat = -1; /* error status */ slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0; @@ -73,14 +73,14 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) } Dmsg1(400, "Want changer slot=%d\n", slot); - if (slot > 0 && jcr->device->changer_name && jcr->device->changer_command) { - uint32_t timeout = jcr->device->max_changer_wait; + if (slot > 0 && dcr->device->changer_name && dcr->device->changer_command) { + uint32_t timeout = dcr->device->max_changer_wait; POOLMEM *changer; int loaded, status; changer = get_pool_memory(PM_FNAME); - loaded = get_autochanger_loaded_slot(jcr); + loaded = get_autochanger_loaded_slot(dcr); /* If tape we want is not loaded, load it. */ if (loaded != slot) { @@ -88,44 +88,42 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) /* We are going to load a new tape, so close the device */ force_close_dev(dev); if (loaded != 0 && loaded != -1) { /* must unload drive */ - Dmsg0(400, "Doing changer unload.\n"); + Dmsg0(400, "Doing changer unload.\n"); Jmsg(jcr, M_INFO, 0, - _("3303 Issuing autochanger \"unload slot %d, drive %d\" command.\n"), + _("3303 Issuing autochanger \"unload slot %d, drive %d\" command.\n"), loaded, drive); dcr->VolCatInfo.Slot = loaded; /* slot to be unloaded */ - changer = edit_device_codes(jcr, changer, - jcr->device->changer_command, "unload"); + changer = edit_device_codes(dcr, changer, "unload"); status = run_program(changer, timeout, NULL); if (status != 0) { berrno be; be.set_errno(status); - Jmsg(jcr, M_INFO, 0, _("3992 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"), + Jmsg(jcr, M_INFO, 0, _("3992 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"), slot, drive, be.strerror()); } - Dmsg1(400, "unload status=%d\n", status); + Dmsg1(400, "unload status=%d\n", status); } /* * Load the desired cassette */ - Dmsg1(400, "Doing changer load slot %d\n", slot); + Dmsg1(400, "Doing changer load slot %d\n", slot); Jmsg(jcr, M_INFO, 0, - _("3304 Issuing autochanger \"load slot %d, drive %d\" command.\n"), + _("3304 Issuing autochanger \"load slot %d, drive %d\" command.\n"), slot, drive); dcr->VolCatInfo.Slot = slot; /* slot to be loaded */ - changer = edit_device_codes(jcr, changer, - jcr->device->changer_command, "load"); + changer = edit_device_codes(dcr, changer, "load"); status = run_program(changer, timeout, NULL); if (status == 0) { - Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load slot %d, drive %d\", status is OK.\n"), + Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load slot %d, drive %d\", status is OK.\n"), slot, drive); } else { berrno be; be.set_errno(status); - Jmsg(jcr, M_INFO, 0, _("3992 Bad autochanger \"load slot %d, drive %d\": ERR=%s.\n"), + Jmsg(jcr, M_INFO, 0, _("3992 Bad autochanger \"load slot %d, drive %d\": ERR=%s.\n"), slot, drive, be.strerror()); } - Dmsg2(400, "load slot %d status=%d\n", slot, status); + Dmsg2(400, "load slot %d status=%d\n", slot, status); } else { status = 0; /* we got what we want */ } @@ -140,12 +138,13 @@ int autoload_device(DCR *dcr, int writing, BSOCK *dir) return rtn_stat; } -static int get_autochanger_loaded_slot(JCR *jcr) +static int get_autochanger_loaded_slot(DCR *dcr) { + JCR *jcr = dcr->jcr; POOLMEM *changer, *results; int status, loaded; - uint32_t timeout = jcr->device->max_changer_wait; - int drive = jcr->device->drive_index; + uint32_t timeout = dcr->device->max_changer_wait; + int drive = dcr->device->drive_index; results = get_pool_memory(PM_MESSAGE); changer = get_pool_memory(PM_FNAME); @@ -153,8 +152,7 @@ static int get_autochanger_loaded_slot(JCR *jcr) /* Find out what is loaded, zero means device is unloaded */ Jmsg(jcr, M_INFO, 0, _("3301 Issuing autochanger \"loaded drive %d\" command.\n"), drive); - changer = edit_device_codes(jcr, changer, jcr->device->changer_command, - "loaded"); + changer = edit_device_codes(dcr, changer, "loaded"); status = run_program(changer, timeout, results); Dmsg3(50, "run_prog: %s stat=%d result=%s\n", changer, status, results); if (status == 0) { @@ -204,14 +202,14 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) { DEVICE *dev = dcr->dev; JCR *jcr = dcr->jcr; - uint32_t timeout = jcr->device->max_changer_wait; + uint32_t timeout = dcr->device->max_changer_wait; POOLMEM *changer; BPIPE *bpipe; int slot, loaded; int len = sizeof_pool_memory(dir->msg) - 1; - if (!dev_cap(dev, CAP_AUTOCHANGER) || !jcr->device->changer_name || - !jcr->device->changer_command) { + if (!dev_cap(dev, CAP_AUTOCHANGER) || !dcr->device->changer_name || + !dcr->device->changer_command) { bnet_fsend(dir, _("3993 Not a autochanger device.\n")); return false; } @@ -222,24 +220,24 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) force_close_dev(dev); /* First unload any tape */ - loaded = get_autochanger_loaded_slot(jcr); + loaded = get_autochanger_loaded_slot(dcr); if (loaded > 0) { bnet_fsend(dir, _("3305 Issuing autochanger \"unload slot %d\" command.\n"), loaded); slot = dcr->VolCatInfo.Slot; dcr->VolCatInfo.Slot = loaded; - changer = edit_device_codes(jcr, changer, jcr->device->changer_command, "unload"); + changer = edit_device_codes(dcr, changer, "unload"); int stat = run_program(changer, timeout, NULL); if (stat != 0) { berrno be; be.set_errno(stat); - Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d\" command: ERR=%s.\n"), + Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d\" command: ERR=%s.\n"), loaded, be.strerror()); } dcr->VolCatInfo.Slot = slot; } /* Now list slots occupied */ - changer = edit_device_codes(jcr, changer, jcr->device->changer_command, "list"); + changer = edit_device_codes(dcr, changer, "list"); bnet_fsend(dir, _("3306 Issuing autochanger \"list\" command.\n")); bpipe = open_bpipe(changer, timeout, "r"); if (!bpipe) { @@ -284,53 +282,54 @@ bool autochanger_list(DCR *dcr, BSOCK *dir) * cmd = command string (load, unload, ...) * */ -char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd) +char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd) { const char *p; const char *str; char add[20]; + const char *imsg = dcr->device->changer_command; *omsg = 0; Dmsg1(800, "edit_device_codes: %s\n", imsg); for (p=imsg; *p; p++) { if (*p == '%') { switch (*++p) { - case '%': - str = "%"; + case '%': + str = "%"; break; - case 'a': - str = dev_name(jcr->device->dev); + case 'a': + str = dev_name(dcr->dev); break; - case 'c': - str = NPRT(jcr->device->changer_name); + case 'c': + str = NPRT(dcr->device->changer_name); break; - case 'd': - sprintf(add, "%d", jcr->device->dev->drive_index); + case 'd': + sprintf(add, "%d", dcr->dev->drive_index); str = add; break; - case 'o': + case 'o': str = NPRT(cmd); break; - case 's': - sprintf(add, "%d", jcr->dcr->VolCatInfo.Slot - 1); + case 's': + sprintf(add, "%d", dcr->VolCatInfo.Slot - 1); str = add; break; - case 'S': - sprintf(add, "%d", jcr->dcr->VolCatInfo.Slot); + case 'S': + sprintf(add, "%d", dcr->VolCatInfo.Slot); str = add; break; - case 'j': /* Job name */ - str = jcr->Job; + case 'j': /* Job name */ + str = dcr->jcr->Job; break; - case 'v': - str = NPRT(jcr->dcr->VolumeName); + case 'v': + str = NPRT(dcr->VolumeName); break; - case 'f': - str = NPRT(jcr->client_name); + case 'f': + str = NPRT(dcr->jcr->client_name); break; default: - add[0] = '%'; + add[0] = '%'; add[1] = *p; add[2] = 0; str = add; diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index 9b51f9f369..54f0d82da8 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -169,7 +169,7 @@ int main (int argc, char *argv[]) exit(1); } unlock_device(out_dev); - if (!acquire_device_for_append(out_jcr)) { + if (!acquire_device_for_append(out_jcr, out_dev)) { free_jcr(in_jcr); exit(1); } @@ -212,37 +212,37 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) } switch (rec->FileIndex) { case PRE_LABEL: - Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n"); + Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n"); return false; case VOL_LABEL: - Pmsg0(000, "Volume label not copied.\n"); + Pmsg0(000, "Volume label not copied.\n"); return true; case SOS_LABEL: jobs++; break; case EOS_LABEL: while (!write_record_to_block(out_block, rec)) { - Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len, + Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len, rec->remainder); if (!write_block_to_device(out_jcr->dcr)) { - Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", + Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", dev_name(out_dev), strerror_dev(out_dev)); - Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), strerror_dev(out_dev)); } } if (!write_block_to_device(out_jcr->dcr)) { - Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", + Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", dev_name(out_dev), strerror_dev(out_dev)); - Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), strerror_dev(out_dev)); } break; case EOM_LABEL: - Pmsg0(000, "EOM label not copied.\n"); + Pmsg0(000, "EOM label not copied.\n"); return true; case EOT_LABEL: /* end of all tapes */ - Pmsg0(000, "EOT label not copied.\n"); + Pmsg0(000, "EOT label not copied.\n"); return true; default: break; @@ -255,9 +255,9 @@ static bool record_cb(DCR *in_dcr, DEV_RECORD *rec) Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len, rec->remainder); if (!write_block_to_device(out_jcr->dcr)) { - Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", + Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", dev_name(out_dev), strerror_dev(out_dev)); - Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), strerror_dev(out_dev)); break; } diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 8747e02e91..420ce09c61 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -8,7 +8,7 @@ * */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -70,7 +70,7 @@ bool forge_on = false; static void usage() { fprintf(stderr, -"Copyright (C) 2000-2004 Kern Sibbald and John Walker.\n" +"Copyright (C) 2000-2005 Kern Sibbald.\n" "\nVersion: " VERSION " (" BDATE ")\n\n" "Usage: bextract \n" " -b specify a bootstrap file\n" @@ -122,30 +122,30 @@ int main (int argc, char *argv[]) break; case 'e': /* exclude list */ - if ((fd = fopen(optarg, "r")) == NULL) { + if ((fd = fopen(optarg, "r")) == NULL) { berrno be; - Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n", + Pmsg2(0, "Could not open exclude file: %s, ERR=%s\n", optarg, be.strerror()); exit(1); } while (fgets(line, sizeof(line), fd) != NULL) { strip_trailing_junk(line); - Dmsg1(900, "add_exclude %s\n", line); + Dmsg1(900, "add_exclude %s\n", line); add_fname_to_exclude_list(ff, line); } fclose(fd); break; case 'i': /* include list */ - if ((fd = fopen(optarg, "r")) == NULL) { + if ((fd = fopen(optarg, "r")) == NULL) { berrno be; - Pmsg2(0, "Could not open include file: %s, ERR=%s\n", + Pmsg2(0, "Could not open include file: %s, ERR=%s\n", optarg, be.strerror()); exit(1); } while (fgets(line, sizeof(line), fd) != NULL) { strip_trailing_junk(line); - Dmsg1(900, "add_include %s\n", line); + Dmsg1(900, "add_include %s\n", line); add_fname_to_include_list(ff, 0, line); } fclose(fd); @@ -273,18 +273,18 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) */ if (extract) { if (!is_bopen(&bfd)) { - Emsg0(M_ERROR, 0, _("Logic error output file should be open but is not.\n")); + Emsg0(M_ERROR, 0, _("Logic error output file should be open but is not.\n")); } set_attributes(jcr, attr, &bfd); extract = false; } if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) { - Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); + Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); } if (attr->file_index != rec->FileIndex) { - Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"), + Emsg2(M_ERROR_TERM, 0, _("Record header file index %ld not equal record index %ld\n"), rec->FileIndex, attr->file_index); } @@ -293,7 +293,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) attr->data_stream = decode_stat(attr->attr, &attr->statp, &attr->LinkFI); if (!is_stream_supported(attr->data_stream)) { if (!non_support_data++) { - Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), + Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"), stream_to_ascii(attr->data_stream)); } extract = false; @@ -342,7 +342,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) fileAddr = faddr; if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { berrno be; - Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), + Emsg2(M_ERROR_TERM, 0, _("Seek error on %s: %s\n"), attr->ofname, be.strerror()); } } @@ -351,10 +351,10 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) wsize = rec->data_len; } total += wsize; - Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total); + Dmsg2(8, "Write %u bytes, total=%u\n", wsize, total); if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) { berrno be; - Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), + Emsg2(M_ERROR_TERM, 0, _("Write error on %s: %s\n"), attr->ofname, be.strerror()); } fileAddr += wsize; @@ -382,7 +382,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) fileAddr = faddr; if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { berrno be; - Emsg3(M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), + Emsg3(M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), edit_uint64(fileAddr, ec1), attr->ofname, be.strerror()); extract = false; return true; @@ -395,28 +395,28 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) compress_len = compress_buf_size; if ((stat=uncompress((Bytef *)compress_buf, &compress_len, (const Bytef *)wbuf, (uLong)wsize) != Z_OK)) { - Emsg1(M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat); + Emsg1(M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat); extract = false; return true; } - Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total); + Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total); if ((uLongf)bwrite(&bfd, compress_buf, (size_t)compress_len) != compress_len) { berrno be; - Pmsg0(0, "===Write error===\n"); - Emsg2(M_ERROR, 0, _("Write error on %s: %s\n"), + Pmsg0(0, "===Write error===\n"); + Emsg2(M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, be.strerror()); extract = false; return true; } total += compress_len; fileAddr += compress_len; - Dmsg2(100, "Compress len=%d uncompressed=%d\n", rec->data_len, + Dmsg2(100, "Compress len=%d uncompressed=%d\n", rec->data_len, compress_len); } #else if (extract) { - Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n"); + Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n"); extract = false; return true; } @@ -430,7 +430,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) case STREAM_PROGRAM_NAMES: case STREAM_PROGRAM_DATA: if (!prog_name_msg) { - Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n"); + Pmsg0(000, "Got Program Name or Data Stream. Ignored.\n"); prog_name_msg++; } break; @@ -439,7 +439,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) /* If extracting, wierd stream (not 1 or 2), close output file anyway */ if (extract) { if (!is_bopen(&bfd)) { - Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n"); + Emsg0(M_ERROR, 0, "Logic error output file should be open but is not.\n"); } set_attributes(jcr, attr, &bfd); extract = false; diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index 8fb8a26815..cc88da62ec 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -300,8 +300,10 @@ static bool unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) block_len-BLKHDR_CS_LENGTH); if (BlockCheckSum != CheckSum) { dev->dev_errno = EIO; - Mmsg5(dev->errmsg, _("Volume data error at %u:%u! Block checksum mismatch in block %u: calc=%x blk=%x\n"), - dev->file, dev->block_num, (unsigned)BlockNumber, BlockCheckSum, CheckSum); + Mmsg6(dev->errmsg, _("Volume data error at %u:%u!\n" + "Block checksum mismatch in block=%u len=%d: calc=%x blk=%x\n"), + dev->file, dev->block_num, (unsigned)BlockNumber, + block_len, BlockCheckSum, CheckSum); if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } @@ -545,8 +547,7 @@ bool write_block_to_dev(DCR *dcr) } if (dev->free_space_errno < 0) { /* Error while getting free space */ - char ed1[50]; - char ed2[50]; + char ed1[50], ed2[50]; Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg); Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"), dev->VolCatInfo.VolCatName, @@ -558,8 +559,7 @@ bool write_block_to_dev(DCR *dcr) } if (((dev->free_space_errno > 0) && ((dev->part_size + block->binbuf) >= dev->free_space))) { - char ed1[50]; - char ed2[50]; + char ed1[50], ed2[50]; Dmsg0(10, "==== Just enough free space on the device to write the current part...\n"); Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"), dev->VolCatInfo.VolCatName, @@ -736,7 +736,7 @@ static bool terminate_writing_volume(DCR *dcr) } dev->VolCatInfo.VolCatFiles = dev->file; - if (dev_cap(dev, CAP_REQMOUNT)) { /* Write the current (and last) part. */ + if (dev->is_dvd()) { /* Write the current (and last) part. */ open_next_part(dev); } @@ -820,14 +820,14 @@ reread: return false; } - /*Dmsg1(200, "dev.c 111->file_size=%u\n",(unsigned int)dev->file_size); - Dmsg1(200, "dev.c lseek=%u\n",(unsigned int)lseek(dev->fd, 0, SEEK_CUR)); - Dmsg1(200, "dev.c dev->part_start=%u\n",(unsigned int)dev->part_start); - Dmsg1(200, "dev.c dev->file_size-dev->part_start=%u\n",(unsigned int)dev->file_size-dev->part_start); - Dmsg1(200, "dev.c dev->part_size=%u\n", (unsigned int)dev->part_size); - Dmsg1(200, "dev.c dev->part=%u\n", (unsigned int)dev->part); - Dmsg1(200, "dev.c dev->VolCatInfo.VolCatParts=%u\n", (unsigned int)dev->VolCatInfo.VolCatParts); - Dmsg3(200, "dev.c Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), ((dev->file_size-dev->part_start) == dev->part_size), (dev->part <= dev->VolCatInfo.VolCatParts));*/ + /*Dmsg1(200, "dev->file_size=%u\n",(unsigned int)dev->file_size); + Dmsg1(200, "lseek=%u\n",(unsigned int)lseek(dev->fd, 0, SEEK_CUR)); + Dmsg1(200, "dev->part_start=%u\n",(unsigned int)dev->part_start); + Dmsg1(200, "dev->file_size-dev->part_start=%u\n",(unsigned int)dev->file_size-dev->part_start); + Dmsg1(200, "dev->part_size=%u\n", (unsigned int)dev->part_size); + Dmsg1(200, "dev->part=%u\n", (unsigned int)dev->part); + Dmsg1(200, "dev->VolCatInfo.VolCatParts=%u\n", (unsigned int)dev->VolCatInfo.VolCatParts); + Dmsg3(200, "Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), ((dev->file_size-dev->part_start) == dev->part_size), (dev->part <= dev->VolCatInfo.VolCatParts));*/ /* Check for part file end */ if ((dev->num_parts > 0) && ((dev->file_size-dev->part_start) == dev->part_size) && @@ -862,17 +862,18 @@ reread: Mmsg4(dev->errmsg, _("Read error at file:blk %u:%u on device %s. ERR=%s.\n"), dev->file, dev->block_num, dev->dev_name, be.strerror()); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); - if (dev->state & ST_EOF) { /* EOF just seen? */ + if (dev->at_eof()) { /* EOF just seen? */ dev->state |= ST_EOT; /* yes, error => EOT */ } return false; } - Dmsg1(200, "Read device got %d bytes\n", stat); + Dmsg3(200, "Read device got %d bytes at %u:%u\n", stat, + dev->file, dev->block_num); if (stat == 0) { /* Got EOF ! */ dev->block_num = block->read_len = 0; Mmsg3(dev->errmsg, _("Read zero bytes at %u:%u on device %s.\n"), dev->file, dev->block_num, dev->dev_name); - if (dev->state & ST_EOF) { /* EOF already read? */ + if (dev->at_eof()) { /* EOF already read? */ dev->state |= ST_EOT; /* yes, 2 EOFs => EOT */ block->read_len = 0; return 0; @@ -990,11 +991,13 @@ reread: * absolute positioning -- so much for efficiency. KES Sep 02. */ Dmsg0(200, "At end of read block\n"); - if (block->read_len > block->block_len && !(dev->state & ST_TAPE)) { + if (block->read_len > block->block_len && !dev->is_tape()) { + char ed1[50]; off_t pos = lseek_dev(dev, (off_t)0, SEEK_CUR); /* get curr pos */ pos -= (block->read_len - block->block_len); lseek_dev(dev, pos, SEEK_SET); - Dmsg2(200, "Did lseek blk_size=%d rdlen=%d\n", block->block_len, + Dmsg3(200, "Did lseek pos=%s blk_size=%d rdlen=%d\n", + edit_uint64(pos, ed1), block->block_len, block->read_len); dev->file_addr = pos; dev->file_size = pos; diff --git a/bacula/src/stored/block.h b/bacula/src/stored/block.h index 4df807342a..d230fedf7a 100644 --- a/bacula/src/stored/block.h +++ b/bacula/src/stored/block.h @@ -73,6 +73,8 @@ uint32_t VolSessionTime; */ +class DEVICE; /* for forward reference */ + /* * DEV_BLOCK for reading and writing blocks. * This is the basic unit that is written to the device, and @@ -84,7 +86,7 @@ */ struct DEV_BLOCK { DEV_BLOCK *next; /* pointer to next one */ - void *dev; /* pointer to device (DEVICE not defined yet) */ + DEVICE *dev; /* pointer to device */ /* binbuf is the number of bytes remaining in the buffer. * For writes, it is bytes not yet written. * For reads, it is remaining bytes not yet read. diff --git a/bacula/src/stored/bls.c b/bacula/src/stored/bls.c index debd882ea4..68474d9cb8 100644 --- a/bacula/src/stored/bls.c +++ b/bacula/src/stored/bls.c @@ -5,7 +5,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -65,9 +65,9 @@ static BSR *bsr = NULL; static void usage() { fprintf(stderr, -"Copyright (C) 2000-2004 Kern Sibbald and John Walker.\n" +"Copyright (C) 2000-2005 Kern Sibbald.\n" "\nVersion: " VERSION " (" BDATE ")\n\n" -"Usage: bls [-d debug_level] \n" +"Usage: bls [options] \n" " -b specify a bootstrap file\n" " -c specify a config file\n" " -d specify debug level\n" @@ -254,14 +254,10 @@ static void do_close(JCR *jcr) /* List just block information */ static void do_blocks(char *infname) { - if (verbose) { - dump_volume_label(dev); - rec = new_record(); - } for ( ;; ) { if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) { - Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev)); - if (dev->state & ST_EOT) { + Dmsg1(100, "!read_block(): ERR=%s\n", dev->strerror()); + if (dev->at_eom()) { if (!mount_next_read_volume(dcr)) { Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"), dev->file, dev_name(dev), dcr->VolumeName); @@ -275,8 +271,7 @@ static void do_blocks(char *infname) get_session_record(dev, record, &sessrec); free_record(record); Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), dcr->VolumeName); - - } else if (dev->state & ST_EOF) { + } else if (dev->at_eof()) { Jmsg(jcr, M_INFO, 0, _("Got EOF at file %u on device %s, Volume \"%s\"\n"), dev->file, dev_name(dev), dcr->VolumeName); Dmsg0(20, "read_record got eof. try again\n"); @@ -359,11 +354,6 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) if (rec->Stream == STREAM_UNIX_ATTRIBUTES || rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) { - if (verbose > 1) { - const char *rtype = "Attributes"; - Pmsg5(-1, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", - rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); - } if (!unpack_attributes_record(jcr, rec->Stream, rec->data, attr)) { if (!forge_on) { Emsg0(M_ERROR_TERM, 0, _("Cannot continue.\n")); @@ -381,6 +371,10 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) build_attr_output_fnames(jcr, attr); if (file_is_included(&ff, attr->fname) && !file_is_excluded(&ff, attr->fname)) { + if (verbose) { + Pmsg5(-1, "FileIndex=%d VolSessionId=%d VolSessionTime=%d Stream=%d DataLen=%d\n", + rec->FileIndex, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); + } print_ls_output(jcr, attr); num_files++; } diff --git a/bacula/src/stored/bsr.h b/bacula/src/stored/bsr.h index dfafe13b91..9d18ea0b90 100644 --- a/bacula/src/stored/bsr.h +++ b/bacula/src/stored/bsr.h @@ -7,7 +7,7 @@ * */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -37,6 +37,7 @@ struct VOL_LIST { VOL_LIST *next; char VolumeName[MAX_NAME_LENGTH]; + char MediaType[MAX_NAME_LENGTH]; int Slot; uint32_t start_file; }; @@ -54,6 +55,7 @@ struct VOL_LIST { struct BSR_VOLUME { BSR_VOLUME *next; char VolumeName[MAX_NAME_LENGTH]; + char MediaType[MAX_NAME_LENGTH]; }; struct BSR_CLIENT { diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index a661374c2f..460c0ae937 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -323,10 +323,10 @@ static bool open_the_device() block = new_block(dev); lock_device(dev); - if (!(dev->state & ST_OPENED)) { + if (!dev->is_open()) { Dmsg1(200, "Opening device %s\n", dcr->VolumeName); if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) { - Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); + Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); unlock_device(dev); free_block(block); return false; @@ -358,9 +358,9 @@ static void labelcmd() } } - if (!(dev->state & ST_OPENED)) { + if (!dev->is_open()) { if (!first_open_device(dev)) { - Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev)); + Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev)); } } rewind_dev(dev); @@ -556,15 +556,15 @@ static void capcmd() printf("\n"); printf(_("Device status:\n")); - printf("%sOPENED ", dev->state & ST_OPENED ? "" : "!"); - printf("%sTAPE ", dev->state & ST_TAPE ? "" : "!"); - printf("%sLABEL ", dev->state & ST_LABEL ? "" : "!"); + printf("%sOPENED ", dev->is_open() ? "" : "!"); + printf("%sTAPE ", dev->is_tape() ? "" : "!"); + printf("%sLABEL ", dev->is_labeled() ? "" : "!"); printf("%sMALLOC ", dev->state & ST_MALLOC ? "" : "!"); - printf("%sAPPEND ", dev->state & ST_APPEND ? "" : "!"); - printf("%sREAD ", dev->state & ST_READ ? "" : "!"); - printf("%sEOT ", dev->state & ST_EOT ? "" : "!"); + printf("%sAPPEND ", dev->can_append() ? "" : "!"); + printf("%sREAD ", dev->can_read() ? "" : "!"); + printf("%sEOT ", dev->at_eom() ? "" : "!"); printf("%sWEOT ", dev->state & ST_WEOT ? "" : "!"); - printf("%sEOF ", dev->state & ST_EOF ? "" : "!"); + printf("%sEOF ", dev->at_eof() ? "" : "!"); printf("%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!"); printf("%sSHORT ", dev->state & ST_SHORT ? "" : "!"); printf("\n"); @@ -613,7 +613,7 @@ static void rectestcmd() if (write_record_to_block(block, rec)) { empty_block(block); blkno++; - Pmsg2(0, "Block %d i=%d\n", blkno, i); + Pmsg2(0, "Block %d i=%d\n", blkno, i); } else { break; } @@ -697,7 +697,7 @@ static int re_read_block_test() } if (dev_cap(dev, CAP_TWOEOF)) { if (!bsf_dev(dev, 1)) { - Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); + Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); goto bail_out; } } @@ -720,7 +720,7 @@ static int re_read_block_test() } for (int i=0; idata[i] != 3) { - Pmsg0(0, _("Bad data in record. Test failed!\n")); + Pmsg0(0, _("Bad data in record. Test failed!\n")); goto bail_out; } } @@ -733,11 +733,11 @@ bail_out: free_record(rec); if (stat == 0) { Pmsg0(0, _("This is not terribly serious since Bacula only uses\n" - "this function to verify the last block written to the\n" - "tape. Bacula will skip the last block verification\n" - "if you add:\n\n" - "Backward Space Record = No\n\n" - "to your Storage daemon's Device resource definition.\n")); + "this function to verify the last block written to the\n" + "tape. Bacula will skip the last block verification\n" + "if you add:\n\n" + "Backward Space Record = No\n\n" + "to your Storage daemon's Device resource definition.\n")); } return stat; } @@ -776,11 +776,11 @@ static int write_read_test() *p++ = i; } if (!write_record_to_block(block, rec)) { - Pmsg0(0, _("Error writing record to block.\n")); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(dcr)) { - Pmsg0(0, _("Error writing block to device.\n")); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } } @@ -792,11 +792,11 @@ static int write_read_test() *p++ = i; } if (!write_record_to_block(block, rec)) { - Pmsg0(0, _("Error writing record to block.\n")); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(dcr)) { - Pmsg0(0, _("Error writing block to device.\n")); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } } @@ -816,31 +816,31 @@ read_again: if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) { berrno be; if (dev_state(dev, ST_EOF)) { - Pmsg0(-1, _("Got EOF on tape.\n")); + Pmsg0(-1, _("Got EOF on tape.\n")); if (i == 1001) { goto read_again; } } - Pmsg2(0, _("Read block %d failed! ERR=%s\n"), i, be.strerror(dev->dev_errno)); + Pmsg2(0, _("Read block %d failed! ERR=%s\n"), i, be.strerror(dev->dev_errno)); goto bail_out; } memset(rec->data, 0, rec->data_len); if (!read_record_from_block(block, rec)) { berrno be; - Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.strerror(dev->dev_errno)); + Pmsg2(0, _("Read record failed. Block %d! ERR=%s\n"), i, be.strerror(dev->dev_errno)); goto bail_out; } p = (int *)rec->data; for (j=0; jdev_errno)); - Pmsg0(0, _("This may be because the tape drive block size is not\n" - " set to variable blocking as normally used by Bacula.\n" - " Please see the Tape Testing chapter in the manual and \n" - " look for using mt with defblksize and setoptions\n" - "If your tape drive block size is correct, then perhaps\n" - " your SCSI driver is *really* stupid and does not\n" - " correctly report the file:block after a FSF. In this\n" - " case try setting:\n" - " Fast Forward Space File = no\n" - " in your Device resource.\n")); + Pmsg0(0, _("This may be because the tape drive block size is not\n" + " set to variable blocking as normally used by Bacula.\n" + " Please see the Tape Testing chapter in the manual and \n" + " look for using mt with defblksize and setoptions\n" + "If your tape drive block size is correct, then perhaps\n" + " your SCSI driver is *really* stupid and does not\n" + " correctly report the file:block after a FSF. In this\n" + " case try setting:\n" + " Fast Forward Space File = no\n" + " in your Device resource.\n")); goto bail_out; } memset(rec->data, 0, rec->data_len); if (!read_record_from_block(block, rec)) { berrno be; - Pmsg1(0, _("Read record failed! ERR=%s\n"), be.strerror(dev->dev_errno)); + Pmsg1(0, _("Read record failed! ERR=%s\n"), be.strerror(dev->dev_errno)); goto bail_out; } p = (int *)rec->data; for (j=0; jdevice->max_changer_wait; + int timeout = dcr->device->max_changer_wait; int sleep_time = 0; Dmsg1(100, "Max changer wait = %d sec\n", timeout); if (!dev_cap(dev, CAP_AUTOCHANGER)) { return 1; } - if (!(jcr->device && jcr->device->changer_name && jcr->device->changer_command)) { + if (!(dcr->device && dcr->device->changer_name && dcr->device->changer_command)) { Pmsg0(-1, "\nAutochanger enabled, but no name or no command device specified.\n"); return 1; } Pmsg0(-1, "\nAh, I see you have an autochanger configured.\n" - "To test the autochanger you must have a blank tape\n" - " that I can write on in Slot 1.\n"); + "To test the autochanger you must have a blank tape\n" + " that I can write on in Slot 1.\n"); if (!get_cmd("\nDo you wish to continue with the Autochanger test? (y/n): ")) { return 0; } @@ -1119,8 +1119,7 @@ try_again: dcr->VolCatInfo.Slot = slot; /* Find out what is loaded, zero means device is unloaded */ Pmsg0(-1, _("3301 Issuing autochanger \"loaded\" command.\n")); - changer = edit_device_codes(jcr, changer, jcr->device->changer_command, - "loaded"); + changer = edit_device_codes(dcr, changer, "loaded"); status = run_program(changer, timeout, results); Dmsg3(100, "run_prog: %s stat=%d result=\"%s\"\n", changer, status, results); if (status == 0) { @@ -1144,14 +1143,13 @@ try_again: force_close_dev(dev); Pmsg2(-1, _("3302 Issuing autochanger \"unload %d %d\" command.\n"), loaded, dev->drive_index); - changer = edit_device_codes(jcr, changer, - jcr->device->changer_command, "unload"); + changer = edit_device_codes(dcr, changer, "unload"); status = run_program(changer, timeout, results); Pmsg2(-1, "unload status=%s %d\n", status==0?"OK":"Bad", status); if (status != 0) { berrno be; - Pmsg1(-1, _("3992 Bad autochanger command: %s\n"), changer); - Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.strerror(status)); + Pmsg1(-1, _("3992 Bad autochanger command: %s\n"), changer); + Pmsg2(-1, _("3992 result=\"%s\": ERR=%s\n"), results, be.strerror(status)); } } @@ -1163,7 +1161,7 @@ try_again: dcr->VolCatInfo.Slot = slot; Pmsg2(-1, _("3303 Issuing autochanger \"load slot %d %d\" command.\n"), slot, dev->drive_index); - changer = edit_device_codes(jcr, changer, jcr->device->changer_command, "load"); + changer = edit_device_codes(dcr, changer, "load"); Dmsg1(100, "Changer=%s\n", changer); force_close_dev(dev); status = run_program(changer, timeout, results); @@ -1189,8 +1187,8 @@ try_again: Pmsg1(0, "Bad status from rewind. ERR=%s\n", strerror_dev(dev)); clrerror_dev(dev, -1); Pmsg0(-1, "\nThe test failed, probably because you need to put\n" - "a longer sleep time in the mtx-script in the load) case.\n" - "Adding a 30 second sleep and trying again ...\n"); + "a longer sleep time in the mtx-script in the load) case.\n" + "Adding a 30 second sleep and trying again ...\n"); sleep_time += 30; goto try_again; } else { @@ -1206,8 +1204,8 @@ try_again: if (sleep_time) { Pmsg1(-1, "\nThe test worked this time. Please add:\n\n" - " sleep %d\n\n" - "to your mtx-changer script in the load) case.\n\n", + " sleep %d\n\n" + "to your mtx-changer script in the load) case.\n\n", sleep_time); } else { Pmsg0(-1, "\nThe test autochanger worked!!\n\n"); @@ -1240,8 +1238,8 @@ static int fsf_test() bool set_off = false; Pmsg0(-1, _("\n\n=== Forward space files test ===\n\n" - "This test is essential to Bacula.\n\n" - "I'm going to write five files then test forward spacing\n\n")); + "This test is essential to Bacula.\n\n" + "I'm going to write five files then test forward spacing\n\n")); argc = 1; rewindcmd(); wrcmd(); @@ -1302,8 +1300,8 @@ test_again: } if (set_off) { Pmsg0(-1, "The test worked this time. Please add:\n\n" - " Fast Forward Space File = no\n\n" - "to your Device resource for this drive.\n"); + " Fast Forward Space File = no\n\n" + "to your Device resource for this drive.\n"); } Pmsg0(-1, "\n"); @@ -1323,15 +1321,15 @@ bail_out: Pmsg0(-1, _("\nThe forward space file test failed.\n")); if (dev_cap(dev, CAP_FASTFSF)) { Pmsg0(-1, "You have Fast Forward Space File enabled.\n" - "I am turning it off then retrying the test.\n"); + "I am turning it off then retrying the test.\n"); dev->capabilities &= ~CAP_FASTFSF; set_off = true; goto test_again; } Pmsg0(-1, "You must correct this error or Bacula will not work.\n" - "Some systems, e.g. OpenBSD, require you to set\n" - " Use MTIOCGET= no\n" - "in your device resource. Use with caution.\n"); + "Some systems, e.g. OpenBSD, require you to set\n" + " Use MTIOCGET= no\n" + "in your device resource. Use with caution.\n"); return -2; } @@ -1360,36 +1358,36 @@ static void testcmd() } if (stat == -1) { /* first test failed */ if (dev_cap(dev, CAP_EOM) || dev_cap(dev, CAP_FASTFSF)) { - Pmsg0(-1, "\nAppend test failed. Attempting again.\n" - "Setting \"Hardware End of Medium = no\n" - " and \"Fast Forward Space File = no\n" - "and retrying append test.\n\n"); + Pmsg0(-1, "\nAppend test failed. Attempting again.\n" + "Setting \"Hardware End of Medium = no\n" + " and \"Fast Forward Space File = no\n" + "and retrying append test.\n\n"); dev->capabilities &= ~CAP_EOM; /* turn off eom */ dev->capabilities &= ~CAP_FASTFSF; /* turn off fast fsf */ stat = append_test(); if (stat == 1) { - Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n" - " Hardware End of Medium = No\n\n" - " Fast Forward Space File = No\n" - "to your Device resource in the Storage conf file.\n"); + Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n" + " Hardware End of Medium = No\n\n" + " Fast Forward Space File = No\n" + "to your Device resource in the Storage conf file.\n"); goto all_done; } if (stat == -1) { - Pmsg0(-1, "\n\nThat appears *NOT* to have corrected the problem.\n"); + Pmsg0(-1, "\n\nThat appears *NOT* to have corrected the problem.\n"); goto failed; } /* Wrong count after append */ if (stat == -2) { - Pmsg0(-1, "\n\nIt looks like the append failed. Attempting again.\n" - "Setting \"BSF at EOM = yes\" and retrying append test.\n"); + Pmsg0(-1, "\n\nIt looks like the append failed. Attempting again.\n" + "Setting \"BSF at EOM = yes\" and retrying append test.\n"); dev->capabilities |= CAP_BSFATEOM; /* backspace on eom */ stat = append_test(); if (stat == 1) { - Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n" - " Hardware End of Medium = No\n" - " Fast Forward Space File = No\n" - " BSF at EOM = yes\n\n" - "to your Device resource in the Storage conf file.\n"); + Pmsg0(-1, "\n\nIt looks like the test worked this time, please add:\n\n" + " Hardware End of Medium = No\n" + " Fast Forward Space File = No\n" + " BSF at EOM = yes\n\n" + "to your Device resource in the Storage conf file.\n"); goto all_done; } } @@ -1398,43 +1396,43 @@ static void testcmd() failed: Pmsg0(-1, "\nAppend test failed.\n\n"); Pmsg0(-1, "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" - "Unable to correct the problem. You MUST fix this\n" - "problem before Bacula can use your tape drive correctly\n"); + "Unable to correct the problem. You MUST fix this\n" + "problem before Bacula can use your tape drive correctly\n"); Pmsg0(-1, "\nPerhaps running Bacula in fixed block mode will work.\n" - "Do so by setting:\n\n" - "Minimum Block Size = nnn\n" - "Maximum Block Size = nnn\n\n" - "in your Storage daemon's Device definition.\n" - "nnn must match your tape driver's block size, which\n" - "can be determined by reading your tape manufacturers\n" - "information, and the information on your kernel dirver.\n" - "Fixed block sizes, however, are not normally an ideal solution.\n" - "\n" - "Some systems, e.g. OpenBSD, require you to set\n" - " Use MTIOCGET= no\n" - "in your device resource. Use with caution.\n"); + "Do so by setting:\n\n" + "Minimum Block Size = nnn\n" + "Maximum Block Size = nnn\n\n" + "in your Storage daemon's Device definition.\n" + "nnn must match your tape driver's block size, which\n" + "can be determined by reading your tape manufacturers\n" + "information, and the information on your kernel dirver.\n" + "Fixed block sizes, however, are not normally an ideal solution.\n" + "\n" + "Some systems, e.g. OpenBSD, require you to set\n" + " Use MTIOCGET= no\n" + "in your device resource. Use with caution.\n"); return; } all_done: Pmsg0(-1, _("\nThe above Bacula scan should have output identical to what follows.\n" - "Please double check it ...\n" - "=== Sample correct output ===\n" - "1 block of 64448 bytes in file 1\n" - "End of File mark.\n" - "2 blocks of 64448 bytes in file 2\n" - "End of File mark.\n" - "3 blocks of 64448 bytes in file 3\n" - "End of File mark.\n" - "1 block of 64448 bytes in file 4\n" - "End of File mark.\n" - "Total files=4, blocks=7, bytes = 451,136\n" - "=== End sample correct output ===\n\n")); + "Please double check it ...\n" + "=== Sample correct output ===\n" + "1 block of 64448 bytes in file 1\n" + "End of File mark.\n" + "2 blocks of 64448 bytes in file 2\n" + "End of File mark.\n" + "3 blocks of 64448 bytes in file 3\n" + "End of File mark.\n" + "1 block of 64448 bytes in file 4\n" + "End of File mark.\n" + "Total files=4, blocks=7, bytes = 451,136\n" + "=== End sample correct output ===\n\n")); Pmsg0(-1, _("If the above scan output is not identical to the\n" - "sample output, you MUST correct the problem\n" - "or Bacula will not be able to write multiple Jobs to \n" - "the tape.\n\n")); + "sample output, you MUST correct the problem\n" + "or Bacula will not be able to write multiple Jobs to \n" + "the tape.\n\n")); if (stat == 1) { re_read_block_test(); @@ -1574,12 +1572,12 @@ static void scancmd() if ((stat = read(dev->fd, buf, sizeof(buf))) < 0) { berrno be; clrerror_dev(dev, -1); - Mmsg2(dev->errmsg, "read error on %s. ERR=%s.\n", + Mmsg2(dev->errmsg, "read error on %s. ERR=%s.\n", dev->dev_name, be.strerror()); - Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev)); + Pmsg2(0, "Bad status from read %d. ERR=%s\n", stat, strerror_dev(dev)); if (blocks > 0) - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); return; } Dmsg1(200, "read status = %d\n", stat); @@ -1587,15 +1585,15 @@ static void scancmd() if (stat != block_size) { update_pos_dev(dev); if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); blocks = 0; } block_size = stat; } if (stat == 0) { /* EOF */ update_pos_dev(dev); - printf("End of File mark.\n"); + printf("End of File mark.\n"); /* Two reads of zero means end of tape */ if (dev->state & ST_EOF) dev->state |= ST_EOT; @@ -1604,7 +1602,7 @@ static void scancmd() dev->file++; } if (dev->state & ST_EOT) { - printf("End of tape\n"); + printf("End of tape\n"); break; } } else { /* Got data */ @@ -1643,40 +1641,40 @@ static void scan_blocks() tot_files = dev->file; for (;;) { if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) { - Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev)); + Dmsg1(100, "!read_block(): ERR=%s\n", strerror_dev(dev)); if (dev->state & ST_EOT) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); blocks = 0; } goto bail_out; } if (dev->state & ST_EOF) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); blocks = 0; } - printf(_("End of File mark.\n")); + printf(_("End of File mark.\n")); continue; } if (dev->state & ST_SHORT) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); blocks = 0; } - printf(_("Short block read.\n")); + printf(_("Short block read.\n")); continue; } - printf(_("Error reading block. ERR=%s\n"), strerror_dev(dev)); + printf(_("Error reading block. ERR=%s\n"), strerror_dev(dev)); goto bail_out; } if (block->block_len != block_size) { if (blocks > 0) { - printf("%d block%s of %d bytes in file %d\n", - blocks, blocks>1?"s":"", block_size, dev->file); + printf("%d block%s of %d bytes in file %d\n", + blocks, blocks>1?"s":"", block_size, dev->file); blocks = 0; } block_size = block->block_len; @@ -1690,14 +1688,14 @@ static void scan_blocks() if (verbose == 1) { DEV_RECORD *rec = new_record(); read_record_from_block(block, rec); - Pmsg8(-1, "Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n", + Pmsg8(-1, "Blk_block: %u dev_blk=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n", block->BlockNumber, dev->block_num, block->block_len, FI_to_ascii(rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len); rec->remainder = 0; free_record(rec); } else if (verbose > 1) { - dump_block(block, ""); + dump_block(block, ""); } } @@ -1758,7 +1756,7 @@ static void fillcmd() "This may take a long time -- hours! ...\n\n"); get_cmd("Do you want to run the simplified test (s) with one tape\n" - "or the complete multiple tape (m) test: (s/m) "); + "or the complete multiple tape (m) test: (s/m) "); if (cmd[0] == 's') { Pmsg0(-1, "Simple test (single tape) selected.\n"); simple = true; @@ -1789,7 +1787,7 @@ static void fillcmd() * subroutine. */ Dmsg0(100, "just before acquire_device\n"); - if (!acquire_device_for_append(jcr)) { + if (!acquire_device_for_append(jcr, dev)) { set_jcr_job_status(jcr, JS_ErrorTerminated); return; } @@ -1859,7 +1857,7 @@ static void fillcmd() /* * When we get here we have just filled a block */ - Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len, + Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len, rec.remainder); /* Write block to tape */ @@ -1876,14 +1874,14 @@ static void fillcmd() now = 1; /* prevent divide error */ } kbs = (double)dev->VolCatInfo.VolCatBytes / (1000.0 * (double)now); - Pmsg4(-1, "Wrote blk_block=%u, dev_blk_num=%u VolBytes=%s rate=%.1f KB/s\n", + Pmsg4(-1, "Wrote blk_block=%u, dev_blk_num=%u VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber, dev->block_num, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), (float)kbs); } /* Every 15000 blocks (approx 1GB) write an EOF. */ if ((block->BlockNumber % 15000) == 0) { - Pmsg0(-1, "Flush block, write EOF\n"); + Pmsg0(-1, "Flush block, write EOF\n"); flush_block(block, 0); weof_dev(dev, 1); } @@ -1894,7 +1892,7 @@ static void fillcmd() } } if (!ok) { - Pmsg0(000, _("Not OK\n")); + Pmsg0(000, _("Not OK\n")); break; } jcr->JobBytes += rec.data_len; /* increment bytes this job */ @@ -1904,7 +1902,7 @@ static void fillcmd() /* Get out after writing 10 blocks to the second tape */ if (BlockNumber > 10 && stop != 0) { /* get out */ - Pmsg0(-1, "Done writing ...\n"); + Pmsg0(-1, "Done writing ...\n"); break; } } @@ -1917,12 +1915,12 @@ static void fillcmd() set_jcr_job_status(jcr, JS_ErrorTerminated); } if (!write_session_label(dcr, EOS_LABEL)) { - Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev)); + Pmsg1(000, _("Error writting end session label. ERR=%s\n"), strerror_dev(dev)); ok = false; } /* Write out final block of this session */ if (!write_block_to_device(dcr)) { - Pmsg0(-1, _("Set ok=false after write_block_to_device.\n")); + Pmsg0(-1, _("Set ok=false after write_block_to_device.\n")); ok = false; } Pmsg0(-1, _("Wrote End of Session label.\n")); @@ -2001,14 +1999,14 @@ static void unfillcmd() read(fd, first_block->buf, first_block->buf_len); close(fd); if (state_level != btape_state_level) { - Pmsg0(-1, "\nThe state file level has changed. You must redo\n" - "the fill command.\n"); + Pmsg0(-1, "\nThe state file level has changed. You must redo\n" + "the fill command.\n"); return; } } else { berrno be; Pmsg2(-1, "\nCould not find the state file: %s ERR=%s\n" - "You must redo the fill command.\n", buf, be.strerror()); + "You must redo the fill command.\n", buf, be.strerror()); return; } do_unfill(); @@ -2049,7 +2047,7 @@ static void do_unfill() autochanger = autoload_device(dcr, 1, NULL); if (!autochanger) { force_close_dev(dev); - get_cmd(_("Mount first tape. Press enter when ready: ")); + get_cmd(_("Mount first tape. Press enter when ready: ")); } free_vol_list(jcr); jcr->dcr = new_dcr(jcr, dev); @@ -2059,8 +2057,8 @@ static void do_unfill() close_dev(dev); dev->state &= ~(ST_READ|ST_APPEND); dev->num_writers = 0; - if (!acquire_device_for_read(jcr)) { - Pmsg1(-1, "%s", dev->errmsg); + if (!acquire_device_for_read(jcr, dev)) { + Pmsg1(-1, "%s", dev->errmsg); goto bail_out; } } @@ -2089,9 +2087,9 @@ static void do_unfill() } if (compare_blocks(last_block, block)) { if (simple) { - Pmsg0(-1, _("\nThe last block on the tape matches. Test succeeded.\n\n")); + Pmsg0(-1, _("\nThe last block on the tape matches. Test succeeded.\n\n")); } else { - Pmsg0(-1, _("\nThe last block of the first tape matches.\n\n")); + Pmsg0(-1, _("\nThe last block of the first tape matches.\n\n")); } } if (simple) { @@ -2120,7 +2118,7 @@ static void do_unfill() } dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr)) { + if (!acquire_device_for_read(jcr, dev)) { Pmsg1(-1, "%s", dev->errmsg); goto bail_out; } @@ -2203,9 +2201,9 @@ static bool compare_blocks(DEV_BLOCK *last_block, DEV_BLOCK *block) dump_block(block, _("Block read back")); Pmsg1(-1, "\n\nThe blocks differ at byte %u\n", p - last_block->buf); Pmsg0(-1, "\n\n!!!! The last block written and the block\n" - "that was read back differ. The test FAILED !!!!\n" - "This must be corrected before you use Bacula\n" - "to write multi-tape Volumes.!!!!\n"); + "that was read back differ. The test FAILED !!!!\n" + "This must be corrected before you use Bacula\n" + "to write multi-tape Volumes.!!!!\n"); return false; } if (verbose) { @@ -2255,11 +2253,11 @@ static int flush_block(DEV_BLOCK *block, int dump) first_block = dup_block(block); /* first block second tape */ } if (verbose) { - Pmsg3(000, "Block not written: FileIndex=%u blk_block=%u Size=%u\n", + Pmsg3(000, "Block not written: FileIndex=%u blk_block=%u Size=%u\n", (unsigned)file_index, block->BlockNumber, block->block_len); - dump_block(last_block, "Last block written"); - Pmsg0(-1, "\n"); - dump_block(block, "Block not written"); + dump_block(last_block, "Last block written"); + Pmsg0(-1, "\n"); + dump_block(block, "Block not written"); } if (stop == 0) { eot_block = block->BlockNumber; @@ -2270,7 +2268,7 @@ static int flush_block(DEV_BLOCK *block, int dump) now = time(NULL); now -= jcr->run_time; if (now <= 0) { - now = 1; /* don't divide by zero */ + now = 1; /* don't divide by zero */ } kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now); vol_size = dev->VolCatInfo.VolCatBytes; @@ -2283,7 +2281,7 @@ static int flush_block(DEV_BLOCK *block, int dump) } else { /* Full test in progress */ if (!fixup_device_block_write_error(jcr->dcr)) { - Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev)); + Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev)); ok = false; unlock_device(dev); return 0; @@ -2344,15 +2342,15 @@ static void qfillcmd() Pmsg1(0, "Begin writing %d Bacula blocks to tape ...\n", count); for (i=0; i < count; i++) { if (i % 100 == 0) { - printf("+"); + printf("+"); fflush(stdout); } if (!write_record_to_block(block, rec)) { - Pmsg0(0, _("Error writing record to block.\n")); + Pmsg0(0, _("Error writing record to block.\n")); goto bail_out; } if (!write_block_to_dev(dcr)) { - Pmsg0(0, _("Error writing block to device.\n")); + Pmsg0(0, _("Error writing block to device.\n")); goto bail_out; } } @@ -2399,7 +2397,7 @@ static void rawfill_cmd() stat = write(dev->fd, block->buf, block->buf_len); if (stat == (int)block->buf_len) { if ((block_num++ % 100) == 0) { - printf("+"); + printf("+"); fflush(stdout); } p[0] += p[13]; @@ -2452,7 +2450,7 @@ static void bfill_cmd() break; } if ((block_num++ % 100) == 0) { - printf("+"); + printf("+"); fflush(stdout); } p[0] += p[13]; @@ -2517,7 +2515,7 @@ do_tape_cmds() break; } if (!found) - Pmsg1(0, _("%s is an illegal command\n"), cmd); + Pmsg1(0, _("%s is an illegal command\n"), cmd); if (quit) break; } @@ -2699,7 +2697,7 @@ static bool my_mount_next_read_volume(DCR *dcr) create_vol_list(jcr); close_dev(dev); dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr)) { + if (!acquire_device_for_read(jcr, dev)) { Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), dcr->VolumeName); return false; } diff --git a/bacula/src/stored/butil.c b/bacula/src/stored/butil.c index 2fae0494d3..a63dd2829d 100644 --- a/bacula/src/stored/butil.c +++ b/bacula/src/stored/butil.c @@ -104,8 +104,8 @@ JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr, if (!bsr && VolumeName) { bstrncpy(dcr->VolumeName, VolumeName, sizeof(dcr->VolumeName)); } - strcpy(dcr->pool_name, "Default"); - strcpy(dcr->pool_type, "Backup"); + bstrncpy(dcr->pool_name, "Default", sizeof(dcr->pool_name)); + bstrncpy(dcr->pool_type, "Backup", sizeof(dcr->pool_type)); return jcr; } @@ -136,9 +136,9 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeN /* Try stripping file part */ p = dev_name + strlen(dev_name); - while (p >= dev_name && *p != '/') + while (p >= dev_name && *p != '/') p--; - if (*p == '/') { + if (*p == '/') { bstrncpy(VolName, p+1, sizeof(VolName)); *p = 0; } @@ -150,7 +150,6 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeN dev_name, configfile); return NULL; } - jcr->device = device; dev = init_dev(NULL, device); if (!dev) { @@ -172,7 +171,7 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name, const char *VolumeN create_vol_list(jcr); if (mode) { /* read only access? */ - if (!acquire_device_for_read(jcr)) { + if (!acquire_device_for_read(jcr, dev)) { return NULL; } } @@ -235,10 +234,11 @@ static DEVRES *find_device_res(char *device_name, int read_access) if (!found) { /* Search for name of Device resource rather than archive name */ if (device_name[0] == '"') { - strcpy(device_name, device_name+1); int len = strlen(device_name); + bstrncpy(device_name, device_name+1, len+1); + len--; if (len > 0) { - device_name[len-1] = 0; /* zap trailing " */ + device_name[len-1] = 0; /* zap trailing " */ } } foreach_res(device, R_DEVICE) { @@ -255,7 +255,7 @@ static DEVRES *find_device_res(char *device_name, int read_access) return NULL; } Pmsg2(0, _("Using device: \"%s\" for %s.\n"), device_name, - read_access?"reading":"writing"); + read_access?"reading":"writing"); return device; } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 4fff2ba2f5..b1bb1e0db7 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -86,8 +86,8 @@ int mount_dev(DEVICE* dev, int timeout); int unmount_dev(DEVICE* dev, int timeout); int write_part(DEVICE *dev); char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg); -void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name); -void update_free_space_dev(DEVICE* dev); +static void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name); +static void update_free_space_dev(DEVICE* dev); /* * Allocate and initialize the DEVICE structure @@ -114,34 +114,11 @@ init_dev(DEVICE *dev, DEVRES *device) if (dev) { dev->dev_errno = errno; } - Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name, - be.strerror()); + Jmsg2(NULL, M_FATAL, 0, _("Unable to stat device %s: ERR=%s\n"), + device->device_name, be.strerror()); return NULL; } - /* If the device requires mount : - * - Check that the mount point is available - * - Check that (un)mount commands are defined - */ - if (device->cap_bits & CAP_REQMOUNT) { - if (stat(device->mount_point, &statp) < 0) { - berrno be; - if (dev) { - dev->dev_errno = errno; - } - Emsg2(M_FATAL, 0, "Unable to stat mount point %s : %s\n", device->mount_point, - be.strerror()); - return NULL; - } - if (!device->mount_command || !device->unmount_command) { - Emsg0(M_FATAL, 0, "Mount and unmount commands must defined for a device which requires mount.\n"); - return NULL; - } - if (!device->write_part_command) { - Emsg0(M_FATAL, 0, "Write part command must be defined for a device which requires mount.\n"); - return NULL; - } - } tape = false; fifo = false; @@ -169,7 +146,7 @@ init_dev(DEVICE *dev, DEVRES *device) /* Copy user supplied device parameters from Resource */ dev->dev_name = get_memory(strlen(device->device_name)+1); - strcpy(dev->dev_name, device->device_name); + pm_strcpy(dev->dev_name, device->device_name); dev->capabilities = device->cap_bits; dev->min_block_size = device->min_block_size; dev->max_block_size = device->max_block_size; @@ -203,6 +180,27 @@ init_dev(DEVICE *dev, DEVRES *device) dev->state |= ST_FILE; } + /* If the device requires mount : + * - Check that the mount point is available + * - Check that (un)mount commands are defined + */ + if (dev->is_file() && device->cap_bits & CAP_REQMOUNT) { + if (stat(device->mount_point, &statp) < 0) { + berrno be; + dev->dev_errno = errno; + Jmsg2(NULL, M_FATAL, 0, _("Unable to stat mount point %s: ERR=%s\n"), + device->mount_point, be.strerror()); + return NULL; + } + if (!device->mount_command || !device->unmount_command) { + Jmsg0(NULL, M_ERROR_TERM, 0, _("Mount and unmount commands must defined for a device which requires mount.\n")); + } + if (!device->write_part_command) { + Jmsg0(NULL, M_ERROR_TERM, 0, _("Write part command must be defined for a device which requires mount.\n")); + } + dev->state |= ST_DVD; + } + if (dev->max_block_size > 1000000) { Emsg3(M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"), dev->max_block_size, dev->dev_name, DEFAULT_BLOCK_SIZE); @@ -226,25 +224,25 @@ init_dev(DEVICE *dev, DEVRES *device) berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat)); - Emsg0(M_FATAL, 0, dev->errmsg); + Emsg0(M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat)); - Emsg0(M_FATAL, 0, dev->errmsg); + Emsg0(M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); - Emsg0(M_FATAL, 0, dev->errmsg); + Emsg0(M_ERROR_TERM, 0, dev->errmsg); } if ((errstat = rwl_init(&dev->lock)) != 0) { berrno be; dev->dev_errno = errstat; Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat)); - Emsg0(M_FATAL, 0, dev->errmsg); + Emsg0(M_ERROR_TERM, 0, dev->errmsg); } dev->fd = -1; @@ -257,17 +255,16 @@ init_dev(DEVICE *dev, DEVRES *device) /* * Write the current volume/part filename to archive_name. */ - -void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name) { +static void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name) +{ char partnumber[20]; - if (dev_cap(dev, CAP_REQMOUNT)) { + if (dev->is_dvd()) { /* If we try to open the last part, just open it from disk, * otherwise, open it from the spooling directory */ if (dev->part < dev->num_parts) { pm_strcpy(archive_name, dev->device->mount_point); - } - else { + } else { /* Use the working directory if spool directory is not defined */ if (dev->device->spool_directory) { pm_strcpy(archive_name, dev->device->spool_directory); @@ -275,8 +272,7 @@ void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name) { pm_strcpy(archive_name, working_directory); } } - } - else { + } else { pm_strcpy(archive_name, dev->dev_name); } @@ -285,16 +281,20 @@ void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name) { } pm_strcat(archive_name, VolName); /* if part != 0, append .# to the filename (where # is the part number) */ - if (dev->part != 0) { + if (dev->is_dvd() && dev->part != 0) { pm_strcat(archive_name, "."); bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part); pm_strcat(archive_name, partnumber); } } -/* Open the device with the operating system and +/* + * Open the device with the operating system and * initialize buffer pointers. * + * Returns: -1 on error + * fd on success + * * Note, for a tape, the VolName is the name we give to the * volume (not really used here), but for a file, the * VolName represents the name of the file to be created/opened. @@ -304,7 +304,7 @@ void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name) { int open_dev(DEVICE *dev, char *VolName, int mode) { - if (dev->state & ST_OPENED) { + if (dev->is_open()) { /* * *****FIXME***** how to handle two threads wanting * different volumes mounted???? E.g. one is waiting @@ -327,7 +327,7 @@ open_dev(DEVICE *dev, char *VolName, int mode) Dmsg3(29, "open_dev: tape=%d dev_name=%s vol=%s\n", dev_is_tape(dev), dev->dev_name, dev->VolCatInfo.VolCatName); dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF); - if (dev->state & (ST_TAPE|ST_FIFO)) { + if (dev->is_tape() || dev->is_fifo()) { dev->file_size = 0; int timeout; Dmsg0(29, "open_dev: device is tape\n"); @@ -342,7 +342,7 @@ open_dev(DEVICE *dev, char *VolName, int mode) } timeout = dev->max_open_wait; errno = 0; - if (dev->state & ST_FIFO && timeout) { + if (dev->is_fifo() && timeout) { /* Set open timer */ dev->tid = start_thread_timer(pthread_self(), timeout); } @@ -405,9 +405,9 @@ open_dev(DEVICE *dev, char *VolName, int mode) } get_filename(dev, VolName, archive_name); - if (dev_cap(dev, CAP_REQMOUNT) && (dev->num_parts > 0)) { + if (dev->is_dvd()) { if (mount_dev(dev, 1) < 0) { - Mmsg(dev->errmsg, _("Could not mount device %s.\n"), + Mmsg(dev->errmsg, _("Could not mount archive device %s.\n"), dev->dev_name); Emsg0(M_FATAL, 0, dev->errmsg); dev->fd = -1; @@ -418,8 +418,9 @@ open_dev(DEVICE *dev, char *VolName, int mode) Dmsg2(29, "open_dev: device is disk %s (mode:%d)\n", archive_name.c_str(), mode); dev->openmode = mode; - /* If we are not trying to access the last part, set mode to OPEN_READ_ONLY, - * as writing would be an error. + /* + * If we are not trying to access the last part, set mode to + * OPEN_READ_ONLY as writing would be an error. */ if (dev->part < dev->num_parts) { mode = OPEN_READ_ONLY; @@ -448,15 +449,15 @@ open_dev(DEVICE *dev, char *VolName, int mode) if (fstat(dev->fd, &filestat) < 0) { berrno be; dev->dev_errno = errno; - Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); + Mmsg2(&dev->errmsg, _("Could not fstat: %s, ERR=%s\n"), archive_name.c_str(), be.strerror()); Emsg0(M_FATAL, 0, dev->errmsg); - } - else { + } else { dev->part_size = filestat.st_size; } } Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size); - if ((dev->mode != OPEN_READ_ONLY) && ((dev->free_space_errno == 0) || (dev->num_parts == dev->part))) { + if (dev->is_dvd() && (dev->mode != OPEN_READ_ONLY) && + ((dev->free_space_errno == 0) || (dev->num_parts == dev->part))) { update_free_space_dev(dev); } } @@ -540,7 +541,8 @@ int do_mount_dev(DEVICE* dev, int mount, int dotimeout) { * Note that if the right volume is mounted, open_guess_name_dev returns the same * result as an usual open_dev. */ -int open_guess_name_dev(DEVICE *dev) { +int open_guess_name_dev(DEVICE *dev) +{ Dmsg1(29, "open_guess_name_dev: dev=%s\n", dev->dev_name); POOL_MEM guessedname(PM_FNAME); DIR* dp; @@ -549,7 +551,7 @@ int open_guess_name_dev(DEVICE *dev) { int index; int name_max; - if (!dev_cap(dev, CAP_REQMOUNT)) { + if (!dev->is_dvd()) { Dmsg1(100, "open_guess_name_dev: device does not require mount, returning 0. dev=%s\n", dev->dev_name); return 0; } @@ -566,8 +568,7 @@ int open_guess_name_dev(DEVICE *dev) { if (dev->free_space_errno >= 0) { Dmsg1(100, "open_guess_name_dev: device cannot be mounted, but it seems to be writable, returning 0. dev=%s\n", dev->dev_name); return 0; - } - else { + } else { Dmsg1(100, "open_guess_name_dev: device cannot be mounted, and is not writable, returning 0. dev=%s\n", dev->dev_name); /* read_dev_volume_label_guess must now check dev->free_space_errno to understand that the media is not writable. */ return 0; @@ -682,12 +683,12 @@ int open_guess_name_dev(DEVICE *dev) { * If timeout, wait until the mount command returns 0. * If !timeout, try to mount the device only once. */ -int mount_dev(DEVICE* dev, int timeout) { +int mount_dev(DEVICE* dev, int timeout) +{ if (dev->state & ST_MOUNTED) { Dmsg0(100, "mount_dev: Device already mounted\n"); return 0; - } - else { + } else { return do_mount_dev(dev, 1, timeout); } } @@ -696,23 +697,23 @@ int mount_dev(DEVICE* dev, int timeout) { * If timeout, wait until the unmount command returns 0. * If !timeout, try to unmount the device only once. */ -int unmount_dev(DEVICE* dev, int timeout) { +int unmount_dev(DEVICE* dev, int timeout) +{ if (dev->state & ST_MOUNTED) { return do_mount_dev(dev, 0, timeout); - } - else { + } else { Dmsg0(100, "mount_dev: Device already unmounted\n"); return 0; } } /* Update the free space on the device */ -void update_free_space_dev(DEVICE* dev) { +static void update_free_space_dev(DEVICE* dev) +{ POOL_MEM ocmd(PM_FNAME); POOLMEM* results; char* icmd; int timeout; - char* statstr; long long int free; icmd = dev->device->free_space_command; @@ -734,61 +735,45 @@ void update_free_space_dev(DEVICE* dev) { timeout = 3; while (1) { + char ed1[50]; if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) { Dmsg1(100, "Free space program run : %s\n", results); - /* We also need negatives values, so we can't use dev->free_space, which is unsigned */ - free = strtoll(results, &statstr, 10); - if (results != statstr) { /* Something parsed */ - if (free >= 0) { - dev->free_space = free; - dev->free_space_errno = 1; - Mmsg0(dev->errmsg, ""); - break; - } - else { - dev->free_space_errno = free; - dev->free_space = 0; - if (*statstr == '\n') { - statstr++; - } - if (statstr[strlen(statstr)-1] == '\n') { - statstr[strlen(statstr)-1] = 0; - } - Mmsg1(dev->errmsg, "Error while getting free space (%s)", statstr); - } - } - else { - dev->free_space = 0; - dev->free_space_errno = -EPIPE; - Mmsg1(dev->errmsg, "Error while getting free space (output=%s)", results); + free = str_to_int64(results); + if (free >= 0) { + dev->free_space = free; + dev->free_space_errno = 1; + Mmsg0(dev->errmsg, ""); + break; } } - else { - dev->free_space = 0; - dev->free_space_errno = -EPIPE; - Mmsg1(dev->errmsg, "Cannot run free space command (%s)", results); - } + dev->free_space = 0; + dev->free_space_errno = -EPIPE; + Mmsg1(dev->errmsg, "Cannot run free space command (%s)\n", results); if (--timeout > 0) { - Dmsg4(40, "Cannot get free space on device %s. free_space=%lld, free_space_errno=%d ERR=%s\n", dev->dev_name, - dev->free_space, dev->free_space_errno, dev->errmsg); + Dmsg4(40, "Cannot get free space on device %s. free_space=%s, " + "free_space_errno=%d ERR=%s\n", dev->dev_name, + edit_uint64(dev->free_space, ed1), dev->free_space_errno, + dev->errmsg); bmicrosleep(1, 0); continue; } dev->dev_errno = -dev->free_space_errno; - Dmsg4(40, "Cannot get free space on device %s. free_space=%lld, free_space_errno=%d ERR=%s\n", - dev->dev_name, dev->free_space, dev->free_space_errno, dev->errmsg); - free_pool_memory(results); - return; + Dmsg4(40, "Cannot get free space on device %s. free_space=%s, " + "free_space_errno=%d ERR=%s\n", + dev->dev_name, edit_uint64(dev->free_space, ed1), + dev->free_space_errno, dev->errmsg); + break; } free_pool_memory(results); - Dmsg2(29, "update_free_space_dev: free_space=%lld, free_space_errno=%d\n", dev->free_space, dev->free_space_errno); + return; } -int write_part(DEVICE *dev) { +int write_part(DEVICE *dev) +{ Dmsg1(29, "write_part: device is %s\n", dev->dev_name); if (unmount_dev(dev, 1) < 0) { @@ -840,8 +825,9 @@ int open_next_part(DEVICE *dev) { Dmsg3(29, "open_next_part %s %s %d\n", dev->dev_name, dev->VolCatInfo.VolCatName, dev->openmode); /* When appending, do not open a new part if the current is empty */ - if ((dev->state & ST_APPEND) && (dev->part == dev->num_parts) && (dev->part_size == 0)) { - Dmsg0(29, "open_next_part exited immediatly (dev->part_size == 0).\n"); + if (dev->can_append() && (dev->part == dev->num_parts) && + (dev->part_size == 0)) { + Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n"); return dev->fd; } @@ -854,7 +840,7 @@ int open_next_part(DEVICE *dev) { state = dev->state; dev->state &= ~ST_OPENED; - if ((dev_cap(dev, CAP_REQMOUNT)) && (dev->part == dev->num_parts) && (dev->state & ST_APPEND)) { + if (dev->is_dvd() && (dev->part == dev->num_parts) && dev->can_append()) { if (write_part(dev) < 0) { return -1; } @@ -901,8 +887,7 @@ int open_next_part(DEVICE *dev) { if (open_dev(dev, dev->VolCatInfo.VolCatName, dev->openmode) < 0) { return -1; - } - else { + } else { dev->state = state; return dev->fd; } @@ -930,8 +915,7 @@ int open_first_part(DEVICE *dev) { if (open_dev(dev, dev->VolCatInfo.VolCatName, dev->openmode)) { dev->state = state; return dev->fd; - } - else { + } else { return 0; } } @@ -946,7 +930,8 @@ bool _rewind_dev(char *file, int line, DEVICE *dev) #endif /* Protected version of lseek, which opens the right part if necessary */ -off_t lseek_dev(DEVICE *dev, off_t offset, int whence) { +off_t lseek_dev(DEVICE *dev, off_t offset, int whence) +{ int pos, openmode; if (dev->num_parts == 0) { /* If there is only one part, simply call lseek. */ @@ -954,97 +939,92 @@ off_t lseek_dev(DEVICE *dev, off_t offset, int whence) { } switch(whence) { - case SEEK_SET: - Dmsg1(100, "lseek_dev SEEK_SET called %d\n", offset); - if ((uint64_t)offset >= dev->part_start) { - if ((uint64_t)(offset - dev->part_start) < dev->part_size) { - /* We are staying in the current part, just seek */ - if ((pos = lseek(dev->fd, (off_t)(offset-dev->part_start), SEEK_SET)) < 0) { - return pos; - } - else { - return pos + dev->part_start; - } - } - else { - /* Load next part, and start again */ - if (open_next_part(dev) < 0) { - Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); - return -1; - } - return lseek_dev(dev, offset, SEEK_SET); + case SEEK_SET: + Dmsg1(100, "lseek_dev SEEK_SET called %d\n", offset); + if ((uint64_t)offset >= dev->part_start) { + if ((uint64_t)(offset - dev->part_start) < dev->part_size) { + /* We are staying in the current part, just seek */ + if ((pos = lseek(dev->fd, (off_t)(offset-dev->part_start), SEEK_SET)) < 0) { + return pos; + } else { + return pos + dev->part_start; } - } - else { - /* pos < dev->part_start : - * We need to access a previous part, - * so just load the first one, and seek again - * until the right one is loaded */ - if (open_first_part(dev) < 0) { - Dmsg0(100, "lseek_dev failed while trying to open the first part\n"); + } else { + /* Load next part, and start again */ + if (open_next_part(dev) < 0) { + Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); return -1; } return lseek_dev(dev, offset, SEEK_SET); } - break; - case SEEK_CUR: - Dmsg1(100, "lseek_dev SEEK_CUR called %d\n", offset); - if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) { - return pos; - } - pos += dev->part_start; - if (offset == 0) { - return pos; - } - else { /* Not used in Bacula, but should work */ - return lseek_dev(dev, pos, SEEK_SET); - } - break; - case SEEK_END: - Dmsg1(100, "lseek_dev SEEK_END called %d\n", offset); - if (offset > 0) { /* Not used by bacula */ - Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", offset); - errno = EINVAL; + } else { + /* pos < dev->part_start : + * We need to access a previous part, + * so just load the first one, and seek again + * until the right one is loaded */ + if (open_first_part(dev) < 0) { + Dmsg0(100, "lseek_dev failed while trying to open the first part\n"); return -1; } + return lseek_dev(dev, offset, SEEK_SET); + } + break; + case SEEK_CUR: + Dmsg1(100, "lseek_dev SEEK_CUR called %d\n", offset); + if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) { + return pos; + } + pos += dev->part_start; + if (offset == 0) { + return pos; + } + else { /* Not used in Bacula, but should work */ + return lseek_dev(dev, pos, SEEK_SET); + } + break; + case SEEK_END: + Dmsg1(100, "lseek_dev SEEK_END called %d\n", offset); + if (offset > 0) { /* Not used by bacula */ + Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", offset); + errno = EINVAL; + return -1; + } + + if (dev->part == dev->num_parts) { /* The right part is already loaded */ + if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) { + return pos; + } else { + return pos + dev->part_start; + } + } else { + /* Load the first part, then load the next until we reach the last one. + * This is the only way to be sure we compute the right file address. */ + /* Save previous openmode, and open all but last part read-only (useful for DVDs) */ + openmode = dev->openmode; + dev->openmode = OPEN_READ_ONLY; - if (dev->part == dev->num_parts) { /* The right part is already loaded */ - if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) { - return pos; - } - else { - return pos + dev->part_start; - } + /* Works because num_parts > 0. */ + if (open_first_part(dev) < 0) { + Dmsg0(100, "lseek_dev failed while trying to open the first part\n"); + return -1; } - else { - /* Load the first part, then load the next until we reach the last one. - * This is the only way to be sure we compute the right file address. */ - /* Save previous openmode, and open all but last part read-only (useful for DVDs) */ - openmode = dev->openmode; - dev->openmode = OPEN_READ_ONLY; - - /* Works because num_parts > 0. */ - if (open_first_part(dev) < 0) { - Dmsg0(100, "lseek_dev failed while trying to open the first part\n"); - return -1; - } - while (dev->part < (dev->num_parts-1)) { - if (open_next_part(dev) < 0) { - Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); - return -1; - } - } - dev->openmode = openmode; + while (dev->part < (dev->num_parts-1)) { if (open_next_part(dev) < 0) { Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); return -1; } - return lseek_dev(dev, 0, SEEK_END); } - break; - default: - errno = EINVAL; - return -1; + dev->openmode = openmode; + if (open_next_part(dev) < 0) { + Dmsg0(100, "lseek_dev failed while trying to open the next part\n"); + return -1; + } + return lseek_dev(dev, 0, SEEK_END); + } + break; + default: + errno = EINVAL; + return -1; } } @@ -1070,7 +1050,7 @@ bool rewind_dev(DEVICE *dev) dev->block_num = dev->file = 0; dev->file_size = 0; dev->file_addr = 0; - if (dev->state & ST_TAPE) { + if (dev->is_tape()) { mt_com.mt_op = MTREW; mt_com.mt_count = 1; /* If we get an I/O error on rewind, it is probably because @@ -1095,7 +1075,7 @@ bool rewind_dev(DEVICE *dev) } break; } - } else if (dev->state & ST_FILE) { + } else if (dev->is_file()) { if (lseek_dev(dev, (off_t)0, SEEK_SET) < 0) { berrno be; dev->dev_errno = errno; @@ -1131,7 +1111,7 @@ eod_dev(DEVICE *dev) if (dev->state & (ST_FIFO | ST_PROG)) { return 1; } - if (!(dev->state & ST_TAPE)) { + if (!(dev->is_tape())) { pos = lseek_dev(dev, (off_t)0, SEEK_END); // Dmsg1(100, "====== Seek to %lld\n", pos); if (pos >= 0) { @@ -1147,7 +1127,8 @@ eod_dev(DEVICE *dev) } #ifdef MTEOM - if (dev_cap(dev, CAP_MTIOCGET) && dev_cap(dev, CAP_FASTFSF) && !dev_cap(dev, CAP_EOM)) { + if (dev_cap(dev, CAP_MTIOCGET) && dev_cap(dev, CAP_FASTFSF) && + !dev_cap(dev, CAP_EOM)) { struct mtget mt_stat; Dmsg0(100,"Using FAST FSF for EOM\n"); if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno <= 0) { @@ -1273,7 +1254,7 @@ bool update_pos_dev(DEVICE *dev) } /* Find out where we are */ - if (dev->state & ST_FILE) { + if (dev->is_file()) { dev->file = 0; dev->file_addr = 0; pos = lseek_dev(dev, (off_t)0, SEEK_CUR); @@ -1314,7 +1295,7 @@ uint32_t status_dev(DEVICE *dev) stat |= BMT_EOF; Dmsg0(-20, " EOF"); } - if (dev->state & ST_TAPE) { + if (dev->is_tape()) { stat |= BMT_TAPE; Dmsg0(-20," Bacula status:"); Dmsg2(-20," file=%d block=%d\n", dev->file, dev->block_num); @@ -1394,7 +1375,7 @@ bool load_dev(DEVICE *dev) Emsg0(M_FATAL, 0, dev->errmsg); return false; } - if (!(dev->state & ST_TAPE)) { + if (!(dev->is_tape())) { return true; } #ifndef MTLOAD @@ -1437,7 +1418,7 @@ bool offline_dev(DEVICE *dev) Emsg0(M_FATAL, 0, dev->errmsg); return false; } - if (!(dev->state & ST_TAPE)) { + if (!(dev->is_tape())) { return true; } @@ -2032,7 +2013,7 @@ static void do_close(DEVICE *dev) } /* Remove the last part file if it is empty */ - if ((dev->state & ST_APPEND) && (dev->num_parts > 0)) { + if (dev->can_append() && (dev->num_parts > 0)) { struct stat statp; POOL_MEM archive_name(PM_FNAME); dev->part = dev->num_parts; @@ -2148,8 +2129,8 @@ dev_is_tape(DEVICE *dev) bool dev_can_write(DEVICE *dev) { - if ((dev->state & ST_OPENED) && (dev->state & ST_APPEND) && - (dev->state & ST_LABEL) && !(dev->state & ST_WEOT)) { + if (dev->is_open() && dev->can_append() && + dev->is_labeled() && !(dev->state & ST_WEOT)) { return true; } else { return false; diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 181398c630..e6fb96b11c 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -31,13 +31,13 @@ #ifndef __DEV_H #define __DEV_H 1 -#undef DCR /* used by Bacula */ +#undef DCR /* used by Bacula */ /* #define NEW_LOCK 1 */ -#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev)) +#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev)) #define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state)) -#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev)) +#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev)) #define lock_device(d) _lock_device(__FILE__, __LINE__, (d)) #define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d)) @@ -54,228 +54,261 @@ enum { }; /* Generic status bits returned from status_dev() */ -#define BMT_TAPE (1<<0) /* is tape device */ -#define BMT_EOF (1<<1) /* just read EOF */ -#define BMT_BOT (1<<2) /* at beginning of tape */ -#define BMT_EOT (1<<3) /* end of tape reached */ -#define BMT_SM (1<<4) /* DDS setmark */ -#define BMT_EOD (1<<5) /* DDS at end of data */ -#define BMT_WR_PROT (1<<6) /* tape write protected */ -#define BMT_ONLINE (1<<7) /* tape online */ -#define BMT_DR_OPEN (1<<8) /* tape door open */ -#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */ +#define BMT_TAPE (1<<0) /* is tape device */ +#define BMT_EOF (1<<1) /* just read EOF */ +#define BMT_BOT (1<<2) /* at beginning of tape */ +#define BMT_EOT (1<<3) /* end of tape reached */ +#define BMT_SM (1<<4) /* DDS setmark */ +#define BMT_EOD (1<<5) /* DDS at end of data */ +#define BMT_WR_PROT (1<<6) /* tape write protected */ +#define BMT_ONLINE (1<<7) /* tape online */ +#define BMT_DR_OPEN (1<<8) /* tape door open */ +#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */ /* Test capabilities */ #define dev_cap(dev, cap) ((dev)->capabilities & (cap)) /* Bits for device capabilities */ -#define CAP_EOF (1<<0) /* has MTWEOF */ -#define CAP_BSR (1<<1) /* has MTBSR */ -#define CAP_BSF (1<<2) /* has MTBSF */ -#define CAP_FSR (1<<3) /* has MTFSR */ -#define CAP_FSF (1<<4) /* has MTFSF */ -#define CAP_EOM (1<<5) /* has MTEOM */ -#define CAP_REM (1<<6) /* is removable media */ -#define CAP_RACCESS (1<<7) /* is random access device */ -#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */ -#define CAP_LABEL (1<<9) /* Label blank tapes */ -#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */ -#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */ +#define CAP_EOF (1<<0) /* has MTWEOF */ +#define CAP_BSR (1<<1) /* has MTBSR */ +#define CAP_BSF (1<<2) /* has MTBSF */ +#define CAP_FSR (1<<3) /* has MTFSR */ +#define CAP_FSF (1<<4) /* has MTFSF */ +#define CAP_EOM (1<<5) /* has MTEOM */ +#define CAP_REM (1<<6) /* is removable media */ +#define CAP_RACCESS (1<<7) /* is random access device */ +#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */ +#define CAP_LABEL (1<<9) /* Label blank tapes */ +#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */ +#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */ #define CAP_AUTOCHANGER (1<<12) /* AutoChanger */ #define CAP_OFFLINEUNMOUNT (1<<13) /* Offline before unmount */ -#define CAP_STREAM (1<<14) /* Stream device */ -#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */ -#define CAP_FASTFSF (1<<16) /* Fast forward space file */ -#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */ +#define CAP_STREAM (1<<14) /* Stream device */ +#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */ +#define CAP_FASTFSF (1<<16) /* Fast forward space file */ +#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */ #define CAP_CLOSEONPOLL (1<<18) /* Close device on polling */ #define CAP_POSITIONBLOCKS (1<<19) /* Use block positioning */ -#define CAP_MTIOCGET (1<<20) /* Basic support for fileno and blkno */ -#define CAP_REQMOUNT (1<<21) /* Require mount to read files back (typically: DVD) */ +#define CAP_MTIOCGET (1<<20) /* Basic support for fileno and blkno */ +#define CAP_REQMOUNT (1<<21) /* Require mount to read files back (typically: DVD) */ /* Test state */ #define dev_state(dev, st_state) ((dev)->state & (st_state)) /* Device state bits */ -#define ST_OPENED (1<<0) /* set when device opened */ -#define ST_TAPE (1<<1) /* is a tape device */ -#define ST_FILE (1<<2) /* is a file device */ -#define ST_FIFO (1<<3) /* is a fifo device */ -#define ST_PROG (1<<4) /* is a program device */ -#define ST_LABEL (1<<5) /* label found */ -#define ST_MALLOC (1<<6) /* dev packet malloc'ed in init_dev() */ -#define ST_APPEND (1<<7) /* ready for Bacula append */ -#define ST_READ (1<<8) /* ready for Bacula read */ -#define ST_EOT (1<<9) /* at end of tape */ -#define ST_WEOT (1<<10) /* Got EOT on write */ -#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */ -#define ST_NEXTVOL (1<<12) /* Start writing on next volume */ -#define ST_SHORT (1<<13) /* Short block read */ -#define ST_MOUNTED (1<<14) /* the device is mounted to the mount point */ +#define ST_OPENED (1<<0) /* set when device opened */ +#define ST_TAPE (1<<1) /* is a tape device */ +#define ST_FILE (1<<2) /* is a file device */ +#define ST_FIFO (1<<3) /* is a fifo device */ +#define ST_DVD (1<<4) /* is a DVD device */ +#define ST_PROG (1<<5) /* is a program device */ +#define ST_LABEL (1<<6) /* label found */ +#define ST_MALLOC (1<<7) /* dev packet malloc'ed in init_dev() */ +#define ST_APPEND (1<<8) /* ready for Bacula append */ +#define ST_READ (1<<9) /* ready for Bacula read */ +#define ST_EOT (1<<10) /* at end of tape */ +#define ST_WEOT (1<<11) /* Got EOT on write */ +#define ST_EOF (1<<12) /* Read EOF i.e. zero bytes */ +#define ST_NEXTVOL (1<<13) /* Start writing on next volume */ +#define ST_SHORT (1<<14) /* Short block read */ +#define ST_MOUNTED (1<<15) /* the device is mounted to the mount point */ /* dev_blocked states (mutually exclusive) */ enum { - BST_NOT_BLOCKED = 0, /* not blocked */ - BST_UNMOUNTED, /* User unmounted device */ - BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */ - BST_DOING_ACQUIRE, /* Opening/validating/moving tape */ - BST_WRITING_LABEL, /* Labeling a tape */ + BST_NOT_BLOCKED = 0, /* not blocked */ + BST_UNMOUNTED, /* User unmounted device */ + BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */ + BST_DOING_ACQUIRE, /* Opening/validating/moving tape */ + BST_WRITING_LABEL, /* Labeling a tape */ BST_UNMOUNTED_WAITING_FOR_SYSOP, /* Closed by user during mount request */ - BST_MOUNT /* Mount request */ + BST_MOUNT /* Mount request */ }; /* Volume Catalog Information structure definition */ struct VOLUME_CAT_INFO { /* Media info for the current Volume */ - uint32_t VolCatJobs; /* number of jobs on this Volume */ - uint32_t VolCatFiles; /* Number of files */ - uint32_t VolCatBlocks; /* Number of blocks */ - uint64_t VolCatBytes; /* Number of bytes written */ - uint32_t VolCatParts; /* Number of parts written */ - uint32_t VolCatMounts; /* Number of mounts this volume */ - uint32_t VolCatErrors; /* Number of errors this volume */ - uint32_t VolCatWrites; /* Number of writes this volume */ - uint32_t VolCatReads; /* Number of reads this volume */ - uint64_t VolCatRBytes; /* Number of bytes read */ - uint32_t VolCatRecycles; /* Number of recycles this volume */ - uint32_t EndFile; /* Last file number */ - uint32_t EndBlock; /* Last block number */ - int32_t Slot; /* Slot in changer */ - bool InChanger; /* Set if vol in current magazine */ - uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ - uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ - uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ + uint32_t VolCatJobs; /* number of jobs on this Volume */ + uint32_t VolCatFiles; /* Number of files */ + uint32_t VolCatBlocks; /* Number of blocks */ + uint64_t VolCatBytes; /* Number of bytes written */ + uint32_t VolCatParts; /* Number of parts written */ + uint32_t VolCatMounts; /* Number of mounts this volume */ + uint32_t VolCatErrors; /* Number of errors this volume */ + uint32_t VolCatWrites; /* Number of writes this volume */ + uint32_t VolCatReads; /* Number of reads this volume */ + uint64_t VolCatRBytes; /* Number of bytes read */ + uint32_t VolCatRecycles; /* Number of recycles this volume */ + uint32_t EndFile; /* Last file number */ + uint32_t EndBlock; /* Last block number */ + int32_t LabelType; /* Bacula/ANSI/IBM */ + int32_t Slot; /* Slot in changer */ + bool InChanger; /* Set if vol in current magazine */ + uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */ + uint32_t VolCatMaxFiles; /* Maximum files to write to volume */ + uint64_t VolCatMaxBytes; /* Max bytes to write to volume */ uint64_t VolCatCapacityBytes; /* capacity estimate */ - uint64_t VolReadTime; /* time spent reading */ - uint64_t VolWriteTime; /* time spent writing this Volume */ - char VolCatStatus[20]; /* Volume status */ + uint64_t VolReadTime; /* time spent reading */ + uint64_t VolWriteTime; /* time spent writing this Volume */ + char VolCatStatus[20]; /* Volume status */ char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ }; typedef struct s_steal_lock { - pthread_t no_wait_id; /* id of no wait thread */ - int dev_blocked; /* state */ - int dev_prev_blocked; /* previous blocked state */ + pthread_t no_wait_id; /* id of no wait thread */ + int dev_blocked; /* state */ + int dev_prev_blocked; /* previous blocked state */ } bsteal_lock_t; -struct DEVRES; /* Device resource defined in stored_conf.h */ +struct DEVRES; /* Device resource defined in stored_conf.h */ /* * Device structure definition. There is one of these for * each physical device. Everything here is "global" to * that device and effects all jobs using the device. */ -struct DEVICE { +class DEVICE { public: - DEVICE *next; /* pointer to next open device */ - DEVICE *prev; /* pointer to prev open device */ - JCR *attached_jcrs; /* attached JCR list */ - dlist *attached_dcrs; /* attached DCR list */ - pthread_mutex_t mutex; /* access control */ + dlist *attached_dcrs; /* attached DCR list */ + pthread_mutex_t mutex; /* access control */ pthread_mutex_t spool_mutex; /* mutex for updating spool_size */ - pthread_cond_t wait; /* thread wait variable */ + pthread_cond_t wait; /* thread wait variable */ pthread_cond_t wait_next_vol; /* wait for tape to be mounted */ - pthread_t no_wait_id; /* this thread must not wait */ - int dev_blocked; /* set if we must wait (i.e. change tape) */ - int dev_prev_blocked; /* previous blocked state */ - int num_waiting; /* number of threads waiting */ - int num_writers; /* number of writing threads */ + pthread_t no_wait_id; /* this thread must not wait */ + int dev_blocked; /* set if we must wait (i.e. change tape) */ + int dev_prev_blocked; /* previous blocked state */ + int num_waiting; /* number of threads waiting */ + int num_writers; /* number of writing threads */ + int reserved_device; /* number of device reservations */ /* New access control in process of being implemented */ - brwlock_t lock; /* New mutual exclusion lock */ - - int use_count; /* usage count on this device */ - int fd; /* file descriptor */ - int capabilities; /* capabilities mask */ - int state; /* state mask */ - int dev_errno; /* Our own errno */ - int mode; /* read/write modes */ - int openmode; /* parameter passed to open_dev (useful to reopen the device) */ - uint32_t drive_index; /* Autochanger drive index */ - POOLMEM *dev_name; /* device name */ - char *errmsg; /* nicely edited error message */ - uint32_t block_num; /* current block number base 0 */ - uint32_t file; /* current file number base 0 */ - uint64_t file_addr; /* Current file read/write address */ - uint64_t file_size; /* Current file size */ - uint32_t EndBlock; /* last block written */ - uint32_t EndFile; /* last file written */ - uint32_t min_block_size; /* min block size */ - uint32_t max_block_size; /* max block size */ - uint64_t max_volume_size; /* max bytes to put on one volume */ - uint64_t max_file_size; /* max file size to put in one file on volume */ - uint64_t volume_capacity; /* advisory capacity */ - uint64_t max_spool_size; /* maximum spool file size */ - uint64_t spool_size; /* current spool size */ - uint32_t max_rewind_wait; /* max secs to allow for rewind */ - uint32_t max_open_wait; /* max secs to allow for open */ - uint32_t max_open_vols; /* max simultaneous open volumes */ + brwlock_t lock; /* New mutual exclusion lock */ + + int use_count; /* usage count on this device */ + int fd; /* file descriptor */ + int capabilities; /* capabilities mask */ + int state; /* state mask */ + int dev_errno; /* Our own errno */ + int mode; /* read/write modes */ + int openmode; /* parameter passed to open_dev (useful to reopen the device) */ + uint32_t drive_index; /* Autochanger drive index */ + POOLMEM *dev_name; /* device name */ + char *errmsg; /* nicely edited error message */ + uint32_t block_num; /* current block number base 0 */ + uint32_t file; /* current file number base 0 */ + uint64_t file_addr; /* Current file read/write address */ + uint64_t file_size; /* Current file size */ + uint32_t EndBlock; /* last block written */ + uint32_t EndFile; /* last file written */ + uint32_t min_block_size; /* min block size */ + uint32_t max_block_size; /* max block size */ + uint64_t max_volume_size; /* max bytes to put on one volume */ + uint64_t max_file_size; /* max file size to put in one file on volume */ + uint64_t volume_capacity; /* advisory capacity */ + uint64_t max_spool_size; /* maximum spool file size */ + uint64_t spool_size; /* current spool size */ + uint32_t max_rewind_wait; /* max secs to allow for rewind */ + uint32_t max_open_wait; /* max secs to allow for open */ + uint32_t max_open_vols; /* max simultaneous open volumes */ - uint64_t max_part_size; /* max part size */ - uint64_t part_size; /* current part size */ - uint32_t part; /* current part number */ - uint64_t part_start; /* current part start address (relative to the whole volume) */ - uint32_t num_parts; /* number of parts (total) */ - uint64_t free_space; /* current free space on medium (without the current part) */ - int free_space_errno; /* indicates: - * - free_space_errno == 0: ignore free_space. - * - free_space_errno < 0: an error occured. - * - free_space_errno > 0: free_space is valid. */ + uint64_t max_part_size; /* max part size */ + uint64_t part_size; /* current part size */ + uint32_t part; /* current part number */ + uint64_t part_start; /* current part start address (relative to the whole volume) */ + uint32_t num_parts; /* number of parts (total) */ + uint64_t free_space; /* current free space on medium (without the current part) */ + int free_space_errno; /* indicates: + * - free_space_errno == 0: ignore free_space. + * - free_space_errno < 0: an error occured. + * - free_space_errno > 0: free_space is valid. */ - utime_t vol_poll_interval; /* interval between polling Vol mount */ - DEVRES *device; /* pointer to Device Resource */ - btimer_t *tid; /* timer id */ + utime_t vol_poll_interval; /* interval between polling Vol mount */ + DEVRES *device; /* pointer to Device Resource */ + btimer_t *tid; /* timer id */ - VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */ - VOLUME_LABEL VolHdr; /* Actual volume label */ + VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */ + VOLUME_LABEL VolHdr; /* Actual volume label */ /* Device wait times ***FIXME*** look at durations */ char BadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */ - bool poll; /* set to poll Volume */ + bool poll; /* set to poll Volume */ int min_wait; int max_wait; int max_num_wait; int wait_sec; int rem_wait_sec; int num_wait; + + int is_tape() const; + int is_file() const; + int is_fifo() const; + int is_dvd() const; + int is_open() const; + int is_labeled() const; + int at_eof() const; + int at_eom() const; + int can_append() const; + int can_read() const; + const char *strerror() const; + const char *archive_name() const; }; +/* Note, these return int not bool! */ +inline int DEVICE::is_tape() const { return state & ST_TAPE; } +inline int DEVICE::is_file() const { return state & ST_FILE; } +inline int DEVICE::is_fifo() const { return state & ST_FIFO; } +inline int DEVICE::is_dvd() const { return state & ST_DVD; } +inline int DEVICE::is_open() const { return state & ST_OPENED; } +inline int DEVICE::is_labeled() const { return state & ST_LABEL; } +inline int DEVICE::at_eof() const { return state & ST_EOF; } +inline int DEVICE::at_eom() const { return state & ST_EOT; } +inline int DEVICE::can_append() const { return state & ST_APPEND; } +inline int DEVICE::can_read() const { return state & ST_READ; } +inline const char *DEVICE::strerror() const { return errmsg; } +inline const char *DEVICE::archive_name() const { return dev_name; } + + + + /* * Device Context (or Control) Record. * There is one of these records for each Job that is using * the device. Items in this record are "local" to the Job and - * do not affect other Jobs. + * do not affect other Jobs. Note, a job can have multiple + * DCRs open, each pointing to a different device. */ class DCR { public: - dlink dev_link; /* link to attach to dev */ - JCR *jcr; /* pointer to JCR */ - DEVICE *dev; /* pointer to device */ - DEV_BLOCK *block; /* pointer to block */ - DEV_RECORD *rec; /* pointer to record */ - int spool_fd; /* fd if spooling */ - bool spool_data; /* set to spool data */ - bool spooling; /* set when actually spooling */ - bool dev_locked; /* set if dev already locked */ - bool NewVol; /* set if new Volume mounted */ - bool WroteVol; /* set if Volume written */ - bool NewFile; /* set when EOF written */ - uint32_t VolFirstIndex; /* First file index this Volume */ - uint32_t VolLastIndex; /* Last file index this Volume */ - uint32_t FileIndex; /* Current File Index */ - uint32_t EndFile; /* End file written */ - uint32_t StartFile; /* Start write file */ - uint32_t StartBlock; /* Start write block */ - uint32_t EndBlock; /* Ending block written */ - int64_t spool_size; /* Current spool size */ - int64_t max_spool_size; /* Max job spool size */ + dlink dev_link; /* link to attach to dev */ + JCR *jcr; /* pointer to JCR */ + DEVICE *dev; /* pointer to device */ + DEVRES *device; /* pointer to device resource */ + DEV_BLOCK *block; /* pointer to block */ + DEV_RECORD *rec; /* pointer to record */ + int spool_fd; /* fd if spooling */ + bool spool_data; /* set to spool data */ + bool spooling; /* set when actually spooling */ + bool dev_locked; /* set if dev already locked */ + bool NewVol; /* set if new Volume mounted */ + bool WroteVol; /* set if Volume written */ + bool NewFile; /* set when EOF written */ + bool reserved_device; /* set if reserve done */ + uint32_t VolFirstIndex; /* First file index this Volume */ + uint32_t VolLastIndex; /* Last file index this Volume */ + uint32_t FileIndex; /* Current File Index */ + uint32_t EndFile; /* End file written */ + uint32_t StartFile; /* Start write file */ + uint32_t StartBlock; /* Start write block */ + uint32_t EndBlock; /* Ending block written */ + int64_t spool_size; /* Current spool size */ + int64_t max_spool_size; /* Max job spool size */ char VolumeName[MAX_NAME_LENGTH]; /* Volume name */ char pool_name[MAX_NAME_LENGTH]; /* pool name */ char pool_type[MAX_NAME_LENGTH]; /* pool type */ char media_type[MAX_NAME_LENGTH]; /* media type */ char dev_name[MAX_NAME_LENGTH]; /* dev name */ - VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */ + VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */ }; @@ -284,7 +317,7 @@ public: * dependent. Arrgggg! */ #ifndef MTEOM -#ifdef MTSEOD +#ifdef MTSEOD #define MTEOM MTSEOD #endif #ifdef MTEOD diff --git a/bacula/src/stored/device.c b/bacula/src/stored/device.c index b14f64c125..682ce6e0a4 100644 --- a/bacula/src/stored/device.c +++ b/bacula/src/stored/device.c @@ -276,7 +276,7 @@ bool first_open_device(DEVICE *dev) return true; } - if (!(dev->state & ST_OPENED)) { + if (!dev->is_open()) { int mode; if (dev_cap(dev, CAP_STREAM)) { mode = OPEN_WRITE_ONLY; @@ -285,7 +285,7 @@ bool first_open_device(DEVICE *dev) } Dmsg0(129, "Opening device.\n"); if (open_dev(dev, NULL, mode) < 0) { - Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); + Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg); unlock_device(dev); return false; } @@ -303,21 +303,23 @@ bool open_device(DCR *dcr) { DEVICE *dev = dcr->dev; /* Open device */ - if (!(dev_state(dev, ST_OPENED))) { - int mode; - if (dev_cap(dev, CAP_STREAM)) { - mode = OPEN_WRITE_ONLY; - } else { - mode = OPEN_READ_WRITE; - } - if (open_dev(dev, dcr->VolCatInfo.VolCatName, mode) < 0) { - /* If polling, ignore the error */ - if (!dev->poll) { - Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s. ERR=%s\n"), - dev_name(dev), strerror_dev(dev)); - } - return false; - } + if (!dev->is_open()) { + int mode; + if (dev_cap(dev, CAP_STREAM)) { + mode = OPEN_WRITE_ONLY; + } else { + mode = OPEN_READ_WRITE; + } + if (open_dev(dev, dcr->VolCatInfo.VolCatName, mode) < 0) { + /* If polling, ignore the error */ + if (!dev->poll) { + Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open archive %s. ERR=%s\n"), + dev_name(dev), strerror_dev(dev)); + Dmsg2(000, "Unable to open archive %s. ERR=%s\n", + dev_name(dev), strerror_dev(dev)); + } + return false; + } } return true; } @@ -353,7 +355,7 @@ void _lock_device(const char *file, int line, DEVICE *dev) while (dev->dev_blocked) { if ((stat = pthread_cond_wait(&dev->wait, &dev->mutex)) != 0) { V(dev->mutex); - Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"), + Emsg1(M_ABORT, 0, _("pthread_cond_wait failure. ERR=%s\n"), strerror(stat)); } } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 12c67cb156..c4a9775725 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -52,15 +52,18 @@ extern time_t daemon_start_time; extern struct s_last_job last_job; /* Static variables */ -static char derrmsg[] = "3900 Invalid command\n"; -static char OKsetdebug[] = "3000 OK setdebug=%d\n"; +static char derrmsg[] = "3900 Invalid command\n"; +static char OKsetdebug[] = "3000 OK setdebug=%d\n"; static char illegal_cmd[] = "3997 Illegal command for a Director with Monitor directive enabled\n"; /* Imported functions */ extern void terminate_child(); extern bool job_cmd(JCR *jcr); +extern bool use_cmd(JCR *jcr); +extern bool run_cmd(JCR *jcr); extern bool status_cmd(JCR *sjcr); extern bool qstatus_cmd(JCR *jcr); +extern bool query_cmd(JCR *jcr); /* Forward referenced functions */ static bool label_cmd(JCR *jcr); @@ -103,6 +106,9 @@ static struct s_cmds cmds[] = { {"status", status_cmd, 1}, {".status", qstatus_cmd, 1}, {"unmount", unmount_cmd, 0}, + {"use device=", use_cmd, 0}, + {"run", run_cmd, 0}, + {"query", query_cmd, 0}, {NULL, NULL} /* list terminator */ }; @@ -178,7 +184,7 @@ void *handle_connection_request(void *arg) } Dmsg0(90, "Message channel init completed.\n"); - for (quit=0; !quit;) { + for (quit=false; !quit;) { /* Read command */ if ((bnet_stat = bnet_recv(bs)) <= 0) { break; /* connection terminated */ @@ -193,6 +199,7 @@ void *handle_connection_request(void *arg) bnet_sig(bs, BNET_EOD); break; } + Dmsg1(200, "Do command: %s\n", cmds[i].cmd); if (!cmds[i].func(jcr)) { /* do command */ quit = true; /* error, get out */ Dmsg1(190, "Command %s requsts quit\n", cmds[i].cmd); @@ -322,7 +329,7 @@ static bool do_label(JCR *jcr, int relabel) if (dev) { /******FIXME**** compare MediaTypes */ P(dev->mutex); /* Use P to avoid indefinite block */ - if (!(dev->state & ST_OPENED)) { + if (!dev->is_open()) { label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); force_close_dev(dev); /* Under certain "safe" conditions, we can steal the lock */ @@ -382,12 +389,9 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, } /* See what we have for a Volume */ - label_status = read_dev_volume_label(dcr); - - if (dev_cap(dev, CAP_REQMOUNT)) { + if (dev->is_dvd()) { label_status = read_dev_volume_label_guess(dcr, 1); - } - else { + } else { label_status = read_dev_volume_label(dcr); } @@ -477,7 +481,6 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &dname) /* Find resource, and make sure we were able to open it */ if (strcmp(device->hdr.name, dname.c_str()) == 0 && device->dev) { Dmsg1(20, "Found device %s\n", device->hdr.name); - jcr->device = device; found = true; break; } @@ -489,6 +492,7 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &dname) */ jcr->dcr = new_dcr(jcr, device->dev); UnlockRes(); + jcr->dcr->device = device; return jcr->dcr->dev; } UnlockRes(); @@ -539,7 +543,7 @@ static bool mount_cmd(JCR *jcr) Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n"); dev->dev_blocked = BST_MOUNT; } - if (dev_state(dev, ST_LABEL)) { + if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), dev_name(dev), dev->VolHdr.VolName); } else { @@ -560,8 +564,8 @@ static bool mount_cmd(JCR *jcr) break; case BST_NOT_BLOCKED: - if (dev_state(dev, ST_OPENED)) { - if (dev_state(dev, ST_LABEL)) { + if (dev->is_open()) { + if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), dev_name(dev), dev->VolHdr.VolName); } else { @@ -580,7 +584,7 @@ static bool mount_cmd(JCR *jcr) break; } read_label(dcr); - if (dev_state(dev, ST_LABEL)) { + if (dev->is_labeled()) { bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"), dev_name(dev), dev->VolHdr.VolName); } else { @@ -620,7 +624,7 @@ static bool unmount_cmd(JCR *jcr) dev = find_device(jcr, dname); if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ - if (!(dev->state & ST_OPENED)) { + if (!dev->is_open()) { Dmsg0(90, "Device already unmounted\n"); bnet_fsend(dir, _("3901 Device \"%s\" is already unmounted.\n"), dev_name(dev)); @@ -694,7 +698,7 @@ static bool release_cmd(JCR *jcr) dev = find_device(jcr, dname); if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ - if (!(dev->state & ST_OPENED)) { + if (!dev->is_open()) { Dmsg0(90, "Device already released\n"); bnet_fsend(dir, _("3911 Device %s already released.\n"), dev_name(dev)); @@ -757,7 +761,7 @@ static bool autochanger_cmd(JCR *jcr) P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev_is_tape(dev)) { bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev_name(dev)); - } else if (!(dev->state & ST_OPENED)) { + } else if (!dev->is_open()) { autochanger_list(dcr, dir); /* Under certain "safe" conditions, we can steal the lock */ } else if (dev->dev_blocked && @@ -802,7 +806,7 @@ static bool readlabel_cmd(JCR *jcr) dev = find_device(jcr, dname); if (dev) { P(dev->mutex); /* Use P to avoid indefinite block */ - if (!dev_state(dev, ST_OPENED)) { + if (!dev->is_open()) { read_volume_label(jcr, dev, Slot); force_close_dev(dev); /* Under certain "safe" conditions, we can steal the lock */ @@ -884,10 +888,10 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName) } /* Ensure that the device is open -- autoload_device() closes it */ - for ( ; !(dev->state & ST_OPENED); ) { + for ( ; !dev->is_open(); ) { if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) { bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"), - dev_name(dev), strerror_dev(dev)); + dev_name(dev), dev->strerror()); return false; } } diff --git a/bacula/src/stored/fd_cmds.c b/bacula/src/stored/fd_cmds.c index 122dca6da0..71a75615cd 100644 --- a/bacula/src/stored/fd_cmds.c +++ b/bacula/src/stored/fd_cmds.c @@ -13,7 +13,7 @@ * */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -145,7 +145,7 @@ void run_job(JCR *jcr) } } if (!found) { /* command not found */ - Dmsg1(110, "msg); + Dmsg1(110, "msg); bnet_fsend(fd, ferrmsg); break; } @@ -214,8 +214,7 @@ static bool append_open_session(JCR *jcr) return false; } - Dmsg1(110, "Append open session: %s\n", dev_name(jcr->device->dev)); - jcr->session_opened = TRUE; + jcr->session_opened = true; /* Send "Ticket" to File Daemon */ bnet_fsend(fd, OK_open, jcr->VolSessionId); @@ -244,8 +243,6 @@ static bool append_close_session(JCR *jcr) bnet_sig(fd, BNET_EOD); /* send EOD to File daemon */ - Dmsg1(110, "Append close session: %s\n", dev_name(jcr->device->dev)); - jcr->session_opened = false; return true; } @@ -301,9 +298,7 @@ static bool read_open_session(JCR *jcr) jcr->read_EndBlock); } - Dmsg1(110, "Read open session: %s\n", dev_name(jcr->device->dev)); - - jcr->session_opened = TRUE; + jcr->session_opened = true; jcr->JobType = JT_RESTORE; /* Send "Ticket" to File Daemon */ @@ -380,6 +375,6 @@ static bool read_close_session(JCR *jcr) bnet_sig(fd, BNET_EOD); /* send EOD to File daemon */ - jcr->session_opened = FALSE; + jcr->session_opened = false; return true; } diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 1be408cfeb..660d6adb9a 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -42,8 +42,10 @@ static bool use_device_cmd(JCR *jcr); static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " "SpoolData=%d WritePartAfterJob=%d"; -static char use_device[] = "use device=%127s media_type=%127s pool_name=%127s pool_type=%127s\n"; -static char use_devices[] = "use devices=%127s media_type=%127s pool_name=%127s pool_type=%127s\n"; +static char use_device[] = "use device=%127s media_type=%127s " + "pool_name=%127s pool_type=%127s append=%d"; +static char query_device[] = "query device=%127s"; + /* Responses sent to Director daemon */ static char OKjob[] = "3000 OK Job SDid=%u SDtime=%u Authorization=%s\n"; @@ -51,6 +53,10 @@ static char OK_device[] = "3000 OK use device\n"; static char NO_device[] = "3914 Device \"%s\" not in SD Device resources.\n"; static char BAD_use[] = "3913 Bad use command: %s\n"; static char BAD_job[] = "3915 Bad Job command: %s\n"; +static char OK_query[] = "3001 OK query append=%d read=%d num_writers=%d " + "num_waiting=%d open=%d use_count=%d labeled=%d " + "media_type=%s volume_name=%s"; +static char BAD_query[] = "3917 Bad query command: %s\n"; /* * Director requests us to start a job @@ -64,14 +70,11 @@ static char BAD_job[] = "3915 Bad Job command: %s\n"; */ bool job_cmd(JCR *jcr) { - int JobId, errstat; + int JobId; char auth_key[100]; BSOCK *dir = jcr->dir_bsock; POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; int JobType, level, spool_attributes, no_attributes, spool_data, write_part_after_job; - struct timeval tv; - struct timezone tz; - struct timespec timeout; JCR *ojcr; /* @@ -130,7 +133,11 @@ bool job_cmd(JCR *jcr) Dmsg1(110, ">dird: %s", dir->msg); jcr->sd_auth_key = bstrdup(auth_key); memset(auth_key, 0, sizeof(auth_key)); + return true; +} +bool use_cmd(JCR *jcr) +{ /* * Wait for the device, media, and pool information */ @@ -139,6 +146,15 @@ bool job_cmd(JCR *jcr) memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key)); return false; } + return true; +} + +bool run_cmd(JCR *jcr) +{ + struct timeval tv; + struct timezone tz; + struct timespec timeout; + int errstat; /* The following jobs don't need the FD */ switch (jcr->JobType) { @@ -243,81 +259,131 @@ static bool use_device_cmd(JCR *jcr) POOL_MEM dev_name, media_type, pool_name, pool_type; BSOCK *dir = jcr->dir_bsock; DEVRES *device; - bool quit = false; - - while (!quit) { - bool ok; - if (bnet_recv(dir) <= 0) { - Jmsg0(jcr, M_FATAL, 0, _("No Device from Director\n")); - return false; - } + int append; + bool ok; - Dmsg1(120, "Use device: %s", dir->msg); - /* - * If there are multiple devices, the director sends us - * use_devices (note plurel) until the last one, at which - * time, it sends us a use_device command (note singlular) - * so we stop looking after getting the use_device. - */ - ok = sscanf(dir->msg, use_device, dev_name.c_str(), media_type.c_str(), - pool_name.c_str(), pool_type.c_str()) == 4; - if (ok) { - quit = true; /* got last device */ - } else { - ok = sscanf(dir->msg, use_devices, dev_name.c_str(), media_type.c_str(), - pool_name.c_str(), pool_type.c_str()) == 4; - } - if (ok) { - unbash_spaces(dev_name); - unbash_spaces(media_type); - unbash_spaces(pool_name); - unbash_spaces(pool_type); - LockRes(); - foreach_res(device, R_DEVICE) { - /* Find resource, and make sure we were able to open it */ - if (fnmatch(dev_name.c_str(), device->hdr.name, 0) == 0 && - device->dev && strcmp(device->media_type, media_type.c_str()) == 0) { - const int name_len = MAX_NAME_LENGTH; - DCR *dcr; - UnlockRes(); - dcr = new_dcr(jcr, device->dev); - if (!dcr) { - return false; - } - Dmsg1(120, "Found device %s\n", device->hdr.name); - bstrncpy(dcr->pool_name, pool_name, name_len); - bstrncpy(dcr->pool_type, pool_type, name_len); - bstrncpy(dcr->media_type, media_type, name_len); - bstrncpy(dcr->dev_name, dev_name, name_len); - jcr->device = device; - Dmsg1(220, "Got: %s", dir->msg); - return bnet_fsend(dir, OK_device); + Dmsg1(120, "Use device: %s", dir->msg); + /* + * If there are multiple devices, the director sends us + * use_device for each device that it wants to use. + */ + ok = sscanf(dir->msg, use_device, dev_name.c_str(), media_type.c_str(), + pool_name.c_str(), pool_type.c_str(), &append) == 5; + if (ok) { + unbash_spaces(dev_name); + unbash_spaces(media_type); + unbash_spaces(pool_name); + unbash_spaces(pool_type); + LockRes(); + foreach_res(device, R_DEVICE) { + /* Find resource, and make sure we were able to open it */ + if (fnmatch(dev_name.c_str(), device->hdr.name, 0) == 0 && + device->dev && strcmp(device->media_type, media_type.c_str()) == 0) { + const int name_len = MAX_NAME_LENGTH; + DCR *dcr = new_dcr(jcr, device->dev); + UnlockRes(); + Dmsg1(120, "Found device %s\n", device->hdr.name); + bstrncpy(dcr->pool_name, pool_name, name_len); + bstrncpy(dcr->pool_type, pool_type, name_len); + bstrncpy(dcr->media_type, media_type, name_len); + bstrncpy(dcr->dev_name, dev_name, name_len); + jcr->dcr = dcr; + if (!dcr) { + bnet_fsend(dir, _("Could not get dcr for device: %s\n"), dev_name.c_str()); + return false; } + if (append == SD_APPEND) { + ok = reserve_device_for_append(jcr, device->dev); + } else { + ok = reserve_device_for_read(jcr, device->dev); + } + if (!ok) { + bnet_fsend(dir, _("Could not get dcr for device: %s\n"), dev_name.c_str()); + free_dcr(jcr->dcr); + return false; + } + Dmsg1(220, "Got: %s", dir->msg); + return bnet_fsend(dir, OK_device); } - UnlockRes(); - if (verbose) { - unbash_spaces(dir->msg); - pm_strcpy(jcr->errmsg, dir->msg); - Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg); - } - Jmsg(jcr, M_FATAL, 0, _("\n" - " Device \"%s\" with MediaType \"%s\" requested by Dir not found in SD Device resources.\n"), - dev_name.c_str(), media_type.c_str()); - bnet_fsend(dir, NO_device, dev_name.c_str()); - } else { + } + UnlockRes(); + if (verbose) { unbash_spaces(dir->msg); pm_strcpy(jcr->errmsg, dir->msg); - if (verbose) { - Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg); - } - Jmsg(jcr, M_FATAL, 0, _("Bad Use Device command: %s\n"), jcr->errmsg); - bnet_fsend(dir, BAD_use, jcr->errmsg); + Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg); } + Jmsg(jcr, M_FATAL, 0, _("\n" + " Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"), + dev_name.c_str(), media_type.c_str()); + bnet_fsend(dir, NO_device, dev_name.c_str()); + } else { + unbash_spaces(dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); + if (verbose) { + Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg); + } + Jmsg(jcr, M_FATAL, 0, _("Bad Use Device command: %s\n"), jcr->errmsg); + bnet_fsend(dir, BAD_use, jcr->errmsg); } return false; /* ERROR return */ } +/* + * Query Device command from Director + * Sends Storage Daemon's information on the device to the + * caller (presumably the Director). + * This command always returns "true" so that the line is + * not closed on an error. + * + */ +bool query_cmd(JCR *jcr) +{ + POOL_MEM dev_name; + BSOCK *dir = jcr->dir_bsock; + DEVRES *device; + bool ok; + + Dmsg1(120, "Query: %s", dir->msg); + + ok = sscanf(dir->msg, query_device, dev_name.c_str()) == 1; + if (ok) { + unbash_spaces(dev_name); + LockRes(); + foreach_res(device, R_DEVICE) { + /* Find resource, and make sure we were able to open it */ + if (fnmatch(dev_name.c_str(), device->hdr.name, 0) == 0 && + device->dev) { + DEVICE *dev = device->dev; + POOL_MEM VolumeName, MediaType; + UnlockRes(); + if (dev->is_labeled()) { + pm_strcpy(VolumeName, dev->VolHdr.VolName); + } else { + pm_strcpy(VolumeName, ""); + } + bash_spaces(VolumeName); + pm_strcpy(MediaType, device->media_type); + bash_spaces(MediaType); + return bnet_fsend(dir, OK_query, dev->can_append()!=0, + dev->can_read()!=0, dev->num_writers, dev->num_waiting, + dev->is_open()!=0, dev->use_count, dev->is_labeled()!=0, + MediaType.c_str(), VolumeName.c_str()); + } + } + UnlockRes(); + unbash_spaces(dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); + bnet_fsend(dir, NO_device, dev_name.c_str()); + } else { + unbash_spaces(dir->msg); + pm_strcpy(jcr->errmsg, dir->msg); + bnet_fsend(dir, BAD_query, jcr->errmsg); + } + return true; +} + + /* * Destroy the Job Control Record and associated * resources (sockets). diff --git a/bacula/src/stored/label.c b/bacula/src/stored/label.c index 9b5e03aba2..7e10a4b719 100644 --- a/bacula/src/stored/label.c +++ b/bacula/src/stored/label.c @@ -32,6 +32,8 @@ /* Forward referenced functions */ static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec); +static int read_ansi_ibm_label(DCR *dcr); +static char *ansi_date(time_t td, char *buf); extern char my_name[]; extern int debug_level; @@ -68,7 +70,10 @@ int read_dev_volume_label(DCR *dcr) Dmsg3(100, "Enter read_volume_label device=%s vol=%s dev_Vol=%s\n", dev_name(dev), VolName, dev->VolHdr.VolName); - if (dev_state(dev, ST_LABEL)) { /* did we already read label? */ + if (!dev->is_open()) { + Emsg0(M_ABORT, 0, _("BAD call to read_dev_volume_label\n")); + } + if (dev->is_labeled()) { /* did we already read label? */ /* Compare Volume Names allow special wild card */ if (VolName && *VolName && *VolName != '*' && strcmp(dev->VolHdr.VolName, VolName) != 0) { Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), @@ -95,6 +100,12 @@ int read_dev_volume_label(DCR *dcr) return VOL_NO_MEDIA; } bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id)); + + /* Read ANSI/IBM label if so requested */ + int stat = read_ansi_ibm_label(dcr); + if (stat != VOL_OK) { + return stat; + } /* Read the Volume label block */ record = new_record(); @@ -190,12 +201,15 @@ int read_dev_volume_label(DCR *dcr) * Writing : returns the label of the current file (on the harddisk). * Reading : returns an error */ -int read_dev_volume_label_guess(DCR *dcr, bool write) { +int read_dev_volume_label_guess(DCR *dcr, bool write) +{ int vol_label_status; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; Dmsg3(100, "Enter read_dev_volume_label_guess device=%s vol=%s dev_Vol=%s\n", - dev_name(dcr->dev), dcr->VolumeName, dcr->dev->VolHdr.VolName); + dev_name(dev), dcr->VolumeName, dev->VolHdr.VolName); - if (!dev_cap(dcr->dev, CAP_REQMOUNT)) { + if (!dev->is_dvd()) { Dmsg0(100, "Leave read_dev_volume_label_guess !CAP_REQMOUNT\n"); return read_dev_volume_label(dcr); } @@ -207,38 +221,37 @@ int read_dev_volume_label_guess(DCR *dcr, bool write) { /* For mounted devices, tries to guess the volume name, and read the label if possible. */ - if (open_guess_name_dev(dcr->dev) < 0) { + if (open_guess_name_dev(dev) < 0) { if ((!write) || (dcr->VolCatInfo.VolCatParts > 0)) { - Mmsg2(dcr->jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula labeled Volume."), - dev_name(dcr->dev), dcr->VolumeName); + Mmsg2(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula labeled Volume."), + dev_name(dev), dcr->VolumeName); Dmsg0(100, "Leave read_dev_volume_label_guess VOL_IO_ERROR (!open_guess_name_dev)\n"); return VOL_NO_LABEL; } - if (write && (dcr->dev->free_space_errno < 0)) { + if (write && (dev->free_space_errno < 0)) { Dmsg0(100, "Leave read_dev_volume_label_guess !free_space VOL_NO_MEDIA\n"); - Mmsg2(dcr->jcr->errmsg, _("free_space error on %s. The current medium is probably not writable. ERR=%s.\n"), - dcr->dev->dev_name, dcr->dev->errmsg); + Mmsg2(jcr->errmsg, _("free_space error on %s. The current medium is probably not writable. ERR=%s.\n"), + dev->dev_name, dev->errmsg); return VOL_NO_MEDIA; } /* If we can't guess the name, and we are writing, just reopen the right file with open_first_part. */ - if (open_first_part(dcr->dev) < 0) { + if (open_first_part(dev) < 0) { berrno be; - Mmsg2(dcr->jcr->errmsg, _("open_first_part error on %s. ERR=%s.\n"), - dcr->dev->dev_name, be.strerror()); + Mmsg2(jcr->errmsg, _("open_first_part error on %s. ERR=%s.\n"), + dev->dev_name, be.strerror()); Dmsg0(100, "Leave read_dev_volume_label_guess VOL_IO_ERROR (!open_guess_name_dev && !open_first_part)\n"); return VOL_IO_ERROR; } Dmsg0(100, "Leave read_dev_volume_label_guess !open_guess_name_dev\n"); return read_dev_volume_label(dcr); - } - else { + } else { if (write && (dcr->dev->free_space_errno < 0)) { Dmsg0(100, "Leave read_dev_volume_label_guess !free_space VOL_NO_MEDIA\n"); - Mmsg2(dcr->jcr->errmsg, _("free_space error on %s. The current medium is probably not writable. ERR=%s.\n"), - dcr->dev->dev_name, dcr->dev->errmsg); + Mmsg2(jcr->errmsg, _("free_space error on %s. The current medium is probably not writable. ERR=%s.\n"), + dev->dev_name, dev->errmsg); return VOL_NO_MEDIA; } @@ -251,8 +264,8 @@ int read_dev_volume_label_guess(DCR *dcr, bool write) { if (open_first_part(dcr->dev) < 0) { berrno be; - Mmsg2(dcr->jcr->errmsg, _("open_first_part error on %s. ERR=%s.\n"), - dcr->dev->dev_name, be.strerror()); + Mmsg2(jcr->errmsg, _("open_first_part error on %s. ERR=%s.\n"), + dev->dev_name, be.strerror()); Dmsg0(100, "Leave read_dev_volume_label_guess VOL_IO_ERROR (open_guess_name_dev && !open_first_part)\n"); return VOL_IO_ERROR; } @@ -262,7 +275,7 @@ int read_dev_volume_label_guess(DCR *dcr, bool write) { */ if (vol_label_status != VOL_NAME_ERROR) { Dmsg0(100, "Leave read_dev_volume_label_guess (open_guess_name_dev && !VOL_NAME_ERROR)\n"); - dcr->dev->state &= ~ST_LABEL; + dev->state &= ~ST_LABEL; return read_dev_volume_label(dcr); } else { @@ -274,7 +287,7 @@ int read_dev_volume_label_guess(DCR *dcr, bool write) { /* unser_volume_label * - * Unserialize the Volume label into the device Volume_Label + * Unserialize the Bacula Volume label into the device Volume_Label * structure. * * Assumes that the record is already read. @@ -497,6 +510,11 @@ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *Po } } + /* Write ANSI/IBM label if so requested */ + if (!write_ansi_ibm_label(dcr, VolName)) { + goto bail_out; + } + create_volume_label_record(dcr, dcr->rec); dcr->rec->Stream = 0; @@ -674,30 +692,29 @@ void dump_volume_label(DEVICE *dev) debug_level = 1; File = dev->file; switch (dev->VolHdr.LabelType) { - case PRE_LABEL: - LabelType = "PRE_LABEL"; - break; - case VOL_LABEL: - LabelType = "VOL_LABEL"; - break; - case EOM_LABEL: - LabelType = "EOM_LABEL"; - break; - case SOS_LABEL: - LabelType = "SOS_LABEL"; - break; - case EOS_LABEL: - LabelType = "EOS_LABEL"; - break; - case EOT_LABEL: - goto bail_out; - default: - LabelType = buf; - sprintf(buf, "Unknown %d", dev->VolHdr.LabelType); - break; + case PRE_LABEL: + LabelType = "PRE_LABEL"; + break; + case VOL_LABEL: + LabelType = "VOL_LABEL"; + break; + case EOM_LABEL: + LabelType = "EOM_LABEL"; + break; + case SOS_LABEL: + LabelType = "SOS_LABEL"; + break; + case EOS_LABEL: + LabelType = "EOS_LABEL"; + break; + case EOT_LABEL: + goto bail_out; + default: + LabelType = buf; + sprintf(buf, "Unknown %d", dev->VolHdr.LabelType); + break; } - Pmsg11(-1, "\nVolume Label:\n" "Id : %s" "VerNo : %d\n" @@ -937,3 +954,152 @@ void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose) } debug_level = dbl; } + +/* + * Write an ANSI or IBM 80 character tape label + * Assume we are positioned at the beginning of the tape. + * Returns: true of OK + * false if error + */ +bool write_ansi_ibm_label(DCR *dcr, const char *VolName) +{ + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + char label[80]; /* tape label */ + char date[20]; /* ansi date buffer */ + time_t now; + int len; + int stat; + + switch (dcr->VolCatInfo.LabelType) { + case B_BACULA_LABEL: + return true; + case B_ANSI_LABEL: + case B_IBM_LABEL: + ser_declare; + Dmsg0(000, "Write ansi label.\n"); + len = strlen(VolName); + if (len > 6) { + len = 6; /* max len ANSI label */ + } + memset(label, ' ', sizeof(label)); + ser_begin(label, sizeof(label)); + ser_bytes("VOL1", 4); + ser_bytes(VolName, len); + label[79] = '1'; /* ANSI label flag */ + /* Write VOL1 label */ + stat = write(dev->fd, label, sizeof(label)); + if (stat != sizeof(label)) { + berrno be; + Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI VOL1 label. ERR=%s\n"), + be.strerror()); + return false; + } + /* Now construct HDR1 label */ + ser_begin(label, sizeof(label)); + ser_bytes("HDR1", 4); + len = strlen(VolName); + if (len > 17) { + len = 17; /* Max filename len */ + } + ser_bytes(VolName, len); /* stick Volume name in Filename field */ + if (len > 6) { + len = 6; + } + ser_begin(&label[21], sizeof(label)-21); + ser_bytes(VolName, len); /* write Vol Ser No. */ + ser_begin(&label[27], sizeof(label)-27); + ser_bytes("000100010001", 12); /* File section, File seq no, Generation no */ + now = time(NULL); + ser_bytes(ansi_date(now, date), 6); /* current date */ + ser_bytes(ansi_date(now - 24 * 3600, date), 6); /* created yesterday */ + ser_bytes(" 000000BACULA ", 27); + /* Write HDR1 label */ + stat = write(dev->fd, label, sizeof(label)); + if (stat != sizeof(label)) { + berrno be; + Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), + be.strerror()); + return false; + } + /* Now construct HDR2 label */ + memset(label, ' ', sizeof(label)); + ser_begin(label, sizeof(label)); + ser_bytes("HDR2F3200032000", 15); + /* Write HDR1 label */ + stat = write(dev->fd, label, sizeof(label)); + if (stat != sizeof(label)) { + berrno be; + Jmsg1(jcr, M_FATAL, 0, _("Could not write ANSI HDR1 label. ERR=%s\n"), + be.strerror()); + return false; + } + if (weof_dev(dev, 1) < 0) { + Jmsg(jcr, M_FATAL, 0, _("Error writing EOF to tape. ERR=%s"), dev->errmsg); + return false; + } + return true; + default: + Jmsg0(jcr, M_ABORT, 0, _("write_ansi_ibm_label called for non-ANSI/IBM type\n")); + return false; /* should not get here */ + } +} + +static int read_ansi_ibm_label(DCR *dcr) +{ + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + char label[80]; /* tape label */ + int retry, stat, i, num_rec; + + if (dcr->VolCatInfo.LabelType == B_BACULA_LABEL) { + return VOL_OK; + } + /* + * Read VOL1, HDR1, HDR2 labels, but ignore the data + * If tape read the following EOF mark, on disk do + * not read. + */ + Dmsg0(000, "Read ansi label.\n"); + if (dev->state & ST_TAPE) { + num_rec = 4; + } else { + num_rec = 3; + } + for (i=0; i < num_rec; i++) { + retry = 0; + do { + stat = read(dev->fd, label, sizeof(label)); + if (retry == 1) { + dev->VolCatInfo.VolCatErrors++; + } + } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 11); + if (stat < 0) { + berrno be; + clrerror_dev(dev, -1); + Dmsg1(200, "Read device got: ERR=%s\n", be.strerror()); + Mmsg2(dev->errmsg, _("Read error on device %s in ANSI/IBM label. ERR=%s\n"), + dev->dev_name, be.strerror()); + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + if (dev->state & ST_EOF) { /* EOF just seen? */ + dev->state |= ST_EOT; /* yes, error => EOT */ + } + return VOL_IO_ERROR; + } + Dmsg1(000, "ANSI label=%80s\n", label); + } + return VOL_OK; +} + + +static char *ansi_date(time_t td, char *buf) +{ + struct tm *tm; + + if (td == 0) { + td = time(NULL); + } + tm = gmtime(&td); + bsnprintf(buf, 6, "%d", 1000 * (tm->tm_year + 1900 - 2000) + tm->tm_yday); + return buf; +} diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 4b58a57aab..fb6103eeeb 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -156,23 +156,24 @@ mount_next_vol: } /* Ensure the device is open */ - /* If we have a device that requires mount, we first want to guess - * which device is loaded, so we continue (if the wrong device is + /* If we have a dvd that requires mount, we first want to guess + * which Volume is loaded, so we continue (if the wrong device is * loaded, open_device would fail). */ - if (!dev_cap(dev, CAP_REQMOUNT)) { + if (!dev->is_dvd()) { if (!open_device(dcr)) { if (dev->poll) { goto mount_next_vol; - } - else { + } else { return false; } } - } - else { - /* Just copy the VolCatName in the device resource (usually done by open_dev). - * It is necessary so we can open the real files later. */ - bstrncpy(dcr->dev->VolCatInfo.VolCatName, dcr->VolCatInfo.VolCatName, sizeof(dcr->dev->VolCatInfo.VolCatName)); + } else { + /* + * Just copy the VolCatName in the device resource + * (usually done by open_dev). + * It is necessary so we can open the real files later. + */ + bstrncpy(dev->VolCatInfo.VolCatName, dcr->VolCatInfo.VolCatName, sizeof(dev->VolCatInfo.VolCatName)); } /* @@ -187,10 +188,9 @@ read_volume: vol_label_status = VOL_OK; create_volume_label(dev, dcr->VolumeName, "Default"); dev->VolHdr.LabelType = PRE_LABEL; - } else if (dev_cap(dev, CAP_REQMOUNT)) { + } else if (dev->is_dvd()) { vol_label_status = read_dev_volume_label_guess(dcr, 1); - } - else { + } else { vol_label_status = read_dev_volume_label(dcr); } if (job_canceled(jcr)) { @@ -410,6 +410,9 @@ static bool rewrite_volume_label(DCR *dcr, bool recycle) } /* Attempt write to check write permission */ Dmsg0(200, "Attempt to write to device.\n"); + if (!write_ansi_ibm_label(dcr, dev->VolHdr.VolName)) { + return false; + } if (!write_block_to_dev(dcr)) { Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"), dev_name(dev), strerror_dev(dev)); @@ -482,7 +485,7 @@ bool mount_next_read_volume(DCR *dcr) if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) { close_dev(dev); dev->state &= ~ST_READ; - if (!acquire_device_for_read(jcr)) { + if (!acquire_device_for_read(jcr, dev)) { Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), dcr->VolumeName); return false; @@ -517,14 +520,13 @@ void release_volume(DCR *dcr) dev->state &= ~(ST_LABEL|ST_READ|ST_APPEND); dcr->VolumeName[0] = 0; - if ((dev->state & ST_OPENED) && - (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN))) { + if (dev->is_open() && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) { offline_or_rewind_dev(dev); close_dev(dev); } /* If we have not closed the device, then at least rewind the tape */ - if (dev->state & ST_OPENED) { + if (dev->is_open()) { offline_or_rewind_dev(dev); } Dmsg0(190, "===== release_volume ---"); diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index b9a2e0e44b..a1fbc6ba07 100755 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2002 Kern Sibbald and John Walker + Copyright (C) 2002-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -32,6 +32,7 @@ typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr); static BSR *store_vol(LEX *lc, BSR *bsr); +static BSR *store_mediatype(LEX *lc, BSR *bsr); static BSR *store_client(LEX *lc, BSR *bsr); static BSR *store_job(LEX *lc, BSR *bsr); static BSR *store_jobid(LEX *lc, BSR *bsr); @@ -60,6 +61,7 @@ struct kw_items { */ struct kw_items items[] = { {"volume", store_vol}, + {"mediatype", store_mediatype}, {"client", store_client}, {"job", store_job}, {"jobid", store_jobid}, @@ -137,13 +139,13 @@ BSR *parse_bsr(JCR *jcr, char *fname) for (i=0; items[i].name; i++) { if (strcasecmp(items[i].name, lc->str) == 0) { token = lex_get_token(lc, T_ALL); - Dmsg1 (200, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); + Dmsg1 (200, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); if (token != T_EQUALS) { - scan_err1(lc, "expected an equals, got: %s", lc->str); + scan_err1(lc, "expected an equals, got: %s", lc->str); bsr = NULL; break; } - Dmsg1(200, "calling handler for %s\n", items[i].name); + Dmsg1(200, "calling handler for %s\n", items[i].name); /* Call item handler */ bsr = items[i].handler(lc, bsr); i = -1; @@ -151,8 +153,8 @@ BSR *parse_bsr(JCR *jcr, char *fname) } } if (i >= 0) { - Dmsg1(200, "Keyword = %s\n", lc->str); - scan_err1(lc, "Keyword %s not found", lc->str); + Dmsg1(200, "Keyword = %s\n", lc->str); + scan_err1(lc, "Keyword %s not found", lc->str); bsr = NULL; break; } @@ -247,6 +249,28 @@ static BSR *store_vol(LEX *lc, BSR *bsr) return bsr; } +/* Shove the MediaType in each Volume in the current bsr */ +static BSR *store_mediatype(LEX *lc, BSR *bsr) +{ + int token; + + token = lex_get_token(lc, T_STRING); + if (token == T_ERROR) { + return NULL; + } + if (!bsr->volume) { + Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"), + lc->str); + return bsr; + } + BSR_VOLUME *bv; + for (bv=bsr->volume; bv; bv=bv->next) { + bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType)); + } + return bsr; +} + + static BSR *store_client(LEX *lc, BSR *bsr) { int token; @@ -619,9 +643,9 @@ void dump_findex(BSR_FINDEX *FileIndex) { if (FileIndex) { if (FileIndex->findex == FileIndex->findex2) { - Dmsg1(-1, "FileIndex : %u\n", FileIndex->findex); + Dmsg1(-1, "FileIndex : %u\n", FileIndex->findex); } else { - Dmsg2(-1, "FileIndex : %u-%u\n", FileIndex->findex, FileIndex->findex2); + Dmsg2(-1, "FileIndex : %u-%u\n", FileIndex->findex, FileIndex->findex2); } dump_findex(FileIndex->next); } @@ -631,9 +655,9 @@ void dump_jobid(BSR_JOBID *jobid) { if (jobid) { if (jobid->JobId == jobid->JobId2) { - Dmsg1(-1, "JobId : %u\n", jobid->JobId); + Dmsg1(-1, "JobId : %u\n", jobid->JobId); } else { - Dmsg2(-1, "JobId : %u-%u\n", jobid->JobId, jobid->JobId2); + Dmsg2(-1, "JobId : %u-%u\n", jobid->JobId, jobid->JobId2); } dump_jobid(jobid->next); } @@ -643,9 +667,9 @@ void dump_sessid(BSR_SESSID *sessid) { if (sessid) { if (sessid->sessid == sessid->sessid2) { - Dmsg1(-1, "SessId : %u\n", sessid->sessid); + Dmsg1(-1, "SessId : %u\n", sessid->sessid); } else { - Dmsg2(-1, "SessId : %u-%u\n", sessid->sessid, sessid->sessid2); + Dmsg2(-1, "SessId : %u-%u\n", sessid->sessid, sessid->sessid2); } dump_sessid(sessid->next); } @@ -852,12 +876,14 @@ void create_vol_list(JCR *jcr) for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) { vol = new_vol(); bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName)); + bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType)); vol->start_file = sfile; if (add_vol(jcr, vol)) { jcr->NumVolumes++; - Dmsg1(400, "Added volume %s\n", vol->VolumeName); + Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName, + vol->MediaType); } else { - Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName); + Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName); free((char *)vol); } sfile = 0; /* start at beginning of second volume */ @@ -866,12 +892,13 @@ void create_vol_list(JCR *jcr) } else { /* This is the old way -- deprecated */ for (p = jcr->dcr->VolumeName; p && *p; ) { - n = strchr(p, '|'); /* volume name separator */ + n = strchr(p, '|'); /* volume name separator */ if (n) { *n++ = 0; /* Terminate name */ } vol = new_vol(); bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName)); + bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType)); if (add_vol(jcr, vol)) { jcr->NumVolumes++; } else { diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index dc3e1eda07..f5ab5defe5 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,177 +28,180 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -DCR *acquire_device_for_append(JCR *jcr); -DCR *acquire_device_for_read(JCR *jcr); -bool release_device(JCR *jcr); -DCR *new_dcr(JCR *jcr, DEVICE *dev); -void free_dcr(DCR *dcr); +bool reserve_device_for_append(JCR *jcr, DEVICE *dev); +DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev); +bool reserve_device_for_read(JCR *jcr, DEVICE *dev); +DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev); +bool release_device(JCR *jcr); +DCR *new_dcr(JCR *jcr, DEVICE *dev); +void free_dcr(DCR *dcr); /* From askdir.c */ enum get_vol_info_rw { GET_VOL_INFO_FOR_WRITE, GET_VOL_INFO_FOR_READ }; -bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); -bool dir_find_next_appendable_volume(DCR *dcr); -bool dir_update_volume_info(DCR *dcr, bool label); -bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); -bool dir_ask_sysop_to_mount_volume(DCR *dcr); -bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); -bool dir_send_job_status(JCR *jcr); -bool dir_create_jobmedia_record(DCR *dcr); +bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); +bool dir_find_next_appendable_volume(DCR *dcr); +bool dir_update_volume_info(DCR *dcr, bool label); +bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); +bool dir_ask_sysop_to_mount_volume(DCR *dcr); +bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); +bool dir_send_job_status(JCR *jcr); +bool dir_create_jobmedia_record(DCR *dcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From autochanger.c */ -int autoload_device(DCR *dcr, int writing, BSOCK *dir); -bool autochanger_list(DCR *dcr, BSOCK *dir); -void invalidate_slot_in_catalog(DCR *dcr); -char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd); +int autoload_device(DCR *dcr, int writing, BSOCK *dir); +bool autochanger_list(DCR *dcr, BSOCK *dir); +void invalidate_slot_in_catalog(DCR *dcr); +char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd); /* From block.c */ -void dump_block(DEV_BLOCK *b, const char *msg); +void dump_block(DEV_BLOCK *b, const char *msg); DEV_BLOCK *new_block(DEVICE *dev); DEV_BLOCK *dup_block(DEV_BLOCK *eblock); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -bool write_block_to_device(DCR *dcr); -bool write_block_to_dev(DCR *dcr); -void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); -void ser_block_header(DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +bool write_block_to_device(DCR *dcr); +bool write_block_to_dev(DCR *dcr); +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); +void ser_block_header(DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false -bool read_block_from_device(DCR *dcr, bool check_block_numbers); -bool read_block_from_dev(DCR *dcr, bool check_block_numbers); +bool read_block_from_device(DCR *dcr, bool check_block_numbers); +bool read_block_from_dev(DCR *dcr, bool check_block_numbers); /* From butil.c -- utilities for SD tool programs */ -void print_ls_output(const char *fname, const char *link, int type, struct stat *statp); +void print_ls_output(const char *fname, const char *link, int type, struct stat *statp); JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr, - const char *VolumeName, int mode); -void display_tape_error_status(JCR *jcr, DEVICE *dev); + const char *VolumeName, int mode); +void display_tape_error_status(JCR *jcr, DEVICE *dev); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, DEVRES *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -off_t lseek_dev(DEVICE *dev, off_t offset, int whence); -int open_first_part(DEVICE *dev); -int open_next_part(DEVICE *dev); -int open_guess_name_dev(DEVICE *dev); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -bool truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -bool update_pos_dev(DEVICE *dev); -bool rewind_dev(DEVICE *dev); -bool load_dev(DEVICE *dev); -bool offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); +DEVICE *init_dev(DEVICE *dev, DEVRES *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +off_t lseek_dev(DEVICE *dev, off_t offset, int whence); +int open_first_part(DEVICE *dev); +int open_next_part(DEVICE *dev); +int open_guess_name_dev(DEVICE *dev); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +bool truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +bool update_pos_dev(DEVICE *dev); +bool rewind_dev(DEVICE *dev); +bool load_dev(DEVICE *dev); +bool offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); uint32_t status_dev(DEVICE *dev); -int eod_dev(DEVICE *dev); -bool fsf_dev(DEVICE *dev, int num); -bool fsr_dev(DEVICE *dev, int num); -bool bsf_dev(DEVICE *dev, int num); -bool bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); -bool dev_can_write(DEVICE *dev); -bool offline_or_rewind_dev(DEVICE *dev); -bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); -void init_dev_wait_timers(DEVICE *dev); -bool double_dev_wait_time(DEVICE *dev); +int eod_dev(DEVICE *dev); +bool fsf_dev(DEVICE *dev, int num); +bool fsr_dev(DEVICE *dev, int num); +bool bsf_dev(DEVICE *dev, int num); +bool bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +bool dev_can_write(DEVICE *dev); +bool offline_or_rewind_dev(DEVICE *dev); +bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); +void init_dev_wait_timers(DEVICE *dev); +bool double_dev_wait_time(DEVICE *dev); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -bool dev_is_tape(DEVICE *dev); +bool dev_is_tape(DEVICE *dev); /* From device.c */ -bool open_device(DCR *dcr); -bool first_open_device(DEVICE *dev); -bool fixup_device_block_write_error(DCR *dcr); -void _lock_device(const char *file, int line, DEVICE *dev); -void _unlock_device(const char *file, int line, DEVICE *dev); -void _block_device(const char *file, int line, DEVICE *dev, int state); -void _unblock_device(const char *file, int line, DEVICE *dev); -void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); -void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold); -void set_new_volume_parameters(DCR *dcr); -void set_new_file_parameters(DCR *dcr); -bool device_is_unmounted(DEVICE *dev); -void dev_lock(DEVICE *dev); -void dev_unlock(DEVICE *dev); +bool open_device(DCR *dcr); +bool first_open_device(DEVICE *dev); +bool fixup_device_block_write_error(DCR *dcr); +void _lock_device(const char *file, int line, DEVICE *dev); +void _unlock_device(const char *file, int line, DEVICE *dev); +void _block_device(const char *file, int line, DEVICE *dev, int state); +void _unblock_device(const char *file, int line, DEVICE *dev); +void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); +void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold); +void set_new_volume_parameters(DCR *dcr); +void set_new_file_parameters(DCR *dcr); +bool device_is_unmounted(DEVICE *dev); +void dev_lock(DEVICE *dev); +void dev_unlock(DEVICE *dev); const char *edit_blocked_reason(DEVICE *dev); /* From dircmd.c */ -void *handle_connection_request(void *arg); +void *handle_connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); -bool bootstrap_cmd(JCR *jcr); +void run_job(JCR *jcr); +bool bootstrap_cmd(JCR *jcr); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(DCR *dcr); -int read_dev_volume_label_guess(DCR *dcr, bool write); -void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); -bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); -bool write_session_label(DCR *dcr, int label); -bool write_volume_label_to_block(DCR *dcr); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(DCR *dcr); +int read_dev_volume_label_guess(DCR *dcr, bool write); +void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); +void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); +bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); +bool write_ansi_ibm_label(DCR *dcr, const char *VolName); +bool write_session_label(DCR *dcr, int label); +bool write_volume_label_to_block(DCR *dcr); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ -int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); -int match_bsr_block(BSR *bsr, DEV_BLOCK *block); -void position_bsr_block(BSR *bsr, DEV_BLOCK *block); -BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); -bool match_set_eof(BSR *bsr, DEV_RECORD *rec); +int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, + SESSION_LABEL *sesrec); +int match_bsr_block(BSR *bsr, DEV_BLOCK *block); +void position_bsr_block(BSR *bsr, DEV_BLOCK *block); +BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); +bool match_set_eof(BSR *bsr, DEV_RECORD *rec); /* From mount.c */ -bool mount_next_write_volume(DCR *dcr, bool release); -bool mount_next_read_volume(DCR *dcr); -void release_volume(DCR *ddr); -void mark_volume_in_error(DCR *dcr); +bool mount_next_write_volume(DCR *dcr, bool release); +bool mount_next_read_volume(DCR *dcr); +void release_volume(DCR *ddr); +void mark_volume_in_error(DCR *dcr); /* From parse_bsr.c */ -BSR *parse_bsr(JCR *jcr, char *lf); -void dump_bsr(BSR *bsr, bool recurse); -void free_bsr(BSR *bsr); +BSR *parse_bsr(JCR *jcr, char *lf); +void dump_bsr(BSR *bsr, bool recurse); +void free_bsr(BSR *bsr); VOL_LIST *new_vol(); -int add_vol(JCR *jcr, VOL_LIST *vol); -void free_vol_list(JCR *jcr); -void create_vol_list(JCR *jcr); +int add_vol(JCR *jcr, VOL_LIST *vol); +void free_vol_list(JCR *jcr); +void create_vol_list(JCR *jcr); /* From record.c */ const char *FI_to_ascii(int fi); const char *stream_to_ascii(int stream, int fi); -bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); -void empty_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); +void empty_record(DEV_RECORD *rec); /* From read_record.c */ bool read_records(DCR *dcr, @@ -206,12 +209,12 @@ bool read_records(DCR *dcr, bool mount_cb(DCR *dcr)); /* From spool.c */ -bool begin_data_spool (JCR *jcr); -bool discard_data_spool (JCR *jcr); -bool commit_data_spool (JCR *jcr); -bool are_attributes_spooled (JCR *jcr); -bool begin_attribute_spool (JCR *jcr); -bool discard_attribute_spool (JCR *jcr); -bool commit_attribute_spool (JCR *jcr); -bool write_block_to_spool_file (DCR *dcr); -void list_spool_stats (BSOCK *bs); +bool begin_data_spool (JCR *jcr); +bool discard_data_spool (JCR *jcr); +bool commit_data_spool (JCR *jcr); +bool are_attributes_spooled (JCR *jcr); +bool begin_attribute_spool (JCR *jcr); +bool discard_attribute_spool (JCR *jcr); +bool commit_attribute_spool (JCR *jcr); +bool write_block_to_spool_file (DCR *dcr); +void list_spool_stats (BSOCK *bs); diff --git a/bacula/src/stored/read.c b/bacula/src/stored/read.c index 6bceb324b1..ec0cdc18b0 100644 --- a/bacula/src/stored/read.c +++ b/bacula/src/stored/read.c @@ -46,11 +46,11 @@ bool do_read_data(JCR *jcr) { BSOCK *fd = jcr->file_bsock; bool ok = true; - DCR *dcr; + DCR *dcr = jcr->dcr; Dmsg0(20, "Start read data.\n"); - if (!bnet_set_buffer_size(fd, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { + if (!bnet_set_buffer_size(fd, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { return false; } @@ -66,11 +66,10 @@ bool do_read_data(JCR *jcr) Dmsg2(200, "Found %d volumes names to restore. First=%s\n", jcr->NumVolumes, jcr->VolList->VolumeName); - /* - * Ready device for reading, and read records - */ - if (!(dcr=acquire_device_for_read(jcr))) { + /* Ready device for reading */ + if (!acquire_device_for_read(jcr, dcr->dev)) { free_vol_list(jcr); + bnet_fsend(fd, FD_error); return false; } diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 6a6c6db381..4a4d91ef22 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -67,10 +67,10 @@ bool read_records(DCR *dcr, if (dev_state(dev, ST_EOT)) { DEV_RECORD *trec = new_record(); - Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n", + Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n", dev->file, dev_name(dev), dcr->VolumeName); if (!mount_cb(dcr)) { - Jmsg(jcr, M_INFO, 0, "End of all volumes.\n"); + Jmsg(jcr, M_INFO, 0, "End of all volumes.\n"); ok = false; /* * Create EOT Label so that Media record may @@ -99,21 +99,21 @@ bool read_records(DCR *dcr, } else if (dev_state(dev, ST_EOF)) { if (verbose) { - Jmsg(jcr, M_INFO, 0, "Got EOF at file %u on device %s, Volume \"%s\"\n", + Jmsg(jcr, M_INFO, 0, "Got EOF at file %u on device %s, Volume \"%s\"\n", dev->file, dev_name(dev), dcr->VolumeName); } - Dmsg3(200, "Got EOF at file %u on device %s, Volume \"%s\"\n", + Dmsg3(200, "Got EOF at file %u on device %s, Volume \"%s\"\n", dev->file, dev_name(dev), dcr->VolumeName); continue; } else if (dev_state(dev, ST_SHORT)) { - Jmsg1(jcr, M_ERROR, 0, "%s", dev->errmsg); + Jmsg1(jcr, M_ERROR, 0, "%s", dev->errmsg); continue; } else { /* I/O error or strange end of tape */ display_tape_error_status(jcr, dev); if (forge_on || jcr->ignore_label_errors) { fsr_dev(dev, 1); /* try skipping bad record */ - Dmsg0(000, "Did fsr\n"); + Dmsg0(000, "Did fsr\n"); continue; /* try to continue */ } ok = false; @@ -146,15 +146,8 @@ bool read_records(DCR *dcr, if (!found) { rec = new_record(); recs->prepend(rec); - Dmsg2(300, "New record for SI=%d ST=%d\n", + Dmsg2(300, "New record for SI=%d ST=%d\n", block->VolSessionId, block->VolSessionTime); - } else { -#ifdef xxx - if (rec->Block != 0 && (rec->Block+1) != block->BlockNumber) { - Jmsg(jcr, M_ERROR, 0, _("Invalid block number. Expected %u, got %u\n"), - rec->Block+1, block->BlockNumber); - } -#endif } Dmsg3(300, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); @@ -163,11 +156,11 @@ bool read_records(DCR *dcr, Dmsg1(300, "Block empty %d\n", is_block_empty(rec)); for (rec->state=0; !is_block_empty(rec); ) { if (!read_record_from_block(block, rec)) { - Dmsg3(400, "!read-break. state=%s blk=%d rem=%d\n", rec_state_to_str(rec), + Dmsg3(400, "!read-break. state=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); break; } - Dmsg5(300, "read-OK. state=%s blk=%d rem=%d file:block=%d:%d\n", + Dmsg5(300, "read-OK. state=%s blk=%d rem=%d file:block=%d:%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder, dev->file, dev->block_num); /* @@ -177,12 +170,12 @@ bool read_records(DCR *dcr, * get all the data. */ record++; - Dmsg6(300, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, + Dmsg6(300, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, rec_state_to_str(rec), block->BlockNumber, rec->VolSessionId, rec->VolSessionTime, rec->FileIndex); if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ - Dmsg0(40, "Get EOM LABEL\n"); + Dmsg0(40, "Get EOM LABEL\n"); break; /* yes, get out */ } @@ -191,7 +184,7 @@ bool read_records(DCR *dcr, handle_session_record(dev, rec, &sessrec); ok = record_cb(dcr, rec); if (rec->FileIndex == EOS_LABEL) { - Dmsg2(300, "Remove rec. SI=%d ST=%d\n", rec->VolSessionId, + Dmsg2(300, "Remove rec. SI=%d ST=%d\n", rec->VolSessionId, rec->VolSessionTime); recs->remove(rec); free_record(rec); @@ -206,35 +199,35 @@ bool read_records(DCR *dcr, int stat = match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec); if (stat == -1) { /* no more possible matches */ done = true; /* all items found, stop */ - Dmsg2(300, "All done=(file:block) %d:%d\n", dev->file, dev->block_num); + Dmsg2(300, "All done=(file:block) %d:%d\n", dev->file, dev->block_num); break; } else if (stat == 0) { /* no match */ - Dmsg4(300, "Clear rem=%d FI=%d before set_eof pos %d:%d\n", + Dmsg4(300, "Clear rem=%d FI=%d before set_eof pos %d:%d\n", rec->remainder, rec->FileIndex, dev->file, dev->block_num); rec->remainder = 0; rec->state &= ~REC_PARTIAL_RECORD; if (try_repositioning(jcr, rec, dev)) { break; } - continue; /* we don't want record, read next one */ + continue; /* we don't want record, read next one */ } } if (is_partial_record(rec)) { - Dmsg6(300, "Partial, break. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, + Dmsg6(300, "Partial, break. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, rec_state_to_str(rec), block->BlockNumber, rec->VolSessionId, rec->VolSessionTime, rec->FileIndex); break; /* read second part of record */ } ok = record_cb(dcr, rec); if (rec->Stream == STREAM_MD5_SIGNATURE || rec->Stream == STREAM_SHA1_SIGNATURE) { - Dmsg3(300, "Done FI=%d before set_eof pos %d:%d\n", rec->FileIndex, + Dmsg3(300, "Done FI=%d before set_eof pos %d:%d\n", rec->FileIndex, dev->file, dev->block_num); if (match_set_eof(jcr->bsr, rec) && try_repositioning(jcr, rec, dev)) { - Dmsg2(300, "Break after match_set_eof pos %d:%d\n", + Dmsg2(300, "Break after match_set_eof pos %d:%d\n", dev->file, dev->block_num); break; } - Dmsg2(300, "After set_eof pos %d:%d\n", dev->file, dev->block_num); + Dmsg2(300, "After set_eof pos %d:%d\n", dev->file, dev->block_num); } } /* end for loop over records */ Dmsg2(300, "After end records position=(file:block) %d:%d\n", dev->file, dev->block_num); @@ -272,7 +265,7 @@ static int try_repositioning(JCR *jcr, DEV_RECORD *rec, DEVICE *dev) } if (bsr) { if (verbose) { - Jmsg(jcr, M_INFO, 0, "Reposition from (file:block) %d:%d to %d:%d\n", + Jmsg(jcr, M_INFO, 0, "Reposition from (file:block) %d:%d to %d:%d\n", dev->file, dev->block_num, bsr->volfile->sfile, bsr->volblock->sblock); } @@ -299,9 +292,9 @@ static BSR *position_to_first_file(JCR *jcr, DEVICE *dev) jcr->bsr->reposition = true; /* force repositioning */ bsr = find_next_bsr(jcr->bsr, dev); if (bsr && (bsr->volfile->sfile != 0 || bsr->volblock->sblock != 0)) { - Jmsg(jcr, M_INFO, 0, _("Forward spacing to file:block %u:%u.\n"), + Jmsg(jcr, M_INFO, 0, _("Forward spacing to file:block %u:%u.\n"), bsr->volfile->sfile, bsr->volblock->sblock); - Dmsg2(300, "Forward spacing to file:block %u:%u.\n", + Dmsg2(300, "Forward spacing to file:block %u:%u.\n", bsr->volfile->sfile, bsr->volblock->sblock); reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock); } diff --git a/bacula/src/stored/record.c b/bacula/src/stored/record.c index dce3c1c9c5..6b3d23dc12 100644 --- a/bacula/src/stored/record.c +++ b/bacula/src/stored/record.c @@ -323,18 +323,18 @@ bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec) #ifdef xxxxxSMCHECK if (!sm_check_rtn(__FILE__, __LINE__, False)) { /* We damaged a buffer */ - Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n" + Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n" "rem=%d remainder=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, stream_to_ascii(rec->Stream, rec->FileIndex), rec->data_len, remlen, rec->remainder); - Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n", + Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n", block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf, remlen); - Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n", + Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n", block->buf, block->bufp-block->buf); - Emsg0(M_ABORT, 0, "Damaged buffer\n"); + Emsg0(M_ABORT, 0, "Damaged buffer\n"); } #endif @@ -402,7 +402,7 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) /* Clear state flags */ rec->state = 0; - if (((DEVICE *)block->dev)->state & ST_TAPE) { + if (block->dev->is_tape()) { rec->state |= REC_ISTAPE; } @@ -444,7 +444,7 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) if (rec->remainder && (rec->VolSessionId != VolSessionId || rec->VolSessionTime != VolSessionTime)) { rec->state |= REC_NO_MATCH; - Dmsg0(450, "remainder and VolSession doesn't match\n"); + Dmsg0(450, "remainder and VolSession doesn't match\n"); return false; /* This is from some other Session */ } @@ -452,10 +452,10 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) * of a previous partially written record. */ if (Stream < 0) { /* continuation record? */ - Dmsg1(500, "Got negative Stream => continuation. remainder=%d\n", + Dmsg1(500, "Got negative Stream => continuation. remainder=%d\n", rec->remainder); rec->state |= REC_CONTINUATION; - if (!rec->remainder) { /* if we didn't read previously */ + if (!rec->remainder) { /* if we didn't read previously */ rec->data_len = 0; /* return data as if no continuation */ } else if (rec->Stream != -Stream) { rec->state |= REC_NO_MATCH; @@ -477,7 +477,7 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) } Dmsg6(450, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n" - "remlen=%d data_len=%d\n", + "remlen=%d data_len=%d\n", FI_to_ascii(rec->FileIndex), rec->VolSessionId, stream_to_ascii(rec->Stream, rec->FileIndex), data_bytes, remlen, rec->data_len); @@ -491,12 +491,6 @@ bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec) * then reread. */ Dmsg0(450, "read_record_block: nothing\n"); -#ifdef xxx - if (!rec->remainder) { - rec->remainder = 1; /* set to expect continuation */ - rec->data_len = 0; /* no data transferred */ - } -#endif rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY); empty_block(block); /* mark block empty */ return false; diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index 89a774f64c..ac7bd0f322 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -93,7 +93,7 @@ bool begin_data_spool(JCR *jcr) stat = open_data_spool_file(jcr); if (stat) { jcr->dcr->spooling = true; - Jmsg(jcr, M_INFO, 0, _("Spooling data ...\n")); + Jmsg(jcr, M_INFO, 0, _("Spooling data ...\n")); P(mutex); spool_stats.data_jobs++; V(mutex); @@ -119,7 +119,7 @@ bool commit_data_spool(JCR *jcr) Dmsg0(100, "Committing spooled data\n"); stat = despool_data(jcr->dcr, true /*commit*/); if (!stat) { - Pmsg1(000, "Bad return from despool WroteVol=%d\n", jcr->dcr->WroteVol); + Pmsg1(000, "Bad return from despool WroteVol=%d\n", jcr->dcr->WroteVol); close_data_spool_file(jcr); return false; } @@ -136,7 +136,8 @@ static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name) } else { dir = working_directory; } - Mmsg(name, "%s/%s.data.spool.%s.%s", dir, my_name, jcr->Job, jcr->device->hdr.name); + Mmsg(name, "%s/%s.data.spool.%s.%s", dir, my_name, jcr->Job, + jcr->dcr->device->hdr.name); } @@ -300,11 +301,11 @@ static int read_block_from_spool_file(DCR *dcr) } else if (stat != (ssize_t)rlen) { if (stat == -1) { berrno be; - Jmsg(dcr->jcr, M_FATAL, 0, _("Spool header read error. ERR=%s\n"), + Jmsg(dcr->jcr, M_FATAL, 0, _("Spool header read error. ERR=%s\n"), be.strerror()); } else { - Pmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat); - Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool header read error. Wanted %u bytes, got %u\n"), rlen, stat); + Pmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat); + Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool header read error. Wanted %u bytes, got %u\n"), rlen, stat); } return RB_ERROR; } @@ -368,7 +369,7 @@ bool write_block_to_spool_file(DCR *dcr) #ifdef xDEBUG char ec1[30], ec2[30], ec3[30], ec4[30]; Dmsg4(100, "Despool in write_block_to_spool_file max_size=%s size=%s " - "max_job_size=%s job_size=%s\n", + "max_job_size=%s job_size=%s\n", edit_uint64_with_commas(dcr->max_spool_size, ec1), edit_uint64_with_commas(dcr->spool_size, ec2), edit_uint64_with_commas(dcr->dev->max_spool_size, ec3), @@ -376,7 +377,7 @@ bool write_block_to_spool_file(DCR *dcr) #endif Jmsg(dcr->jcr, M_INFO, 0, _("User specified spool size reached.\n")); if (!despool_data(dcr, false)) { - Pmsg0(000, "Bad return from despool in write_block.\n"); + Pmsg0(000, "Bad return from despool in write_block.\n"); return false; } /* Despooling cleared these variables so reset them */ @@ -415,7 +416,7 @@ static bool write_spool_header(DCR *dcr) stat = write(dcr->spool_fd, (char*)&hdr, sizeof(hdr)); if (stat == -1) { berrno be; - Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing header to spool file. ERR=%s\n"), + Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing header to spool file. ERR=%s\n"), be.strerror()); } if (stat != (ssize_t)sizeof(hdr)) { @@ -423,13 +424,13 @@ static bool write_spool_header(DCR *dcr) if (stat != -1) { if (ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) - stat) != 0) { berrno be; - Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file failed: ERR=%s\n"), + Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file failed: ERR=%s\n"), be.strerror()); return false; } } if (!despool_data(dcr, false)) { - Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); + Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); return false; } continue; /* try again */ @@ -450,7 +451,7 @@ static bool write_spool_data(DCR *dcr) stat = write(dcr->spool_fd, block->buf, (size_t)block->binbuf); if (stat == -1) { berrno be; - Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing data to spool file. ERR=%s\n"), + Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing data to spool file. ERR=%s\n"), be.strerror()); } if (stat != (ssize_t)block->binbuf) { @@ -461,13 +462,13 @@ static bool write_spool_data(DCR *dcr) if (ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) - stat - sizeof(spool_hdr)) != 0) { berrno be; - Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file failed: ERR=%s\n"), + Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file failed: ERR=%s\n"), be.strerror()); return false; } } if (!despool_data(dcr, false)) { - Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); + Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); return false; } if (!write_spool_header(dcr)) { @@ -532,7 +533,7 @@ bool commit_attribute_spool(JCR *jcr) if (are_attributes_spooled(jcr)) { if (fseek(jcr->dir_bsock->spool_fd, 0, SEEK_END) != 0) { berrno be; - Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"), + Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"), be.strerror()); } size = ftell(jcr->dir_bsock->spool_fd); diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index a9c0bf9146..59196f3c9b 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -97,48 +97,47 @@ bool status_cmd(JCR *jcr) bnet_fsend(user, _("\nDevice status:\n")); LockRes(); foreach_res(device, R_DEVICE) { - for (dev=device->dev; dev; dev=dev->next) { - if (dev_state(dev, ST_OPENED)) { - if (dev_state(dev, ST_LABEL)) { - bnet_fsend(user, _("Device \"%s\" is mounted with Volume \"%s\"\n"), - dev_name(dev), dev->VolHdr.VolName); - } else { - bnet_fsend(user, _("Device \"%s\" open but no Bacula volume is mounted.\n"), dev_name(dev)); + dev = device->dev; + if (dev->is_open()) { + if (dev->is_labeled()) { + bnet_fsend(user, _("Device \"%s\" is mounted with Volume \"%s\"\n"), + dev_name(dev), dev->VolHdr.VolName); + } else { + bnet_fsend(user, _("Device \"%s\" open but no Bacula volume is mounted.\n"), dev_name(dev)); + } + send_blocked_status(jcr, dev); + if (dev_state(dev, ST_APPEND)) { + bpb = dev->VolCatInfo.VolCatBlocks; + if (bpb <= 0) { + bpb = 1; } - send_blocked_status(jcr, dev); - if (dev_state(dev, ST_APPEND)) { - bpb = dev->VolCatInfo.VolCatBlocks; - if (bpb <= 0) { - bpb = 1; - } - bpb = dev->VolCatInfo.VolCatBytes / bpb; - bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"), - edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1), - edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), - edit_uint64_with_commas(bpb, b3)); - } else { /* reading */ - bpb = dev->VolCatInfo.VolCatReads; - if (bpb <= 0) { - bpb = 1; - } - if (dev->VolCatInfo.VolCatRBytes > 0) { - bpb = dev->VolCatInfo.VolCatRBytes / bpb; - } else { - bpb = 0; - } - bnet_fsend(user, _(" Total Bytes Read=%s Blocks Read=%s Bytes/block=%s\n"), - edit_uint64_with_commas(dev->VolCatInfo.VolCatRBytes, b1), - edit_uint64_with_commas(dev->VolCatInfo.VolCatReads, b2), - edit_uint64_with_commas(bpb, b3)); + bpb = dev->VolCatInfo.VolCatBytes / bpb; + bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"), + edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1), + edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), + edit_uint64_with_commas(bpb, b3)); + } else { /* reading */ + bpb = dev->VolCatInfo.VolCatReads; + if (bpb <= 0) { + bpb = 1; } - bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"), - 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)); - send_blocked_status(jcr, dev); + if (dev->VolCatInfo.VolCatRBytes > 0) { + bpb = dev->VolCatInfo.VolCatRBytes / bpb; + } else { + bpb = 0; + } + bnet_fsend(user, _(" Total Bytes Read=%s Blocks Read=%s Bytes/block=%s\n"), + edit_uint64_with_commas(dev->VolCatInfo.VolCatRBytes, b1), + edit_uint64_with_commas(dev->VolCatInfo.VolCatReads, b2), + edit_uint64_with_commas(bpb, b3)); } + bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"), + 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)); + send_blocked_status(jcr, dev); } } UnlockRes(); @@ -202,22 +201,23 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev) bnet_fsend(user, "\n"); bnet_fsend(user, _("Device status:\n")); - bnet_fsend(user, "%sOPENED ", dev->state & ST_OPENED ? "" : "!"); - bnet_fsend(user, "%sTAPE ", dev->state & ST_TAPE ? "" : "!"); - bnet_fsend(user, "%sLABEL ", dev->state & ST_LABEL ? "" : "!"); + bnet_fsend(user, "%sOPENED ", dev->is_open() ? "" : "!"); + bnet_fsend(user, "%sTAPE ", dev->is_tape() ? "" : "!"); + bnet_fsend(user, "%sLABEL ", dev->is_labeled() ? "" : "!"); bnet_fsend(user, "%sMALLOC ", dev->state & ST_MALLOC ? "" : "!"); - bnet_fsend(user, "%sAPPEND ", dev->state & ST_APPEND ? "" : "!"); - bnet_fsend(user, "%sREAD ", dev->state & ST_READ ? "" : "!"); - bnet_fsend(user, "%sEOT ", dev->state & ST_EOT ? "" : "!"); + bnet_fsend(user, "%sAPPEND ", dev->can_append() ? "" : "!"); + bnet_fsend(user, "%sREAD ", dev->can_read() ? "" : "!"); + bnet_fsend(user, "%sEOT ", dev->at_eom() ? "" : "!"); bnet_fsend(user, "%sWEOT ", dev->state & ST_WEOT ? "" : "!"); - bnet_fsend(user, "%sEOF ", dev->state & ST_EOF ? "" : "!"); + bnet_fsend(user, "%sEOF ", dev->at_eof() ? "" : "!"); bnet_fsend(user, "%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!"); bnet_fsend(user, "%sSHORT ", dev->state & ST_SHORT ? "" : "!"); bnet_fsend(user, "%sMOUNTED ", dev->state & ST_MOUNTED ? "" : "!"); bnet_fsend(user, "\n"); bnet_fsend(user, _("Device parameters:\n")); - bnet_fsend(user, "Device name: %s\n", dev->dev_name); + bnet_fsend(user, "Archive name: %s Device name: %s\n", dev->dev_name, + dev->device->hdr.name); bnet_fsend(user, "File=%u block=%u\n", dev->file, dev->block_num); bnet_fsend(user, "Min block=%u Max block=%u\n", dev->min_block_size, dev->max_block_size); } @@ -239,7 +239,7 @@ static void list_running_jobs(BSOCK *user) bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"), job_type_to_str(jcr->JobType), jcr->Job); } - if (jcr->device) { + if (jcr->dcr && jcr->dcr->device) { bstrncpy(JobName, jcr->Job, sizeof(JobName)); /* There are three periods after the Job name */ char *p; @@ -253,8 +253,8 @@ static void list_running_jobs(BSOCK *user) job_type_to_str(jcr->JobType), JobName, jcr->JobId, - jcr->dcr?jcr->dcr->VolumeName:"*none*", - jcr->device?jcr->device->device_name:"none"); + jcr->dcr->VolumeName, + jcr->dcr->device->device_name); sec = time(NULL) - jcr->run_time; if (sec <= 0) { sec = 1; diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 017fa608e3..afe1ee9d42 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -10,7 +10,7 @@ * */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -65,7 +65,7 @@ static workq_t dird_workq; /* queue for processing connections */ static void usage() { fprintf(stderr, _( -"Copyright (C) 2000-2004 Kern Sibbald and John Walker.\n" +"Copyright (C) 2000-2005 Kern Sibbald.\n" "\nVersion: " VERSION " (" BDATE ")\n\n" "Usage: stored [options] [-c config_file] [config_file]\n" " -c use as configuration file\n" @@ -179,7 +179,6 @@ int main (int argc, char *argv[]) init_signals(terminate_stored); } - if (configfile == NULL) { configfile = bstrdup(CONFIG_FILE); } @@ -206,7 +205,7 @@ int main (int argc, char *argv[]) */ VolSessionTime = (long)daemon_start_time; if (VolSessionTime == 0) { /* paranoid */ - Emsg0(M_ABORT, 0, _("Volume Session Time is ZERO!\n")); + Jmsg0(NULL, M_ABORT, 0, _("Volume Session Time is ZERO!\n")); } /* Make sure on Solaris we can run concurrent, watch dog + servers + misc */ @@ -254,7 +253,7 @@ static void check_config() me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { UnlockRes(); - Emsg1(M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"), + Jmsg1(NULL, M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"), configfile); } @@ -262,23 +261,23 @@ static void check_config() if (GetNextRes(R_STORAGE, (RES *)me) != NULL) { UnlockRes(); - Emsg1(M_ERROR_TERM, 0, _("Only one Storage resource permitted in %s\n"), + Jmsg1(NULL, M_ERROR_TERM, 0, _("Only one Storage resource permitted in %s\n"), configfile); } if (GetNextRes(R_DIRECTOR, NULL) == NULL) { UnlockRes(); - Emsg1(M_ERROR_TERM, 0, _("No Director resource defined in %s. Cannot continue.\n"), + Jmsg1(NULL, M_ERROR_TERM, 0, _("No Director resource defined in %s. Cannot continue.\n"), configfile); } if (GetNextRes(R_DEVICE, NULL) == NULL){ UnlockRes(); - Emsg1(M_ERROR_TERM, 0, _("No Device resource defined in %s. Cannot continue.\n"), + Jmsg1(NULL, M_ERROR_TERM, 0, _("No Device resource defined in %s. Cannot continue.\n"), configfile); } if (!me->messages) { me->messages = (MSGS *)GetNextRes(R_MSGS, NULL); if (!me->messages) { - Emsg1(M_ERROR_TERM, 0, _("No Messages resource defined in %s. Cannot continue.\n"), + Jmsg1(NULL, M_ERROR_TERM, 0, _("No Messages resource defined in %s. Cannot continue.\n"), configfile); } } @@ -288,7 +287,7 @@ static void check_config() UnlockRes(); if (!me->working_directory) { - Emsg1(M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"), + Jmsg1(NULL, M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"), configfile); } @@ -296,8 +295,8 @@ static void check_config() } /* - * We are started as a separate thread. The - * resources are alread locked. + * Here we attempt to init and open each device. This is done + * once at startup in a separate thread. */ extern "C" void *device_allocation(void *arg) @@ -312,14 +311,14 @@ void *device_allocation(void *arg) device->dev = init_dev(NULL, device); Dmsg1(10, "SD init done %s\n", device->device_name); if (!device->dev) { - Emsg1(M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); + Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); continue; } if (device->cap_bits & CAP_ALWAYSOPEN) { - Dmsg1(20, "calling first_open_device %s\n", device->device_name); + Dmsg1(20, "calling first_open_device %s\n", device->device_name); if (!first_open_device(device->dev)) { - Emsg1(M_ERROR, 0, _("Could not open device %s\n"), device->device_name); + Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), device->device_name); } } if (device->cap_bits & CAP_AUTOMOUNT && device->dev && @@ -331,17 +330,16 @@ void *device_allocation(void *arg) /* Initialize FD start condition variable */ int errstat = pthread_cond_init(&jcr->job_start_wait, NULL); if (errstat != 0) { - Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat)); + Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat)); } - jcr->device = device; dcr = new_dcr(jcr, device->dev); switch (read_dev_volume_label(dcr)) { - case VOL_OK: - memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo)); - break; - default: - Emsg1(M_WARNING, 0, _("Could not mount device %s\n"), device->device_name); - break; + case VOL_OK: + memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo)); + break; + default: + Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), device->device_name); + break; } free_jcr(jcr); } @@ -381,10 +379,11 @@ void terminate_stored(int sig) fd = jcr->file_bsock; if (fd) { fd->timed_out = true; - Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId); + Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId); pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); - if (jcr->device && jcr->device->dev && jcr->device->dev->dev_blocked) { - pthread_cond_signal(&jcr->device->dev->wait_next_vol); + /* ***FIXME*** wiffle through all dcrs */ + if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) { + pthread_cond_signal(&jcr->dcr->dev->wait_next_vol); } bmicrosleep(0, 50000); } diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 00c7b2df58..6169057ca1 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -132,6 +132,17 @@ static RES_ITEM dev_items[] = { {NULL, NULL, 0, 0, 0, 0} }; +/* Autochanger definition */ +static RES_ITEM changer_items[] = { + {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0}, + {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0}, + {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, 0, 0}, + {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, 0, 0}, + {NULL, NULL, 0, 0, 0, 0} +}; + + // {"mountanonymousvolumes", store_yesno, ITEM(res_dev.cap_bits), CAP_ANONVOLS, ITEM_DEFAULT, 0}, @@ -141,11 +152,12 @@ extern RES_ITEM msgs_items[]; /* This is the master resource definition */ RES_TABLE resources[] = { - {"director", dir_items, R_DIRECTOR}, - {"storage", store_items, R_STORAGE}, - {"device", dev_items, R_DEVICE}, - {"messages", msgs_items, R_MSGS}, - {NULL, NULL, 0} + {"director", dir_items, R_DIRECTOR}, + {"storage", store_items, R_STORAGE}, + {"device", dev_items, R_DEVICE}, + {"messages", msgs_items, R_MSGS}, + {"autochanger", changer_items, R_AUTOCHANGER}, + {NULL, NULL, 0} }; @@ -202,7 +214,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory)); sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n", res->res_dev.max_spool_size, res->res_dev.max_job_spool_size); - strcpy(buf, " "); + bstrncpy(buf, " ", sizeof(buf)); if (res->res_dev.cap_bits & CAP_EOF) { bstrncat(buf, "CAP_EOF ", sizeof(buf)); } @@ -242,6 +254,17 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm bstrncat(buf, "\n", sizeof(buf)); sendit(sock, buf); break; + case R_AUTOCHANGER: + DEVRES *dev; + sendit(sock, "Changer: name=%s Changer_devname=%s Changer_cmd=%s\n", + res->res_changer.hdr.name, + res->res_changer.changer_name, res->res_changer.changer_command); + foreach_alist(dev, res->res_changer.device) { + sendit(sock, " --->Device: name=%s\n", dev->hdr.name); + } + bstrncat(buf, "\n", sizeof(buf)); + sendit(sock, buf); + break; case R_MSGS: sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name); if (res->res_msgs.mail_cmd) @@ -283,79 +306,86 @@ void free_resource(RES *sres, int type) switch (type) { - case R_DIRECTOR: - if (res->res_dir.password) { - free(res->res_dir.password); - } - if (res->res_dir.address) { - free(res->res_dir.address); - } - break; - case R_STORAGE: - if (res->res_store.sdaddrs) { - free_addresses(res->res_store.sdaddrs); - } - if (res->res_store.sddaddrs) { - free_addresses(res->res_store.sddaddrs); - } - if (res->res_store.working_directory) { - free(res->res_store.working_directory); - } - if (res->res_store.pid_directory) { - free(res->res_store.pid_directory); - } - if (res->res_store.subsys_directory) { - free(res->res_store.subsys_directory); - } - break; - case R_DEVICE: - if (res->res_dev.media_type) { - free(res->res_dev.media_type); - } - if (res->res_dev.device_name) { - free(res->res_dev.device_name); - } - if (res->res_dev.changer_name) { - free(res->res_dev.changer_name); - } - if (res->res_dev.changer_command) { - free(res->res_dev.changer_command); - } - if (res->res_dev.alert_command) { - free(res->res_dev.alert_command); - } - if (res->res_dev.spool_directory) { - free(res->res_dev.spool_directory); - } - if (res->res_dev.mount_point) { - free(res->res_dev.mount_point); - } - if (res->res_dev.mount_command) { - free(res->res_dev.mount_command); - } - if (res->res_dev.unmount_command) { - free(res->res_dev.unmount_command); - } - if (res->res_dev.write_part_command) { - free(res->res_dev.write_part_command); - } - if (res->res_dev.free_space_command) { - free(res->res_dev.free_space_command); - } - break; - case R_MSGS: - if (res->res_msgs.mail_cmd) { - free(res->res_msgs.mail_cmd); - } - if (res->res_msgs.operator_cmd) { - free(res->res_msgs.operator_cmd); - } - free_msgs_res((MSGS *)res); /* free message resource */ - res = NULL; - break; - default: - Dmsg1(0, "Unknown resource type %d\n", type); - break; + case R_DIRECTOR: + if (res->res_dir.password) { + free(res->res_dir.password); + } + if (res->res_dir.address) { + free(res->res_dir.address); + } + break; + case R_AUTOCHANGER: + if (res->res_changer.changer_name) { + free(res->res_changer.changer_name); + } + if (res->res_changer.changer_command) { + free(res->res_changer.changer_command); + } + case R_STORAGE: + if (res->res_store.sdaddrs) { + free_addresses(res->res_store.sdaddrs); + } + if (res->res_store.sddaddrs) { + free_addresses(res->res_store.sddaddrs); + } + if (res->res_store.working_directory) { + free(res->res_store.working_directory); + } + if (res->res_store.pid_directory) { + free(res->res_store.pid_directory); + } + if (res->res_store.subsys_directory) { + free(res->res_store.subsys_directory); + } + break; + case R_DEVICE: + if (res->res_dev.media_type) { + free(res->res_dev.media_type); + } + if (res->res_dev.device_name) { + free(res->res_dev.device_name); + } + if (res->res_dev.changer_name) { + free(res->res_dev.changer_name); + } + if (res->res_dev.changer_command) { + free(res->res_dev.changer_command); + } + if (res->res_dev.alert_command) { + free(res->res_dev.alert_command); + } + if (res->res_dev.spool_directory) { + free(res->res_dev.spool_directory); + } + if (res->res_dev.mount_point) { + free(res->res_dev.mount_point); + } + if (res->res_dev.mount_command) { + free(res->res_dev.mount_command); + } + if (res->res_dev.unmount_command) { + free(res->res_dev.unmount_command); + } + if (res->res_dev.write_part_command) { + free(res->res_dev.write_part_command); + } + if (res->res_dev.free_space_command) { + free(res->res_dev.free_space_command); + } + break; + case R_MSGS: + if (res->res_msgs.mail_cmd) { + free(res->res_msgs.mail_cmd); + } + if (res->res_msgs.operator_cmd) { + free(res->res_msgs.operator_cmd); + } + free_msgs_res((MSGS *)res); /* free message resource */ + res = NULL; + break; + default: + Dmsg1(0, "Unknown resource type %d\n", type); + break; } /* Common stuff again -- free the resource, recurse to next one */ if (res) { @@ -368,7 +398,7 @@ void free_resource(RES *sres, int type) /* Save the new resource by chaining it into the head list for * the resource. If this is pass 2, we update any resource - * pointers (currently only in the Job resource). + * or alist pointers. */ void save_resource(int type, RES_ITEM *items, int pass) { @@ -400,23 +430,31 @@ void save_resource(int type, RES_ITEM *items, int pass) */ if (pass == 2) { switch (type) { - /* Resources not containing a resource */ - case R_DIRECTOR: - case R_DEVICE: - case R_MSGS: - break; - - /* Resources containing a resource */ - case R_STORAGE: - if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { - Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name); - } - res->res_store.messages = res_all.res_store.messages; - break; - default: - printf("Unknown resource type %d\n", type); - error = 1; - break; + /* Resources not containing a resource */ + case R_DIRECTOR: + case R_DEVICE: + case R_MSGS: + break; + + /* Resources containing a resource or an alist */ + case R_STORAGE: + if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { + Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name); + } + res->res_store.messages = res_all.res_store.messages; + break; + case R_AUTOCHANGER: + if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) { + Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n", + res_all.res_changer.hdr.name); + } + /* we must explicitly copy the device alist pointer */ + res->res_changer.device = res_all.res_changer.device; + break; + default: + printf("Unknown resource type %d\n", type); + error = 1; + break; } @@ -445,6 +483,9 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_MSGS: size = sizeof(MSGS); break; + case R_AUTOCHANGER: + size = sizeof(AUTOCHANGER); + break; default: printf("Unknown resource type %d\n", type); error = 1; diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 4e68d83d69..7f92e20d38 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -28,8 +28,9 @@ enum { R_STORAGE, R_DEVICE, R_MSGS, + R_AUTOCHANGER, R_FIRST = R_DIRECTOR, - R_LAST = R_MSGS /* keep this updated */ + R_LAST = R_AUTOCHANGER /* keep this updated */ }; enum { @@ -42,74 +43,86 @@ enum { /* Definition of the contents of each Resource */ -struct DIRRES { - RES hdr; +class DIRRES { +public: + RES hdr; - char *password; /* Director password */ - char *address; /* Director IP address or zero */ - int enable_ssl; /* Use SSL with this Director */ - int monitor; /* Have only access to status and .status functions */ + char *password; /* Director password */ + char *address; /* Director IP address or zero */ + int enable_ssl; /* Use SSL with this Director */ + int monitor; /* Have only access to status and .status functions */ }; /* Storage daemon "global" definitions */ -struct s_res_store { - RES hdr; +class s_res_store { +public: + RES hdr; dlist *sdaddrs; dlist *sddaddrs; - char *working_directory; /* working directory for checkpoints */ + char *working_directory; /* working directory for checkpoints */ char *pid_directory; char *subsys_directory; - int require_ssl; /* Require SSL on all connections */ + int require_ssl; /* Require SSL on all connections */ uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */ - MSGS *messages; /* Daemon message handler */ - utime_t heartbeat_interval; /* Interval to send hb to FD */ + MSGS *messages; /* Daemon message handler */ + utime_t heartbeat_interval; /* Interval to send hb to FD */ }; typedef struct s_res_store STORES; /* Device specific definitions */ -struct DEVRES { - RES hdr; - - char *media_type; /* User assigned media type */ - char *device_name; /* Archive device name */ - char *changer_name; /* Changer device name */ - char *changer_command; /* Changer command -- external program */ - char *alert_command; /* Alert command -- external program */ - char *spool_directory; /* Spool file directory */ - uint32_t drive_index; /* Autochanger drive index */ - uint32_t cap_bits; /* Capabilities of this device */ - uint32_t max_changer_wait; /* Changer timeout */ - uint32_t max_rewind_wait; /* maximum secs to wait for rewind */ - uint32_t max_open_wait; /* maximum secs to wait for open */ - uint32_t max_open_vols; /* maximum simultaneous open volumes */ - uint32_t min_block_size; /* min block size */ - uint32_t max_block_size; /* max block size */ - uint32_t max_volume_jobs; /* max jobs to put on one volume */ +class DEVRES { +public: + RES hdr; + + char *media_type; /* User assigned media type */ + char *device_name; /* Archive device name */ + char *changer_name; /* Changer device name */ + char *changer_command; /* Changer command -- external program */ + char *alert_command; /* Alert command -- external program */ + char *spool_directory; /* Spool file directory */ + uint32_t drive_index; /* Autochanger drive index */ + uint32_t cap_bits; /* Capabilities of this device */ + uint32_t max_changer_wait; /* Changer timeout */ + uint32_t max_rewind_wait; /* maximum secs to wait for rewind */ + uint32_t max_open_wait; /* maximum secs to wait for open */ + uint32_t max_open_vols; /* maximum simultaneous open volumes */ + uint32_t min_block_size; /* min block size */ + uint32_t max_block_size; /* max block size */ + uint32_t max_volume_jobs; /* max jobs to put on one volume */ uint32_t max_network_buffer_size; /* max network buf size */ - utime_t vol_poll_interval; /* interval between polling volume during mount */ - int64_t max_volume_files; /* max files to put on one volume */ - int64_t max_volume_size; /* max bytes to put on one volume */ - int64_t max_file_size; /* max file size in bytes */ - int64_t volume_capacity; /* advisory capacity */ - int64_t max_spool_size; /* Max spool size for all jobs */ - int64_t max_job_spool_size; /* Max spool size for any single job */ + utime_t vol_poll_interval; /* interval between polling volume during mount */ + int64_t max_volume_files; /* max files to put on one volume */ + int64_t max_volume_size; /* max bytes to put on one volume */ + int64_t max_file_size; /* max file size in bytes */ + int64_t volume_capacity; /* advisory capacity */ + int64_t max_spool_size; /* Max spool size for all jobs */ + int64_t max_job_spool_size; /* Max spool size for any single job */ - int64_t max_part_size; /* Max part size */ - char *mount_point; /* Mount point for require mount devices */ - char *mount_command; /* Mount command */ - char *unmount_command; /* Unmount command */ - char *write_part_command; /* Write part command */ - char *free_space_command; /* Free space command */ + int64_t max_part_size; /* Max part size */ + char *mount_point; /* Mount point for require mount devices */ + char *mount_command; /* Mount command */ + char *unmount_command; /* Unmount command */ + char *write_part_command; /* Write part command */ + char *free_space_command; /* Free space command */ - DEVICE *dev; /* Pointer to phyical dev -- set at runtime */ + DEVICE *dev; /* Pointer to phyical dev -- set at runtime */ +}; + +class AUTOCHANGER { +public: + RES hdr; + alist *device; + char *changer_name; /* Changer device name */ + char *changer_command; /* Changer command -- external program */ }; union URES { - DIRRES res_dir; - STORES res_store; - DEVRES res_dev; - MSGS res_msgs; - RES hdr; + DIRRES res_dir; + STORES res_store; + DEVRES res_dev; + MSGS res_msgs; + AUTOCHANGER res_changer; + RES hdr; }; diff --git a/bacula/src/version.h b/bacula/src/version.h index 12dcce9cde..b24b17e1d1 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION -#define VERSION "1.37.2" -#define BDATE "12 January 2005" -#define LSMDATE "12Jan05" +#define VERSION "1.37.3" +#define BDATE "28 January 2005" +#define LSMDATE "28Jan05" /* Debug flags */ #undef DEBUG -- 2.39.5