From a64e57850ac943b84184f43e712ccf18b498ca30 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@91ce42f0-d328-0410-95d8-f526ca767f89> Date: Mon, 3 Nov 2003 09:24:50 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'Release-1.32d'. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/tags/Release-1.32d@796 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/.cvsignore | 4 + bacula/ChangeLog | 161 + bacula/CheckList | 2 +- bacula/Makefile.in | 1 + bacula/ReleaseNotes | 53 +- bacula/autoconf/acconfig.h | 4 +- bacula/autoconf/aclocal.m4 | 5 + bacula/autoconf/config.h.in | 4 +- bacula/autoconf/configure.in | 27 +- bacula/configure | 69 +- bacula/kernstodo | 390 ++- bacula/platforms/freebsd/pthreads-fix.txt | 193 ++ bacula/platforms/redhat/bacula.spec.in | 11 +- bacula/scripts/set-gnome1.4 | 18 + bacula/scripts/set-gnome2 | 16 + bacula/src/.cvsignore | 1 + bacula/src/Makefile.in | 2 + bacula/src/cats/bdb_find.c | 4 +- bacula/src/cats/bdb_get.c | 2 +- bacula/src/cats/make_catalog_backup.in | 4 +- bacula/src/cats/make_catalog_backup.in.patch | 16 + bacula/src/cats/make_mysql_tables.in | 2 +- bacula/src/cats/mysql.c | 4 + bacula/src/cats/protos.h | 4 +- bacula/src/cats/sql_delete.c | 8 +- bacula/src/cats/sql_find.c | 74 +- bacula/src/cats/sql_get.c | 41 +- bacula/src/cats/sql_update.c | 5 +- bacula/src/console/Makefile.in | 2 +- bacula/src/console2.glade | 3080 +++++++++++++++++ bacula/src/console2.gladep | 8 + bacula/src/dird/.cvsignore | 1 + bacula/src/dird/Makefile.in | 4 +- bacula/src/dird/authenticate.c | 4 +- bacula/src/dird/backup.c | 17 +- bacula/src/dird/bacula-dir.conf.in | 2 +- bacula/src/dird/bsr.c | 53 +- bacula/src/dird/catreq.c | 14 +- bacula/src/dird/dird.c | 2 +- bacula/src/dird/dird_conf.c | 19 +- bacula/src/dird/dird_conf.h | 2 + bacula/src/dird/fd_cmds.c | 8 +- bacula/src/dird/getmsg.c | 3 +- bacula/src/dird/inc_conf.c | 23 +- bacula/src/dird/job.c | 12 +- bacula/src/dird/next_vol.c | 40 +- bacula/src/dird/protos.h | 3 +- bacula/src/dird/restore.c | 1 + bacula/src/dird/sql_cmds.c | 15 +- bacula/src/dird/ua_cmds.c | 87 +- bacula/src/dird/ua_label.c | 11 +- bacula/src/dird/ua_output.c | 99 +- bacula/src/dird/ua_prune.c | 6 +- bacula/src/dird/ua_restore.c | 129 +- bacula/src/dird/ua_run.c | 110 +- bacula/src/dird/ua_select.c | 8 +- bacula/src/dird/ua_status.c | 114 +- bacula/src/dird/ua_tree.c | 30 +- bacula/src/dird/verify.c | 103 +- bacula/src/filed/.cvsignore | 1 + bacula/src/filed/job.c | 24 +- bacula/src/filed/restore.c | 59 +- bacula/src/filed/verify.c | 11 +- bacula/src/filed/win32/bin/README.txt | 5 +- bacula/src/findlib/attribs.c | 3 + bacula/src/findlib/bfile.c | 9 +- bacula/src/findlib/create_file.c | 9 + bacula/src/gnome2-console/.cvsignore | 1 + bacula/src/gnome2-console/Makefile.in | 125 + bacula/src/gnome2-console/authenticate.c | 82 + bacula/src/gnome2-console/callbacks.c | 504 +++ bacula/src/gnome2-console/callbacks.h | 240 ++ bacula/src/gnome2-console/console.c | 607 ++++ bacula/src/gnome2-console/console.h | 61 + bacula/src/gnome2-console/console_conf.c | 268 ++ bacula/src/gnome2-console/console_conf.h | 60 + .../src/gnome2-console/gnome-console.conf.in | 15 + bacula/src/gnome2-console/interface.c | 1464 ++++++++ bacula/src/gnome2-console/interface.h | 11 + bacula/src/gnome2-console/support.c | 115 + bacula/src/gnome2-console/support.h | 37 + .../gnome2-console/test-gnome-console.conf | 10 + bacula/src/jcr.h | 4 +- bacula/src/lib/bpipe.c | 3 + bacula/src/lib/cram-md5.c | 1 + bacula/src/lib/daemon.c | 11 +- bacula/src/lib/message.c | 19 +- bacula/src/lib/parse_conf.c | 5 +- bacula/src/lib/tree.c | 74 +- bacula/src/lib/tree.h | 26 +- bacula/src/lib/util.c | 85 +- bacula/src/lib/var.c | 10 +- bacula/src/stored/.cvsignore | 1 + bacula/src/stored/acquire.c | 12 +- bacula/src/stored/bcopy.c | 4 +- bacula/src/stored/bextract.c | 6 +- bacula/src/stored/block.c | 54 +- bacula/src/stored/block.h | 2 +- bacula/src/stored/bscan.c | 16 +- bacula/src/stored/btape.c | 34 +- bacula/src/stored/dev.c | 13 +- bacula/src/stored/dircmd.c | 8 +- bacula/src/stored/fd_cmds.c | 8 +- bacula/src/stored/job.c | 2 +- bacula/src/stored/match_bsr.c | 85 +- bacula/src/stored/mount.c | 8 +- bacula/src/stored/parse_bsr.c | 3 + bacula/src/stored/protos.h | 3 +- bacula/src/stored/read_record.c | 167 +- bacula/src/stored/record.h | 2 + bacula/src/tools/testls.c | 48 +- bacula/src/version.h | 6 +- regress/.cvsignore | 7 - regress/README | 85 - regress/all-non-root-tape-tests | 13 - regress/all-non-root-tests | 28 - regress/all-root-tests | 9 - regress/all-tape-and-file-tests | 30 - regress/all-tests | 8 - regress/scripts/.cvsignore | 12 - regress/scripts/bacula-dir-tape.conf.in | 132 - regress/scripts/bacula-sd-tape.conf.in | 54 - regress/scripts/bacula-sd.conf.in | 74 - regress/scripts/cleanup | 9 - regress/scripts/cleanup-tape.in | 21 - regress/scripts/copy-confs | 5 - regress/scripts/copy-tape-confs | 5 - regress/scripts/copy-test-confs | 5 - regress/scripts/copy-testa-confs | 5 - regress/scripts/do_sed | 41 - regress/scripts/exclude-dev-test | 5 - regress/scripts/exclude-etc-test | 1 - regress/scripts/exclude-lib-test | 5 - regress/scripts/regress-config | 20 - regress/scripts/setup | 47 - regress/scripts/test-bacula-dir.conf.in | 298 -- regress/scripts/test-bacula-fd.conf.in | 33 - regress/scripts/test-bacula-sd.conf.in | 106 - regress/scripts/test-console.conf.in | 10 - regress/scripts/testa-bacula-dir.conf.in | 149 - regress/tests/backup-bacula-tape | 56 - regress/tests/backup-bacula-test | 55 - regress/tests/bextract-test | 59 - regress/tests/bscan-test | 83 - regress/tests/bsr-opt-test | 68 - regress/tests/compressed-test | 60 - regress/tests/concurrent-jobs-test | 77 - regress/tests/dev-test-root | 67 - regress/tests/etc-test-root | 67 - regress/tests/four-concurrent-jobs-test | 80 - regress/tests/lib-test-root | 67 - regress/tests/recycle-test | 89 - regress/tests/restore-by-file-test | 67 - regress/tests/six-vol-test | 66 - regress/tests/small-file-size-tape | 60 - regress/tests/span-vol-test | 65 - regress/tests/sparse-compressed-test | 56 - regress/tests/sparse-test | 56 - regress/tests/test0 | 3 - regress/tests/two-jobs-test | 81 - regress/tests/two-vol-test | 61 - regress/tests/two-volume-tape | 70 - regress/tests/verify-vol-test | 55 - regress/tests/weird-files-test | 68 - regress/tests/weird-files2-test | 84 - regress/weird-files.tar.gz | Bin 1510 -> 0 bytes 166 files changed, 8768 insertions(+), 3645 deletions(-) create mode 100644 bacula/platforms/freebsd/pthreads-fix.txt create mode 100755 bacula/scripts/set-gnome1.4 create mode 100755 bacula/scripts/set-gnome2 create mode 100644 bacula/src/cats/make_catalog_backup.in.patch create mode 100644 bacula/src/console2.glade create mode 100644 bacula/src/console2.gladep create mode 100644 bacula/src/gnome2-console/Makefile.in create mode 100644 bacula/src/gnome2-console/authenticate.c create mode 100644 bacula/src/gnome2-console/callbacks.c create mode 100644 bacula/src/gnome2-console/callbacks.h create mode 100644 bacula/src/gnome2-console/console.c create mode 100644 bacula/src/gnome2-console/console.h create mode 100644 bacula/src/gnome2-console/console_conf.c create mode 100644 bacula/src/gnome2-console/console_conf.h create mode 100644 bacula/src/gnome2-console/gnome-console.conf.in create mode 100644 bacula/src/gnome2-console/interface.c create mode 100644 bacula/src/gnome2-console/interface.h create mode 100644 bacula/src/gnome2-console/support.c create mode 100644 bacula/src/gnome2-console/support.h create mode 100644 bacula/src/gnome2-console/test-gnome-console.conf delete mode 100644 regress/.cvsignore delete mode 100644 regress/README delete mode 100755 regress/all-non-root-tape-tests delete mode 100755 regress/all-non-root-tests delete mode 100755 regress/all-root-tests delete mode 100755 regress/all-tape-and-file-tests delete mode 100755 regress/all-tests delete mode 100644 regress/scripts/.cvsignore delete mode 100644 regress/scripts/bacula-dir-tape.conf.in delete mode 100644 regress/scripts/bacula-sd-tape.conf.in delete mode 100644 regress/scripts/bacula-sd.conf.in delete mode 100755 regress/scripts/cleanup delete mode 100755 regress/scripts/cleanup-tape.in delete mode 100755 regress/scripts/copy-confs delete mode 100755 regress/scripts/copy-tape-confs delete mode 100755 regress/scripts/copy-test-confs delete mode 100755 regress/scripts/copy-testa-confs delete mode 100755 regress/scripts/do_sed delete mode 100644 regress/scripts/exclude-dev-test delete mode 100644 regress/scripts/exclude-etc-test delete mode 100644 regress/scripts/exclude-lib-test delete mode 100755 regress/scripts/regress-config delete mode 100755 regress/scripts/setup delete mode 100644 regress/scripts/test-bacula-dir.conf.in delete mode 100644 regress/scripts/test-bacula-fd.conf.in delete mode 100644 regress/scripts/test-bacula-sd.conf.in delete mode 100644 regress/scripts/test-console.conf.in delete mode 100644 regress/scripts/testa-bacula-dir.conf.in delete mode 100755 regress/tests/backup-bacula-tape delete mode 100755 regress/tests/backup-bacula-test delete mode 100755 regress/tests/bextract-test delete mode 100755 regress/tests/bscan-test delete mode 100755 regress/tests/bsr-opt-test delete mode 100755 regress/tests/compressed-test delete mode 100755 regress/tests/concurrent-jobs-test delete mode 100755 regress/tests/dev-test-root delete mode 100755 regress/tests/etc-test-root delete mode 100755 regress/tests/four-concurrent-jobs-test delete mode 100755 regress/tests/lib-test-root delete mode 100755 regress/tests/recycle-test delete mode 100755 regress/tests/restore-by-file-test delete mode 100755 regress/tests/six-vol-test delete mode 100755 regress/tests/small-file-size-tape delete mode 100755 regress/tests/span-vol-test delete mode 100755 regress/tests/sparse-compressed-test delete mode 100755 regress/tests/sparse-test delete mode 100755 regress/tests/test0 delete mode 100755 regress/tests/two-jobs-test delete mode 100755 regress/tests/two-vol-test delete mode 100755 regress/tests/two-volume-tape delete mode 100755 regress/tests/verify-vol-test delete mode 100755 regress/tests/weird-files-test delete mode 100755 regress/tests/weird-files2-test delete mode 100644 regress/weird-files.tar.gz diff --git a/bacula/.cvsignore b/bacula/.cvsignore index e87bcd24e3..62866bd26b 100644 --- a/bacula/.cvsignore +++ b/bacula/.cvsignore @@ -1,5 +1,9 @@ 1 2 +set-gnome2 +set-gnome1.4 +kerns-gprof-config +autom4te.cache Makefile bacula btraceback diff --git a/bacula/ChangeLog b/bacula/ChangeLog index bf5d6580de..16c0ee65f6 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,165 @@ +2003-11-03 Version 1.32d 02Nov03 Release +02Nov03 +- Mainly a bug fix release. +- Do a clean of both Gnome directories. +- Require that FileSet id match when finding an Incremental + previous job. This was already the case for a Full. +- Print message if no status returned from FD. +- Correct "Do not forget to mount the drive" message. Test was + backward. +- "status dir" stopped scanning the run records on the first + one that matched giving an incomplete listing. +- Edit commas in Bytes on "estimate" command output. + +2003-10-30 Version 1.32c 30Oct03 Release +29Oct03 +- Add %v to job edit codes. It edits in the VolumeName(s). +- Add code to ensure that fds 0,1, and 2 are defined by dup'ing them + to /dev/null if necessary. Mostly for Windows that does not have them. +- Error check dir_create_jobmedia_record() 2 places in acquire.c +26Oct03 +- More doc fixes. +- Make message buffer longer for a status message that was + truncated. +- Put termination on varargs calls in gnome2-console. +- Scroll only if text sent and not for status update. +- Add all possible Status codes the jobstatus_to_ascii() +25Oct03 +- Add new spec file and cats patch from Scott. +- Optimize tree.c a bit -- turn off debug code, keep node fname + length for fast rejection, add some statistics, allocate + in 100K and 1Meg chunks, use bool, uint16_t and uint8_t to + reduce node packet size. +24Oct03 +- Eliminate ua_retention.c that was not used. +- Improve error message when closing brace missing in conf file. +- More doc updates. +- Eliminate Don't forget to mount if it is a disk file. +- Fix Gnome2 scrolling and blank screen problems. +- Eliminate multiple JobIds in restore selection list. +- Fix non-portable varargs code in var.c +- Make doc fixes/changes suggested by Dan Languille +23Oct03 +- Document new features. +- Implement mod of Verify Job at the run prompt. +- Correct SQL table definitions so that MySQL and SQLite + have all the values in the same position. +- Correct a typo in configure.in when configuring GNOME. +- In doing a "status dir" make it loop over all the run + commands in the Schedule rather than doing on the first one. +- Close all unused file descriptors in bpipe.c otherwise if + a daemon is started, it will keep our TCP/IP port open. +22Oct03 +- Print block read error (checksum, I/O, BB01, ...) once then + the number found at the end of the reading. +- Implement RunAfterFailedJob +- Change db_find_job_start_time() to require a Full save before + running an Incremental or Differential job. +- Remove has_volume_expired from code that updates vol info +21Oct03 +- Implement "delete job" +20Oct03 +- More documentation, add Marc Brueckner's tips to manual. +- Tweak gnome2-console scroll window. +- Turn off some debug info. +18Oct03 +- Modify Verify to accept VerifyJob = xx, where the last backup job + of job xxx will be verified. +- Add changing the Pool name for a Volume to "update volume" +- Write most of the code for Verify Disk to Catalog. +- Recreate the src/gnome2-console directory. +- Change all the text handling code to the Gnome 2.0 way. +- Correct the way verify filenames are returned to the Director so + that directories are in canonical form (i.e. trailing /). +- Handle casting bug in glade-2 by sed'ing support.c in gnome2-console. + +2003-10-15 Version 1.32b 14Oct03 Release +14Oct03 +- Modify configure so that if threaded MySQL client library + is not present, Bacula will link with the non-threaded + version. +- Updates to the Web pages and to the manual. +- Remove trademark symbol from title. Phil pointed out that it + does not display correctly in a title. +11Oct03 +- Implement restore by file before date. +- Change restore arguments a bit so that you can feed it + multiple jobid= specifications or multiple file= specifications. +- Pass restore with run option on to run_cmd. +- Make run-cmd not prompt if it has a "run" on the command line. +10Oct03 +- When pruning, select only old orphanned jobs to delete so that + the current job is not pruned too. +09Oct03 +- Corrected return status for bsf_dev and bsr_dev in block.c and btape.c +- dev.c used incorrect ruturn status for bsf_dev in the BSF at EOM + code. This caused all appends on FreeBSD to fail. +- Turn on fast block rejection code. +08Oct03 +- Optimize file index searches by adding a count to the bootstrap. +- Write single files/blocks to bootstrap without the second part. +- Add current Volume status to the cannot use this Volume message. +- Zero the rx->bsr in ua_restore when freeing so it doesn't get + freed twice. +- Lots of testing on the restore +- I noticed that SD and FD bootstrap files were not always + deleted, so delete them as soon as possible. +- Restore by file (or by selecting files) created some + horrible looking bsr files that defeated the forward + spacing code, so fix write_findex to work right. +- Add zlib_strerror() routine in filed/restore in case + of zlib errors. +- In filed/restore.c make sure all error returns cleanup + and close the open file descriptor. +- Make sure to set *non* over filename in attr packet + after file is found, so error messages that print the + filename don't print an old, incorrect name. +- Allow bclose() to be called after closing the file. +- Fix a number of unclear help messages, ... reported by + Phil in btape. +- Retweak stored/read_record.c so that it does forward + spacing at the beginning of every tape, not just the + first one. +- Print repositioning message if verbose is set. + +2003-10-01 Version 1.32a 03Oct03 Release +04Oct03 +- Combine the code in ua_output and ua_status that searches + the run records. +03Oct03 +- Fixed "list nextvol" to search for the correct pool in the + Schedule Run records. +- Correct an error in is_block_zero. It found a false + match if the first 1016 bytes of a 32K buffer and + the last 248 bytes are zero. Broke the sparse option. +01Oct03 +- More documentation. +- Test if multiple mail addresses works. Yes. +- Add debug Jmsg() to trigger if the file I/O packet is + not closed in the FD, i.e file descriptor leaks. +- When error occurs reading label in mount.c, start from + the very top so that the retry count is in effect. +- Zap the mode in soft links in testls.c for regression + testing. + +2003-10-01 Version 1.32 30Sep03 Release +28Sep03 +- Enhance manual faq, regression ... +- Make FreeBSD read sizes always be a multiple of 512. Needed + to read raw disks. +- Make FreeBSD accept block AND character devices for raw + disk reads. On FreeBSD there are no block devices. +27Sep03 +- Fix printing of EndTime on job report after rescheduling. +- Fix jobq.c error returns to clean up before returning. +- Make Cleaning tape aware of "unlabeled" volumes. +- If a job is rescheduled, ensure that old job is + removed from SD's jcr queue -- i.e. it is still waiting + for FD connection. +- Test rescheduling code. +- Change ./configure to detect Cygwin enviornments. + 2003-09-26 Version 1.32 26Sep03 Beta - Add regression and GUI-interface chapters to the manual. - Fix "label" of a volume that is already in the catalog, diff --git a/bacula/CheckList b/bacula/CheckList index ff26ed374b..ccc71d7e79 100644 --- a/bacula/CheckList +++ b/bacula/CheckList @@ -8,7 +8,7 @@ - Update ChangeLog (add release date) - Do a cvs commit - Do a cvs -q export -D now -d bacula-1.nn bacula -- Build new bacula-1.nn to ensure everything is committed +- Run the regression tests on the new bacula - Write ReleaseNotes - If everything is good - cd bacula/k diff --git a/bacula/Makefile.in b/bacula/Makefile.in index 87c3a4da94..65b008f80c 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -149,6 +149,7 @@ distclean: @$(RMF) -r doc/techlogs/2002/CVS doc/techlogs/2001/CVS doc/techlogs/1.27/CVS @$(RMF) -r examples/CVS intl/CVS scripts/CVS @$(RMF) -r po/CVS src/immortal/CVS rescue/freebsd/CVS rescue/solaris/CVS + @$(RMF) -r CVS src/gnome-console/CVS src/tconsole/CVS distdirs: mkdir ../$(VERNAME); diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index 668426ebe3..a53eb61ac3 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,9 +1,49 @@ - Release Notes for Bacula 1.32 + Release Notes for Bacula 1.32d - Bacula code: Total files = 259 Total lines = 77,702 (*.h *.c *.in) + Bacula code: Total files = 259 Total lines = 78,087 (*.h *.c *.in) -Major Changes this Release: +Most Significant Changes since 1.32c +- Mainly a bug fix release. +- Do a clean of both Gnome directories. +- Require that FileSet id match when finding an Incremental + previous job. This was already the case for a Full. +- Print message if no status returned from FD. +- Correct "Do not forget to mount the drive" message. Test was + backward. +- "status dir" stopped scanning the run records on the first + one that matched giving an incomplete listing. +- Edit commas in Bytes on "estimate" command output. + +Most Significant Changes since 1.32b +- Implemented a RunAfterFailedJob record in the Job resource. +- Implemented "delete job" command in the Console. +- Gnome 2.0 console compiles and works. +- Implemented VerifyJob record in the Job resource + that tells Verify which job to verify (JobId not required) +- First cut Verify Disk to Catalog +- Fix "status dir" to examine all run commands in Schedule. +- Close unused file descriptors in bpipe.c +- There is now a patch for FreeBSD 4.8 pthreads that + fixes the problems of data loss at the end of a tape. + Please see: + /platforms/freebsd/pthreads-fix.txt +- Fixed (I think) the elusive Windows "packet too big" bug. +- Added %v to RunBefore/After editing codes. It edits in + a list of Volumes used for the job (not tested). + +Most Significant Changes since 1.32a: +- Improve forward space file/block during restore, many + optimizations. +- Fix a Bacula bug that did not allow appending to a tape + on FreeBSD systems. +- Fix pruning so that it will not prune the current job. +- Modify configure to use non-threaded MySQL client lib if + the threaded version is not present. +- Implement restore by file before date. +- When pruning don't prune the current job. + +Major Changes 1.32a Release: - Implemented forward space file/block whenever possible during restore. Restoring a small number of files is now much faster. @@ -22,9 +62,14 @@ Major Changes this Release: be used is also added to the "status dir" output. - Lots of fixes with variable expansion and counter variables - Implemented a new Include/Exclude syntax. +- While writing a tape, an end of file mark will be written + every 1Gb. This makes restores faster. If you want to + change this use "Maximum File Size" in the SD Device + resource. -Other Changes this Release: +Other Changes 1.32a Release: +- Fixed sparse file bug. - A warning message is sent when a job starts that will be blocked because the user did an "unmount". - Block checksum errors if any are printed in the job report. diff --git a/bacula/autoconf/acconfig.h b/bacula/autoconf/acconfig.h index a6fe066c74..e9cef42055 100644 --- a/bacula/autoconf/acconfig.h +++ b/bacula/autoconf/acconfig.h @@ -23,6 +23,9 @@ /* Define if you want to use MySQL */ #undef HAVE_MYSQL +/* Defined if MySQL thread safe library is present */ +#undef HAVE_THREAD_SAFE_MYSQL + /* Define if you want to use embedded MySQL */ #undef HAVE_EMBEDDED_MYSQL @@ -204,4 +207,3 @@ #undef HAVE_OLD_SOCKOPT #undef HAVE_BIGENDIAN - diff --git a/bacula/autoconf/aclocal.m4 b/bacula/autoconf/aclocal.m4 index 8f0aab87b2..1294fb1381 100644 --- a/bacula/autoconf/aclocal.m4 +++ b/bacula/autoconf/aclocal.m4 @@ -390,7 +390,12 @@ Which DBMS do you want to use (please select only one): fi fi SQL_INCLUDE=-I$MYSQL_INCDIR + if test -f $MYSQL_LIBDIR/libmysqlclient_r.a; then SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz" + AC_DEFINE(HAVE_THREAD_SAFE_MYSQL) + else + SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient -lz" + fi SQL_BINDIR=$MYSQL_BINDIR AC_DEFINE(HAVE_MYSQL) diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index 13c47a8636..db3f80dc3c 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -24,6 +24,9 @@ /* Define if you want to use MySQL */ #undef HAVE_MYSQL +/* Defined if MySQL thread safe library is present */ +#undef HAVE_THREAD_SAFE_MYSQL + /* Define if you want to use embedded MySQL */ #undef HAVE_EMBEDDED_MYSQL @@ -205,7 +208,6 @@ #undef HAVE_BIGENDIAN - /* Define to 1 if the `closedir' function returns void instead of `int'. */ #undef CLOSEDIR_VOID diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index f00fbe38a9..8eca027d8e 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -172,16 +172,16 @@ if test x$support_gnome = xyes; then pkg=$? if test $pkg = 0; then GNOME_INCLUDEDIR=`pkg-config --cflags-only-I libgnomeui-2.0` - GNOMEUI_LIBS=`pkg-config --libs-only-other libgnomeui-2.0` + GNOMEUI_LIBS=`pkg-config --libs-only-l libgnomeui-2.0` GNOME_LIBDIR=`pkg-config --libs libgnomeui-2.0` GNOME_LIBS=`pkg-config --libs-only-l libgnomeui-2.0` AC_SUBST(GNOME_INCLUDEDIR) AC_SUBST(GNOMEUI_LIBS) AC_SUBST(GNOME_LIBDIR) AC_SUBST(GNOME_LIBS) - GNOME_DIR=src/gnome-console + GNOME_DIR=src/gnome2-console else -dnl 1.4 stuff +dnl do 1.4 stuff GNOME_INIT GNOME_DIR=src/gnome-console fi @@ -505,7 +505,7 @@ AC_ARG_WITH(tcp-wrappers, [ if test "x$withval" != "xno" ; then saved_LIBS="$LIBS" - LIBS="$LIBS -lwrap -lnsl" + LIBS="$saved_LIBS -lwrap" AC_MSG_CHECKING(for libwrap) AC_TRY_LINK( [ #include @@ -517,8 +517,21 @@ AC_ARG_WITH(tcp-wrappers, AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LIBWRAP) TCPW_MSG="yes" - ], - [AC_MSG_ERROR([*** libwrap missing]) ] + ], [ + LIBS="$saved_LIBS -lwrap -lnsl" + AC_TRY_LINK( + [ #include + int deny_severity = 0; + int allow_severity = 0; + struct request_info *req; ], + [ hosts_access(req); ], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_LIBWRAP) + TCPW_MSG="yes" + ], + [AC_MSG_ERROR([*** libwrap missing]) ] ] + ) ) fi ] @@ -1420,6 +1433,8 @@ AC_OUTPUT([autoconf/Make.common \ src/console/console.conf \ src/gnome-console/Makefile \ src/gnome-console/gnome-console.conf \ + src/gnome2-console/Makefile \ + src/gnome2-console/gnome-console.conf \ src/tconsole/Makefile \ src/dird/Makefile \ src/dird/bacula-dir.conf \ diff --git a/bacula/configure b/bacula/configure index 89b636774c..0c00614963 100755 --- a/bacula/configure +++ b/bacula/configure @@ -4341,14 +4341,14 @@ if test x$support_gnome = xyes; then pkg=$? if test $pkg = 0; then GNOME_INCLUDEDIR=`pkg-config --cflags-only-I libgnomeui-2.0` - GNOMEUI_LIBS=`pkg-config --libs-only-other libgnomeui-2.0` + GNOMEUI_LIBS=`pkg-config --libs-only-l libgnomeui-2.0` GNOME_LIBDIR=`pkg-config --libs libgnomeui-2.0` GNOME_LIBS=`pkg-config --libs-only-l libgnomeui-2.0` - GNOME_DIR=src/gnome-console + GNOME_DIR=src/gnome2-console else @@ -6326,7 +6326,7 @@ if test "${with_tcp_wrappers+set}" = set; then if test "x$withval" != "xno" ; then saved_LIBS="$LIBS" - LIBS="$LIBS -lwrap -lnsl" + LIBS="$saved_LIBS -lwrap" echo "$as_me:$LINENO: checking for libwrap" >&5 echo $ECHO_N "checking for libwrap... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF @@ -6369,6 +6369,52 @@ _ACEOF TCPW_MSG="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + + LIBS="$saved_LIBS -lwrap -lnsl" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + #include + int deny_severity = 0; + int allow_severity = 0; + struct request_info *req; +int +main () +{ + hosts_access(req); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBWRAP 1 +_ACEOF + + TCPW_MSG="yes" + else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -6377,6 +6423,9 @@ sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me: error: *** libwrap missing" >&2;} { (exit 1); exit 1; }; } +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + fi rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext fi @@ -6685,7 +6734,15 @@ echo "$as_me: error: Invalid MySQL directory $withval - unable to find mysql.h u fi fi SQL_INCLUDE=-I$MYSQL_INCDIR - SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz" + if test -f $MYSQL_LIBDIR/libmysqlclient_r.a; then + SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient_r -lz" + cat >>confdefs.h <<\_ACEOF +#define HAVE_THREAD_SAFE_MYSQL 1 +_ACEOF + + else + SQL_LFLAGS="-L$MYSQL_LIBDIR -lmysqlclient -lz" + fi SQL_BINDIR=$MYSQL_BINDIR cat >>confdefs.h <<\_ACEOF @@ -17424,7 +17481,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/freebsd/Makefile rescue/solaris/Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/console scripts/gconsole scripts/bacula scripts/fd scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/mtx-changer doc/Makefile src/Makefile src/host.h src/console/Makefile src/console/console.conf src/gnome-console/Makefile src/gnome-console/gnome-console.conf src/tconsole/Makefile 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/alter_mysql_tables src/cats/make_mysql_tables src/cats/drop_mysql_tables src/cats/create_mysql_database src/cats/grant_mysql_privileges src/cats/alter_sqlite_tables src/cats/make_sqlite_tables src/cats/drop_sqlite_tables src/cats/create_sqlite_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/make_bdb_tables src/cats/drop_bdb_tables src/cats/make_bacula_tables src/cats/drop_bacula_tables src/findlib/Makefile src/tools/Makefile $PFILES" + ac_config_files="$ac_config_files autoconf/Make.common Makefile rescue/Makefile rescue/linux/Makefile rescue/freebsd/Makefile rescue/solaris/Makefile scripts/startmysql scripts/stopmysql scripts/btraceback scripts/startit scripts/stopit scripts/console scripts/gconsole scripts/bacula scripts/fd scripts/Makefile scripts/logrotate scripts/bacula.desktop.gnome1 scripts/bacula.desktop.gnome2 scripts/mtx-changer doc/Makefile src/Makefile src/host.h src/console/Makefile src/console/console.conf src/gnome-console/Makefile src/gnome-console/gnome-console.conf src/gnome2-console/Makefile src/gnome2-console/gnome-console.conf src/tconsole/Makefile 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/alter_mysql_tables src/cats/make_mysql_tables src/cats/drop_mysql_tables src/cats/create_mysql_database src/cats/grant_mysql_privileges src/cats/alter_sqlite_tables src/cats/make_sqlite_tables src/cats/drop_sqlite_tables src/cats/create_sqlite_database src/cats/sqlite src/cats/mysql src/cats/create_bdb_database src/cats/make_bdb_tables src/cats/drop_bdb_tables src/cats/make_bacula_tables src/cats/drop_bacula_tables src/findlib/Makefile src/tools/Makefile $PFILES" ac_config_commands="$ac_config_commands default" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -17980,6 +18037,8 @@ do "src/console/console.conf" ) CONFIG_FILES="$CONFIG_FILES src/console/console.conf" ;; "src/gnome-console/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/gnome-console/Makefile" ;; "src/gnome-console/gnome-console.conf" ) CONFIG_FILES="$CONFIG_FILES src/gnome-console/gnome-console.conf" ;; + "src/gnome2-console/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/gnome2-console/Makefile" ;; + "src/gnome2-console/gnome-console.conf" ) CONFIG_FILES="$CONFIG_FILES src/gnome2-console/gnome-console.conf" ;; "src/tconsole/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/tconsole/Makefile" ;; "src/dird/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/dird/Makefile" ;; "src/dird/bacula-dir.conf" ) CONFIG_FILES="$CONFIG_FILES src/dird/bacula-dir.conf" ;; diff --git a/bacula/kernstodo b/bacula/kernstodo index 3edeac324b..b0cf71d324 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 26 September 2003 + 30 September 2003 Documentation to do: (any release a little bit at a time) - Document running a test version. @@ -13,6 +13,7 @@ Documentation to do: (any release a little bit at a time) hours of operation. - Lookup HP cleaning recommendations. - Lookup HP tape replacement recommendations (see trouble shooting autochanger) +- Create a man page for each binary (Debian package requirement). Testing to do: (painful) - that ALL console command line options work and are always implemented @@ -21,28 +22,174 @@ Testing to do: (painful) - Test cancel at EOM. - Test not zeroing Autochanger slot when it is wrong. - Figure out how to use ssh or stunnel to protect Bacula communications. -- Test connect timeouts. -For 1.32 Testing/Documentation: -- Document new records in Director. SDAddress SDDeviceName, SDPassword. +For 1.33 Testing/Documentation: +- bextract is sending everything to the log file ****FIXME**** +- Document new alias records in Director. SDAddress SDDeviceName, SDPassword. FDPassword, FDAddress, DBAddress, DBPort, DBPassword. -- Document that it is safe to use the drive when the lights stop flashing. - Document new Include/Exclude ... -- Document all the status codes JobLevel, JobType, JobStatus. - Add test of exclusion, test multiple Include {} statements. - Add counter variable test. +- Document ln -sf /usr/lib/libncurses.so /usr/lib/libtermcap.so + and install the esound-dev  package for compiling Console on SuSE. +- Add an example of using a FIFO in dirdconf.wml +- Add an item to the FAQ about running jobs in different timezones. +- Add some examples of job editing codes. +- Add Dan's 31 Oct 2003 email on tcpwrappers to Tips. +- Add to supported autochangers + OS             : FreeBSD-4.9 + Auto-Changer    : QUALSTAR TLS-4210 +   Manufufactur  : Qualstar +   Tapes         : 12 (AIT1: 36GB, AIT2: 50GB all uncompressed) +   Drives        : 2xAIT2 (installed in the Qualstar: SONY SDX-500C AIT2) + -For 1.32: -- Add GUI interface to manual -- Document that Volume pruning can delete last Full backup and - hence you will not have a valid backup. -- Clarify the fact that having the Bacula cygwin1.dll loaded - is not the same as having cygwin installed. -- Fix sparse file handeling so that it always reads a multiple - of 512. Currently, it subtracts 8 bytes (for faddr). -- Separate Dir heartbeat in FD from the SD heartbeat. For 1.33 +- Estimate to Tibs never returns. +- Fix TimeZone problem! +- Recycling volume with a Slot requires an operator intervention: + rufus-dir: Start Backup JobId 18, Job=kernsave.2003-11-01_21.23.52 + rufus-dir: Pruned 1 Job on Volume Vol01 from catalog. + rufus-dir: There are no Jobs associated with Volume Vol01. Marking it purged. + rufus-dir: Recycled volume "Vol01" + rufus-sd: Please mount Volume "Vol01" on Storage Device "DDS-4" for Job kernsave.2003-11-01_21.23.52 + Use "mount" command to release Job. +- Think about how space could be freed up on a tape -- perhaps this + is a Merge or Compact feature that is needed. +- Modify FileSet, did not upgrade the current Increment job, but + waited for the next job to be upgraded. +- Take a careful look at SetACL http://setacl.sourceforge.net +- Implement a where command for the tree telling where a file + is located. +- Take a careful look at Level for the estimate command, maybe make + it a command line option. +- Optimize fsf not to read. +- Implement Dan's bacula script (email of 26 Oct). +- Implement autochange testing in btape. +- Add Volume name to "I cannot write on this volume because" +- Make restore job check if all the files are actually restored. +- Make tree walk routines like cd, ls, ... more user friendly + by handling spaces better. +- Write your PID file and chwon root:wheel before drop. +- Make sure there is no symlink in a file before creating a + file (attack). +- Look at mktemp or mkstemp(3). + mktemp and mkstemp create files with predictable names too. That's + not the vulnerability. The vulnerability is in creating files without + using the O_EXCL flag, which means "only create this file if it doesn't + exist, including if the file is a dangling symlink." + + It is *NOT* enough to do the equivalent of + + if doesn't exist $filename + then create $filename + + because between the test and the create another process could have + gotten the CPU and created the file. You must use atomic functions + (those that don't get interrupted by other processes) and O_EXCL is + the only way for this particular example. +- Keep last 5 or 10 completed jobs and show them in a similar + list. +- Make a Running Jobs: output similar to current Scheduled Jobs: +- Use ioctl() fsf if it exists. Figure out where we are from + the mt_status command. Use slow fsf only if other does + not work. +- Add flag to write only one EOF mark on the tape. +- Mount a tape that is not right for the job (wrong # files on tape) + Bacula asks for another tape, fix problems with first tape and + say "mount". All works OK, but status shows: + Device /dev/nst0 open but no Bacula volume is mounted. + Total Bytes=1,153,820,213 Blocks=17,888 Bytes/block=64,502 + Positioned at File=9 Block=3,951 + Full Backup job Rufus.2003-10-26_16.45.31 using Volume "DLT-24Oct03" on device /dev/nst0 + Files=21,003 Bytes=253,954,408 Bytes/sec=2,919,016 + FDReadSeqNo=192,134 in_msg=129830 out_msg=5 fd=7 +- Automatically create pools, but instead of looking for what + in in Job records, walk through the pool resources. +- Check and double check tree code, why does it take so long? +- Upgrade to cygwin 1.5 +- Fix time difference problem between Bacula and Client + so that everything is in GMT. +- Finish implementation of Verify=DiskToCatalog +- Change console to bconsole. +- Change smtp to bsmtp. +- Possibly up network buffers to 65K. +- Add device name to "Current Volume not acceptable because ..." +- Make sure that Bacula rechecks the tape after the 20 min wait. +- Set IO_NOWAIT on Bacula TCP/IP packets. +- Try doing a raw partition backup and restore by mounting a + Windows partition. +- Report CVS problems to SourceForge. +- Implement .consolerc for Console +- Is it really important to make Job name the same to find the + Full backup to avoid promoting an Incremental job? +- Start label, then run job when tape labeled, it should broadcast. +- Zap illegal characters in job name for mail files (e.g. /). +- From Lars Köllers: + Yes, it would allow to highly automatic the request for new tapes. If a + tape is empty, bacula reads the barcodes (native or simulated), and if + an unused tape is found, it runs the label command with all the + necessary parameters. + + By the way can bacula automatically "move" an empry/purged volume say + in the "short" pool to the "long" pool if this pool runs out of volume + space? +- Either restrict the characters in a name, or fix the problem + emailing with names containing / (smtp command line breaks). +- Eliminate orphaned jobs: dbcheck, normal pruning, delete job command. + Hm.  Well, there are the remaining orphaned job records: + + |   105 | Llioness Save  | 0000-00-00 00:00:00 | B    | D     |        0 |             0 | f         | + |   110 | Llioness Save  | 0000-00-00 00:00:00 | B    | I     |        0 |             0 | f         | + |   115 | Llioness Save  | 2003-09-10 02:22:03 | B    | I     |        0 |             0 | A         | + |   128 | Catalog Save   | 2003-09-11 03:53:32 | B    | I     |        0 |             0 | C         | + |   131 | Catalog Save   | 0000-00-00 00:00:00 | B    | I     |        0 |             0 | f         | + + As you can see, three of the five are failures.  I already deleted the + one restore and one other failure using the by-client option.  Deciding + what is an orphaned job is a tricky problem though, I agree.  All these + records have or had 0 files/ 0 bytes, except for the restore.  With no + files, of course, I don't know of the job ever actually becomes + associated with a Volume. + + (I'm not sure if this is documented anywhere -- what are the meanings of + all the possible JobStatus codes?) + + Looking at my database, it appears to me as though all the "orphaned" + jobs fit into one of two categories: + + 1)  The Job record has a StartTime but no EndTime, and the job is not +     currently running; + or + 2)  The Job record has an EndTime, indicating that it completed, but +     it has no associated JobMedia record. + + + This does suggest an approach.  If failed jobs (or jobs that, for some + other reason, write no files) are associated with a volume via a + JobMedia record, then they should be purged when the associated volume + is purged.  I see two ways to handle jobs that are NOT associated with a + specific volume: + + 1)  purge them automatically whenever any volume is manually purged; + or + 2)  add an option to the purge command to manually purge all jobs with +     no associated volume. + + I think Restore jobs also fall into category 2 above .... so one might + want to make that "The Job record has an EndTime,, but no associated + JobMedia record, and is not a Restore job." +- Implement RestoreJobRetention? Maybe better "JobRetention" in a Job, + which would take precidence over the Catalog "JobRetention". +- Implement Label Format in Add and Label console commands. +- make "btape /tmp" work. +- Make sure a rescheduled job is properly reported by status. +- Walk through the Pool records rather than the Job records + in dird.c to create/update pools. +- What to do about "list files job=xxx". +- Implement scan: for every slot it finds, zero the slot of + Volume other volume having that slot. - When job rescheduled, status gives is waiting for Client Rufus to connect to Storage File. Dir needs to inform SD that job is rescheduled. @@ -58,7 +205,6 @@ For 1.33 rather than lowest MediaId. - Available volumes for autochangers (see patrick@baanboard.com 3 Sep 03 and 4 Sep) scan slots. -- Upgrade to cygwin 1.5 - Get MySQL 3.23.58 - Get and test MySQL 4.0 - Do a complete audit of all pthreads_mutex, cond, ... to ensure that @@ -71,7 +217,7 @@ For 1.33 - Use system dependent calls to get more precise info on tape errors. - Add heartbeat from FD to SD if hb interval expires. - Suppress read error on blank tape when doing a label. -- Can we dynamically change FileSets. +- Can we dynamically change FileSets? - If pool specified to label command and Label Format is specified, automatically generate the Volume name. - Take a careful look a the Basic recycling algorithm. When Bacula @@ -119,7 +265,6 @@ For 1.33 - Make things like list where a file is saved case independent for Windows. - Edit the Client/Storage name into authentication failure messages. -- Implement job in VerifyToCatalog - Implement migrate - Implement a PostgreSQL driver. - Bacula needs to propagate SD errors. @@ -131,7 +276,8 @@ For 1.33 > > prod4-sd: End of medium on Volume "REU007" Bytes=16,303,521,933 - Use autochanger to handle multiple devices. -- Fix packet too big problem. +- Fix packet too big problem. This is most likely a Windows TCP stack + problem. - Add SuSE install doc to list. - Check and rechedk "Invalid block number" - Make bextract release the drive properly between tapes @@ -474,62 +620,24 @@ Projects: last update 8 May 2003 Item 1: Multiple simultaneous Jobs. (done) -Done -- Restore part needs better implementation to work correctly - Also, it needs considerable testing - - What: Permit multiple simultaneous jobs in Bacula. - - Why: An enterprise level solution needs to go fast without the - need for the system administrator to carefully tweak - timing. Based on the benchmarks, during a full - backup, NetWorker typically hit 10 times the bandwidth to - the tape compared to Bacula--largely. This is probably due to - running parallel jobs and multi-threaded filling of buffers - and writing them to tape. This should also make things work - better when you have a mix of fast and slow machines backing - up at the same time. - - Notes: Bacula was designed to run multiple simultaneous jobs. Thus - implementing this is a matter of some small cleanups and - careful testing. - - -Item 2: Make the Storage daemon use intermediate file storage to buffer data. -Deferred -- not necessary yet -- possibly implement with Migration. - - What: If data is coming into the SD too fast, buffer it to - disk if the user has configured this option. - - Why: This would be nice, especially if it more or less falls out - when implementing (1) above. If not, it probably should not - be given a high priority because fundamentally the backup time - is limited by the tape bandwidth. Even though you may finish a - client job quicker by spilling to disk, you still have to - eventually get it onto tape. If intermediate disk buffering - allows us to improve write bandwidth to tape, it may make - sense. - - Notes: Whether or not this is implemented will depend upon performance - testing after item 1 is implemented. - +Done Item 3: Write the bscan program -- also write a bcopy program. Done - What: Write a program that reads a Bacula tape and puts all the - appropriate data into the catalog. This allows recovery - from a tape that is no longer in the database, or it allows - re-creation of a database if lost. +Item 5: Implement Label templates +Done - Why: This is a fundamental robustness and disaster recovery tool - which will increase the comfort level of a sysadmin - considering adopting Bacula. +Item 6: Write a regression script. +Done -- Continue to expand its testing. - Notes: A skeleton of this program already exists, but much work - needs to be done. Implementing this will also make apparent - any deficiencies in the current Bacula tape format. +Item 9: Add SSL to daemon communications. +For now, implement with stunnel +Item 10: Define definitive tape format. +Done (version 1.27) +--- Not completed Item 4: Implement Base jobs. What: A base job is sort of like a Full save except that you @@ -549,37 +657,23 @@ Item 4: Implement Base jobs. the e. DIR must send FD a list of files/attribs, and the FD must search the list and compare it for each file to be saved. +Item 2: Make the Storage daemon use intermediate file storage to buffer data. +Deferred -- not necessary yet -- possibly implement with Migration. -Item 5: Implement Label templates -Done - - What: This is a mechanism whereby Bacula can automatically create - a tape label for new tapes according to a detailed specification - provided by the user. - - Why: It is a major convenience item for folks who use automated label - creation. - - Notes: Bacula already has a working form of automatic tape label - creation, but it is very crude. The design for the complete - tape labeling project is already documented in the manual. - - -Item 6: Write a regression script. -Done -- Continue to expand its testing. - - What: This is an automatic script that runs and tests as many features - of Bacula as possible. The output is compared to previous - versions of Bacula and any differences are reported. - - Why: This is an enormous help in preventing introduction of new - errors in parts of the program that already work correctly. + What: If data is coming into the SD too fast, buffer it to + disk if the user has configured this option. - Notes: This probably should be ranked higher, it's something the typical - user doesn't see. Depending on how it's implemented, it may - make sense to defer it until the archival tape format and - user interface mature. + Why: This would be nice, especially if it more or less falls out + when implementing (1) above. If not, it probably should not + be given a high priority because fundamentally the backup time + is limited by the tape bandwidth. Even though you may finish a + client job quicker by spilling to disk, you still have to + eventually get it onto tape. If intermediate disk buffering + allows us to improve write bandwidth to tape, it may make + sense. + Notes: Whether or not this is implemented will depend upon performance + testing after item 1 is implemented. Item 7: GUI for interactive restore Item 8: GUI for interactive backup @@ -603,34 +697,6 @@ Item 8: GUI for interactive backup own files will in most cases be on a Windows machine running Exploder. - -Item 9: Add SSL to daemon communications. - - What: This provides for secure communications between the daemons. - - Why: This would allow doing backup across the Internet without - privacy concerns (or with much less concern). - - Notes: The vast majority of near term potential users will be backing up - a single site over a LAN and, correctly or not, they probably - won't be concerned with security, at least not enough to go to - the trouble to set up keys, etc. to screw things down. We suspect - that many users genuinely interested in multi-site backup - already run some form of VPN software in their internetwork - connections, and are willing to delegate security to that layer. - - -Item 10: Define definitive tape format. -Done (version 1.27) - - What: Define that definitive tape format that will not change - for the next millennium. - - Why: Stability, security. - - Notes: See notes for item 11 below. - - Item 11: New daemon communication protocol. What: The current daemon to daemon protocol is basically an ASCII @@ -884,76 +950,8 @@ Need: Done: (see kernsdone for more) -- Implement new alist in FileSet scanning. -- bls should continue reading even if it finds Win32 data on the tape. - The error should be Warning rather the Error. -- Add user configurable timeout for connecting to SD. -- Unsaved Flag in Job record (use JobMissingFiles). -- Base Flag in Job record. -- Configure mtx-changer to have correct path to mtx. -- Add all command line arguments to "update", e.g. slot=nn volStatus=append, ... -- Make some way so that if a machine is skipped because it is not up - that Bacula will continue retrying for a specified period of time -- - periodically. -- Implement all command line args on run. -- Implement command line "restore" args. -- Implement "restore current select=no" -- Restore file modified before date -- Restore -- do nothing but show what would happen -- Add estimate to Console commands -- Use read_record.c in SD code. -- Fix read_record to handle multiple sessions. -- Tip from Steve Allam - mt -f /dev/nst0 defblksize 0 -- Document "status" in the console. -- Document driving console from shell script. -- Write JobMedia records with max file size is reached on tape. -- Handle the case of multiple JobMedia records pending (i.e. the - thread is slow and multiple situations requiring a JobMedia - record occur). -- Do performance analysis on the restore tree routines. -- Fix maximum file size (block.c) to generate JobMedia records. -- Make the default file size 1GB on the tape. -- Implement forward spacing between files. -- Add Machine type (Linux/Windows) to Status report for daemons. - Look at src/host.h -- Use repositioning at the beginning of the tape. -- Do full check the command line args in update (e.g. VolStatus ...). -- Specify list of files to restore -- Implement ClientRunBeforeJob and ClientRunAfterJob. -- Make | and < work on FD side. -- Check to see if "blocked" is set during restore. -- Figure out what is interrupting sql command in console. -- Make new job print warning User Unmounted Tape. -- Test recycling and purging (code changed in db_find_next_volume and - in recycle.c). -- Document SDConnectTimeout (in FD). -- Add restore by filename test. -- Document restore by files. -- Make variable expansion work correctly. -- Implement List Volume Job=xxx or List scheduled volumes or Status Director -- Copy static programs into install directory. -- Think about changing Storage resource Device record to be - SDDeviceName. -- Add RunBeforeJob and RunAfterJob to the Client program. -- Need return status on read_cb() from read_records(). Need multiple - records -- one per Job, maybe a JCR or some other structure with - a block and a record. -- LabelFormat on tape volume apparently creates the db record but - never actually labels the volume. -- Recycling a volume when two jobs are using it is going to break. Fixed. -- Document list nextvol and new format status dir. -- Client files in Win32 with Unix eol conventions doesn't work. -- Either fix or document that fill command in btape can be - compressed enormously by the hardware - a 36GB tape wrote 750GB! -- Add multiple character duration qualifiers. -- Require some modifer. -- Restrict characters permitted in a Resource name, and don't permit - duplicate names. -- Figure out some way to ignore or get past checksum errors in - reading. -- The SD spooling file gets created even if it is not used. -- Look at Cleaning tape in ua_label.c for media create/update -- Add regression testing to the manual -- End time: in job output of rescheduled job is time of first run. -- Document list nextvol and status output. + +=== after 1.32c +- John's Full save failed with 1.32c FD and 1.31 Dir no FD status, + and no error message. + diff --git a/bacula/platforms/freebsd/pthreads-fix.txt b/bacula/platforms/freebsd/pthreads-fix.txt new file mode 100644 index 0000000000..d4fa099c38 --- /dev/null +++ b/bacula/platforms/freebsd/pthreads-fix.txt @@ -0,0 +1,193 @@ +From bacula-users-admin@lists.sourceforge.net Mon Oct 20 23:44:13 2003 +Return-Path: +Received: from sc8-sf-list2.sourceforge.net (lists.sourceforge.net + [66.35.250.206]) by matou.sibbald.com (8.11.6/8.11.6) with ESMTP id + h9KLiDY13657 for ; Mon, 20 Oct 2003 23:44:13 +0200 +Received: from sc8-sf-list1-b.sourceforge.net ([10.3.1.13] + helo=sc8-sf-list1.sourceforge.net) by sc8-sf-list2.sourceforge.net with + esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 1ABhpS-00013k-00; Mon, 20 Oct 2003 + 14:44:42 -0700 +Received: from sc8-sf-mx1-b.sourceforge.net ([10.3.1.11] + helo=sc8-sf-mx1.sourceforge.net) by sc8-sf-list1.sourceforge.net with esmtp + (Cipher TLSv1:DES-CBC3-SHA:168) (Exim 3.31-VA-mm2 #1 (Debian)) id + 1ABhnp-0007qu-00 for ; Mon, 20 Oct 2003 + 14:43:01 -0700 +Received: from bast.unixathome.org ([66.11.174.150] ident=postfix) by + sc8-sf-mx1.sourceforge.net with esmtp (Exim 4.22) id 1ABfiR-0002Iv-Q8 for + bacula-users@lists.sourceforge.net; Mon, 20 Oct 2003 12:29:19 -0700 +Received: from wocker (wocker.unixathome.org [192.168.0.99]) by + bast.unixathome.org (Postfix) with ESMTP id 258913F53 for + ; Mon, 20 Oct 2003 15:25:33 -0400 (EDT) +From: "Dan Langille" +To: bacula-users@lists.sourceforge.net +MIME-Version: 1.0 +Message-ID: <3F93FF4E.14552.13ACB682@localhost> +Priority: normal +X-mailer: Pegasus Mail for Windows (v4.02a) +Content-type: text/plain; charset=US-ASCII +Content-description: Mail message body +X-Spam-Score: 0.0 (/) +X-Spam-Report: 0.0/5.0 Spam Filtering performed by sourceforge.net. See + http://spamassassin.org/tag/ for more details. Report problems to + https://sf.net/tracker/?func=add&group_id=1&atid=200001 +Subject: [Bacula-users] FreeBSD - large backups to tape +Sender: bacula-users-admin@lists.sourceforge.net +Errors-To: bacula-users-admin@lists.sourceforge.net +X-BeenThere: bacula-users@lists.sourceforge.net +X-Mailman-Version: 2.0.9-sf.net +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: + , + +List-Id: Bacula user's email list for support and discussions + +List-Unsubscribe: + , + +List-Archive: + +Date: Mon, 20 Oct 2003 15:29:18 -0400 +Content-Transfer-Encoding: 8bit + +Kern and I have been working on a FreeBSD/Bacula problem. +He's asked me to post this to the list. The problem was within the +FreeBSD pthreads library. A solution has been found. + +PROBLEM DESCRIPTION: + +The FreeBSD pthreads library does not properly handle End Of Tape. +This problem will be fixed in FreeBSD 4.9. The bug results in more +data being written to the tape than could be read. Any backup which +involved more than one tape would be incomplete. + +DEMONSTRATION: + +To demonstrate the problem, tapetest.c can be obtained from +http://www.freebsd.org/cgi/query-pr.cgi?pr=56274 + +This tests without pthreads: + + * If you build this program with: + * + * c++ -g -O2 -Wall -c tapetest.c + * c++ -g -O2 -Wall tapetest.o -o tapetest + * + * Procedure for testing tape + * ./tapetest /dev/your-tape-device + * rewind + * rawfill + * rewind + * scan + * + * The output will be something like: + * + * ======== + * Rewound /dev/nsa0 + * *Begin writing blocks of 64512 bytes. + * ++++++++++++++++++++ ... + * Write failed. Last block written=17294. stat=0 ERR=Unknown +error: 0 + * weof_dev + * Wrote EOF to /dev/nsa0 + * *Rewound /dev/nsa0 + * *Starting scan at file 0 + * 17294 blocks of 64512 bytes in file 0 + * End of File mark. + * End of File mark. + * End of tape + * Total files=1, blocks=17294, bytes = 1115670528 + * ======== + * + * which is correct. Notice that the return status is + * 0, while in the example below, which fails, the return + * status is -1. + +This tests with pthreads: + + * If you build this program with: + * + * c++ -g -O2 -Wall -pthread -c tapetest.c + * c++ -g -O2 -Wall -pthread tapetest.o -o tapetest + * Note, we simply added -pthread compared to the + * previous example. + * + * Procedure for testing tape + * ./tapetest /dev/your-tape-device + * rewind + * rawfill + * rewind + * scan + * + * The output will be something like: + * + * ======== + * Rewound /dev/nsa0 + * *Begin writing blocks of 64512 bytes. + * +++++++++++++++++++++++++++++ ... + * Write failed. Last block written=17926. stat=-1 ERR=No space left on device + * weof_dev + * Wrote EOF to /dev/nsa0 + * *Rewound /dev/nsa0 + * *Starting scan at file 0 + * 17913 blocks of 64512 bytes in file 0 + * End of File mark. + * End of File mark. + * End of tape + * Total files=1, blocks=17913, bytes = 1155603456 + * ======== + * + * which is incroorect because it wrote 17,926 blocks but read + * back only 17,913 blocks + +If you get the same number of blocks written and read WHEN using +pthreads, then you've been correctly patched. + +SOLUTION: + +For FreeBSD prior to 4.9, you have two choices to ensure proper +backups. These instructions assume you are familiar with patching +FreeBSD and already have the FreeBSD source code installed on your +machine. + +1 - cvsup and build your system to FreeBSD 4.8-STABLE + +2 - Apply this patch. + +http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc_r/uthread/uthread_write.c.diff?r1=1.16.2.6&r2=1.16.2.7 + +To apply the patch, follow these instructions as root. + +fetch -o pthread.diff http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc_r/uthread/uthread_write.c.diff?r1=1.16.2.6\&r2=1.16.2.7 + +cd /usr/src/lib/libc_r/uthread/ +patch < /path/to/pthread.diff +cd .. +make all install + +I recommend restarting Bacula. + + +TESTING: + +I suggest running tapetest on your patched system and then +conducting a backup which spans two tapes. Restore the data +and compare to the original. If not identical, please let us know. + +Thanks + +-- +Dan Langille : http://www.langille.org/ + + + +------------------------------------------------------- +This SF.net email is sponsored by OSDN developer relations +Here's your chance to show off your extensive product knowledge +We want to know what you know. Tell us and you have a chance to win $100 +http://www.zoomerang.com/survey.zgi?HRPT1X3RYQNC5V4MLNSV3E54 +_______________________________________________ +Bacula-users mailing list +Bacula-users@lists.sourceforge.net +https://lists.sourceforge.net/lists/listinfo/bacula-users diff --git a/bacula/platforms/redhat/bacula.spec.in b/bacula/platforms/redhat/bacula.spec.in index f69b37527f..c49d55c777 100644 --- a/bacula/platforms/redhat/bacula.spec.in +++ b/bacula/platforms/redhat/bacula.spec.in @@ -38,7 +38,8 @@ Version: @VERSION@ Release: 1 Group: System Environment/Daemons Copyright: GPL v2 -Source: http://www.prdownloads.sourceforge.net/bacula/%{name}-%{version}.tar.gz +Source0:http://www.prdownloads.sourceforge.net/bacula/%{name}-%{version}.tar.gz +Source1:http://www.prdownloads.sourceforge.net/bacula/depkgs-24Jul03.tar.gz BuildRoot: %{_tmppath}/%{name}-root URL: http://www.bacula.org/ Vendor: The Bacula Team @@ -116,7 +117,7 @@ This is the File daemon (Client) only package. %prep -%setup +%setup -b 1 %build @@ -131,6 +132,9 @@ cd ${cwd} # patch the make_sqlite_tables script for installation bindir patch src/cats/make_sqlite_tables.in src/cats/make_sqlite_tables.in.patch +# patch the make_catalog_backup script for installation bindir +patch src/cats/make_catalog_backup.in src/cats/make_catalog_backup.in.patch + %configure \ --prefix=/usr \ --sbindir=/usr/sbin \ @@ -369,6 +373,9 @@ chmod 0755 /usr/sbin/gnome-console /sbin/chkconfig --del bacula-fd %changelog +* Fri Oct 24 2003 D. Scott Barninger +- Added separate Source declaration for depkgs +- added patch for make_catalog_backup script * Mon May 11 2003 D. Scott Barninger - Misc changes to mysql/sqlite build and rh7/8 menu differences - Added rh_version to sub-package names diff --git a/bacula/scripts/set-gnome1.4 b/bacula/scripts/set-gnome1.4 new file mode 100755 index 0000000000..d76e5a2a76 --- /dev/null +++ b/bacula/scripts/set-gnome1.4 @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Simple script to change the package configuration to +# Gnome 1.4 level. +# +MUID=`/usr/bin/id -u` +if [ $MUID != 0 ] ; then + echo " " + echo "You must be root to run this script." + echo " " + exit 1 +fi +cd /usr/lib/pkgconfig +if test -f libgnomeui-2.0.pc.orig ; then + rm -f libgnomeui-2.0.pc +else + mv libgnomeui-2.0.pc libgnomeui-2.0.pc.orig +fi diff --git a/bacula/scripts/set-gnome2 b/bacula/scripts/set-gnome2 new file mode 100755 index 0000000000..414499dd7f --- /dev/null +++ b/bacula/scripts/set-gnome2 @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Simple script to set the Gnome package level +# to Gnome 2.0 +# +MUID=`/usr/bin/id -u` +if [ $MUID != 0 ] ; then + echo " " + echo "You must be root to run this script." + echo " " + exit 1 +fi +cd /usr/lib/pkgconfig +if test -f libgnomeui-2.0.pc.orig ; then + cp -fp libgnomeui-2.0.pc.orig libgnomeui-2.0.pc +fi diff --git a/bacula/src/.cvsignore b/bacula/src/.cvsignore index 018076a9be..a9c61f762d 100644 --- a/bacula/src/.cvsignore +++ b/bacula/src/.cvsignore @@ -5,3 +5,4 @@ Makefile config.h testprogs host.h +perlgui diff --git a/bacula/src/Makefile.in b/bacula/src/Makefile.in index 1f32ee5812..8b67e61486 100644 --- a/bacula/src/Makefile.in +++ b/bacula/src/Makefile.in @@ -40,6 +40,8 @@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status clean: @$(RMF) core core.* a.out *.o *.bak *~ *.intpro *.extpro 1 2 3 + (cd gnome-console; $(MAKE) clean) + (cd gnome2-console; $(MAKE) clean) realclean: clean @$(RMF) tags diff --git a/bacula/src/cats/bdb_find.c b/bacula/src/cats/bdb_find.c index 8526946474..5b9a2581a0 100644 --- a/bacula/src/cats/bdb_find.c +++ b/bacula/src/cats/bdb_find.c @@ -176,7 +176,9 @@ int db_find_next_volume(JCR *jcr, B_DB *mdb, int item, MEDIA_DBR *mr) return stat; } -int db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr) { return 0; } +int +db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr) +{ return 0; } #endif /* HAVE_BACULA_DB */ diff --git a/bacula/src/cats/bdb_get.c b/bacula/src/cats/bdb_get.c index e152c227ba..cbabc7a3aa 100644 --- a/bacula/src/cats/bdb_get.c +++ b/bacula/src/cats/bdb_get.c @@ -492,7 +492,7 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) -int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fdbr) +int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr) { return 0; } int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, uint32_t JobId, VOL_PARAMS **VolParams) diff --git a/bacula/src/cats/make_catalog_backup.in b/bacula/src/cats/make_catalog_backup.in index 94115576b2..fe9c774fc3 100755 --- a/bacula/src/cats/make_catalog_backup.in +++ b/bacula/src/cats/make_catalog_backup.in @@ -6,9 +6,9 @@ cd @working_dir@ rm -f bacula.sql if test xsqlite = x@DB_NAME@ ; then -echo ".dump" | @SQL_BINDIR@/sqlite bacula.db >bacula.sql + echo ".dump" | @SQL_BINDIR@/sqlite bacula.db >bacula.sql else -@SQL_BINDIR@/mysqldump $* -f --opt bacula >bacula.sql + @SQL_BINDIR@/mysqldump $* -f --opt bacula >bacula.sql fi # # To read back a MySQL database use: diff --git a/bacula/src/cats/make_catalog_backup.in.patch b/bacula/src/cats/make_catalog_backup.in.patch new file mode 100644 index 0000000000..14d3adc16f --- /dev/null +++ b/bacula/src/cats/make_catalog_backup.in.patch @@ -0,0 +1,16 @@ +9c9 +< echo ".dump" | @SQL_BINDIR@/sqlite bacula.db >bacula.sql +--- +> echo ".dump" | /usr/lib/sqlite/sqlite bacula.db >bacula.sql +11c11 +< @SQL_BINDIR@/mysqldump $* -f --opt bacula >bacula.sql +--- +> /usr/bin/mysqldump $* -f --opt bacula >bacula.sql +16c16 +< # rm -f @SQL_BINDIR@/../var/bacula/* +--- +> # rm -f /var/lib/mysql/bacula/* +22c22 +< # sqlite bacula.db # /usr/lib/sqlite/sqlite bacula.db connected = TRUE; V(mutex); @@ -188,7 +190,9 @@ db_close_database(JCR *jcr, B_DB *mdb) { P(mutex); mdb->ref_count--; +#ifdef HAVE_TREAD_SAFE_MYSQL my_thread_end(); +#endif if (mdb->ref_count == 0) { qdchain(&mdb->bq); if (mdb->connected && mdb->db) { diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 6ce3efee0c..ab233e474a 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -61,7 +61,7 @@ int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); /* find.c */ int db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime); -int db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr); +int db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr); int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, MEDIA_DBR *mr); /* get.c */ @@ -69,7 +69,7 @@ int db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr); int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr); int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr); int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **VolumeNames); -int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fdbr); +int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr); int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr); int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); int db_get_num_media_records(JCR *jcr, B_DB *mdb); diff --git a/bacula/src/cats/sql_delete.c b/bacula/src/cats/sql_delete.c index 45de5dc65c..5a0790804e 100644 --- a/bacula/src/cats/sql_delete.c +++ b/bacula/src/cats/sql_delete.c @@ -153,7 +153,7 @@ static int delete_handler(void *ctx, int num_fields, char **row) */ static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr) { - char *query = (char *)get_pool_memory(PM_MESSAGE); + POOLMEM *query = get_pool_memory(PM_MESSAGE); struct s_del_ctx del; int i; @@ -173,11 +173,11 @@ static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr) for (i=0; i < del.num_ids; i++) { Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]); - Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]); + Mmsg(&query, "DELETE FROM Job WHERE JobId=%u", del.JobId[i]); db_sql_query(mdb, query, NULL, (void *)NULL); - Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]); + Mmsg(&query, "DELETE FROM File WHERE JobId=%u", del.JobId[i]); db_sql_query(mdb, query, NULL, (void *)NULL); - Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%u", del.JobId[i]); db_sql_query(mdb, query, NULL, (void *)NULL); } free(del.JobId); diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index c0379235f8..87942d2b25 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -53,8 +53,10 @@ extern void print_result(B_DB *mdb); extern int QueryDB(char *file, int line, JCR *jcr, B_DB *db, char *select_cmd); /* - * Find job start time. Used to find last full save - * for Incremental and Differential saves. + * Find job start time if JobId specified, otherwise + * find last full save for Incremental and Differential saves. + * + * StartTime is returned in stime * * Returns: 0 on failure * 1 on success, jr is unchanged, but stime is set @@ -63,7 +65,6 @@ int db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) { SQL_ROW row; - uint32_t JobId; db_lock(mdb); @@ -71,26 +72,23 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) /* If no Id given, we must find corresponding job */ if (jr->JobId == 0) { /* Differential is since last Full backup */ - if (jr->Level == L_DIFFERENTIAL) { Mmsg(&mdb->cmd, -"SELECT JobId FROM Job WHERE JobStatus='T' AND Type='%c' AND " +"SELECT StartTime FROM Job WHERE JobStatus='T' AND Type='%c' AND " "Level='%c' AND Name='%s' AND ClientId=%u AND FileSetId=%u " "ORDER BY StartTime DESC LIMIT 1", jr->Type, L_FULL, jr->Name, jr->ClientId, jr->FileSetId); + + if (jr->Level == L_DIFFERENTIAL) { + /* SQL cmd for Differential backup already edited above */ + /* Incremental is since last Full, Incremental, or Differential */ } else if (jr->Level == L_INCREMENTAL) { - Mmsg(&mdb->cmd, -"SELECT JobId FROM Job WHERE JobStatus='T' AND Type='%c' AND " -"Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%u " -"ORDER BY StartTime DESC LIMIT 1", - jr->Type, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name, - jr->ClientId); - } else { - Mmsg1(&mdb->errmsg, _("Unknown level=%d\n"), jr->Level); - db_unlock(mdb); - return 0; - } - Dmsg1(100, "Submitting: %s\n", mdb->cmd); + /* + * For an Incremental job, we must first ensure + * that a Full backup was done (cmd edited above) + * then we do a second look to find the most recent + * backup + */ if (!QUERY_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); @@ -99,18 +97,27 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); - Mmsg(&mdb->errmsg, _("No prior Job record found.\n")); + Mmsg(&mdb->errmsg, _("No prior Full backup Job record found.\n")); db_unlock(mdb); return 0; } - JobId = atoi(row[0]); sql_free_result(mdb); + /* Now edit SQL command for Incremental Job */ + Mmsg(&mdb->cmd, +"SELECT StartTime FROM Job WHERE JobStatus='T' AND Type='%c' AND " +"Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%u " +"AND FileSetId=%u ORDER BY StartTime DESC LIMIT 1", + jr->Type, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name, + jr->ClientId, jr->FileSetId); } else { - JobId = jr->JobId; /* search for particular id */ + Mmsg1(&mdb->errmsg, _("Unknown level=%d\n"), jr->Level); + db_unlock(mdb); + return 0; } - + } else { Dmsg1(100, "Submitting: %s\n", mdb->cmd); - Mmsg(&mdb->cmd, "SELECT StartTime FROM Job WHERE Job.JobId=%u", JobId); + Mmsg(&mdb->cmd, "SELECT StartTime FROM Job WHERE Job.JobId=%u", jr->JobId); + } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { pm_strcpy(stime, ""); /* set EOS */ @@ -121,7 +128,7 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) } if ((row = sql_fetch_row(mdb)) == NULL) { - Mmsg2(&mdb->errmsg, _("No Job found for JobId=%u: ERR=%s\n"), JobId, sql_strerror(mdb)); + Mmsg1(&mdb->errmsg, _("No Job record found: ERR=%s\n"), sql_strerror(mdb)); sql_free_result(mdb); db_unlock(mdb); return 0; @@ -144,7 +151,7 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) * 0 on failure */ int -db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr) +db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr) { SQL_ROW row; @@ -152,20 +159,27 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr) db_lock(mdb); if (jr->Level == L_VERIFY_CATALOG) { Mmsg(&mdb->cmd, -"SELECT JobId FROM Job WHERE Type='V' AND Level='%c' AND Name='%s' AND " +"SELECT JobId FROM Job WHERE Type='V' AND Level='%c' AND " +" JobStatus='T' AND Name='%s' AND " "ClientId=%u ORDER BY StartTime DESC LIMIT 1", L_VERIFY_INIT, jr->Name, jr->ClientId); - } else if (jr->Level == L_VERIFY_VOLUME_TO_CATALOG) { + } else if (jr->Level == L_VERIFY_VOLUME_TO_CATALOG || + jr->Level == L_VERIFY_DISK_TO_CATALOG) { + if (Name) { + Mmsg(&mdb->cmd, +"SELECT JobId FROM Job WHERE Type='B' AND JobStatus='T' AND " +"Name='%s' ORDER BY StartTime DESC LIMIT 1", Name); + } else { Mmsg(&mdb->cmd, -"SELECT JobId FROM Job WHERE Type='B' AND " -"ClientId=%u ORDER BY StartTime DESC LIMIT 1", - jr->ClientId); +"SELECT JobId FROM Job WHERE Type='B' AND JobStatus='T' AND " +"ClientId=%u ORDER BY StartTime DESC LIMIT 1", jr->ClientId); + } } else { Mmsg1(&mdb->errmsg, _("Unknown Job level=%c\n"), jr->Level); db_unlock(mdb); return 0; } - + Dmsg1(100, "Query: %s\n", mdb->cmd); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); return 0; diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 7ff3a44fe6..9609d8570a 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -48,7 +48,7 @@ */ /* Forward referenced functions */ -static int db_get_file_record(JCR *jcr, B_DB *mdb, FILE_DBR *fdbr); +static int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr); static int db_get_filename_record(JCR *jcr, B_DB *mdb); static int db_get_path_record(JCR *jcr, B_DB *mdb); @@ -67,10 +67,10 @@ extern void split_path_and_filename(JCR *jcr, B_DB *mdb, char *fname); * Returns: 0 on failure * 1 on success with the File record in FILE_DBR */ -int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fdbr) +int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr) { int stat; - Dmsg1(20, "Enter get_file_from_catalog fname=%s \n", fname); + Dmsg1(100, "db_get_file_att_record fname=%s \n", fname); db_lock(mdb); split_path_and_filename(jcr, mdb, fname); @@ -79,7 +79,7 @@ int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fd fdbr->PathId = db_get_path_record(jcr, mdb); - stat = db_get_file_record(jcr, mdb, fdbr); + stat = db_get_file_record(jcr, mdb, jr, fdbr); db_unlock(mdb); @@ -99,15 +99,23 @@ int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, FILE_DBR *fd * "normal" if a new file is found during Verify. */ static -int db_get_file_record(JCR *jcr, B_DB *mdb, FILE_DBR *fdbr) +int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) { SQL_ROW row; int stat = 0; + if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) { Mmsg(&mdb->cmd, -"SELECT FileId, LStat, MD5 from File where File.JobId=%u and File.PathId=%u and \ -File.FilenameId=%u", fdbr->JobId, fdbr->PathId, fdbr->FilenameId); - +"SELECT FileId, LStat, MD5 FROM File,Job WHERE " +"File.JobId=Job.JobId AND File.PathId=%u AND " +"File.FilenameId=%u AND Job.Type='B' AND Job.JobSTATUS='T' AND " +"ClientId=%u ORDER BY StartTime DESC LIMIT 1", + fdbr->PathId, fdbr->FilenameId, jr->ClientId); + } else { + Mmsg(&mdb->cmd, +"SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%u AND File.PathId=%u AND " +"File.FilenameId=%u", fdbr->JobId, fdbr->PathId, fdbr->FilenameId); + } Dmsg3(050, "Get_file_record JobId=%u FilenameId=%u PathId=%u\n", fdbr->JobId, fdbr->FilenameId, fdbr->PathId); @@ -254,15 +262,15 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) db_lock(mdb); if (jr->JobId == 0) { - Mmsg(&mdb->cmd, "SELECT VolSessionId,VolSessionTime,\ -PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,\ -Type,Level \ -FROM Job WHERE Job='%s'", jr->Job); + Mmsg(&mdb->cmd, "SELECT VolSessionId,VolSessionTime," +"PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus," +"Type,Level,ClientId " +"FROM Job WHERE Job='%s'", jr->Job); } else { - Mmsg(&mdb->cmd, "SELECT VolSessionId,VolSessionTime,\ -PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,\ -Type,Level \ -FROM Job WHERE JobId=%u", jr->JobId); + Mmsg(&mdb->cmd, "SELECT VolSessionId,VolSessionTime," +"PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus," +"Type,Level,ClientId " +"FROM Job WHERE JobId=%u", jr->JobId); } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { @@ -288,6 +296,7 @@ FROM Job WHERE JobId=%u", jr->JobId); jr->JobStatus = (int)*row[9]; jr->Type = (int)*row[10]; jr->Level = (int)*row[11]; + jr->ClientId = str_to_uint64(row[12]); sql_free_result(mdb); db_unlock(mdb); diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index 510c21bab2..4acb2b8f59 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -103,9 +103,10 @@ db_update_job_start_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) JobTDate = (btime_t)stime; db_lock(mdb); - Mmsg(&mdb->cmd, "UPDATE Job SET Level='%c', StartTime='%s', \ -ClientId=%u, JobTDate=%s WHERE JobId=%u", + Mmsg(&mdb->cmd, "UPDATE Job SET Level='%c', StartTime='%s'," +"ClientId=%u, JobTDate=%s WHERE JobId=%u", (char)(jr->Level), dt, jr->ClientId, edit_uint64(JobTDate, ed1), jr->JobId); + stat = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); mdb->changes = 0; diff --git a/bacula/src/console/Makefile.in b/bacula/src/console/Makefile.in index d5b91b7216..9f9d3d7364 100644 --- a/bacula/src/console/Makefile.in +++ b/bacula/src/console/Makefile.in @@ -59,7 +59,7 @@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status clean: @$(RMF) console core core.* a.out *.o *.bak *~ *.intpro *.extpro 1 2 3 - @$(RMF) static-console + @$(RMF) static-console gmon.out realclean: clean @$(RMF) tags console.conf diff --git a/bacula/src/console2.glade b/bacula/src/console2.glade new file mode 100644 index 0000000000..2c2619445c --- /dev/null +++ b/bacula/src/console2.glade @@ -0,0 +1,3080 @@ + + + + + + + True + Bacula Console + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + + + + + True + False + 0 + + + + 1 + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + + + + True + _File + True + + + + True + + + + True + Connect to Director + _Connect + True + + + + + + + True + Disconnect from Director + _Disconnect + True + + + + + + + True + + + + + + True + gtk-quit + True + + Exit + + + + + + + + + + + + True + _Edit + True + + + + True + + + + True + gtk-cut + True + + Cut + + + + + + + + True + gtk-copy + True + + Copy + + + + + + + + True + gtk-paste + True + + Paste + + + + + + + + True + gtk-clear + True + + Clear + + + + + + + + True + + + + + + + + + + True + Display Messages + _View + True + + + + True + + + + True + _Display Messages + True + + + + + + + + + + + True + _Settings + True + + + + True + + + + True + gtk-preferences + True + + Preferences + + + + + + + + + + + + True + _Help + True + + + + True + + + + True + gnome-stock-about + True + + About + + + + + + + + + + + + + 0 + False + True + + + + + + 1 + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + 1 + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + + + + True + Connect to Director + Connect + True + gtk-new + + + + + + + True + Run a Job + Run + True + gtk-execute + + + + + + + True + Display Messages + Msgs + True + gtk-find + + + + + + + True + Restore + True + gtk-revert-to-saved + + + + + + + True + Label + True + gtk-save-as + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + False + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Command: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + True + + + + + + True + Enter Commands Here + True + True + True + True + True + True + 150 + + True + * + False + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + Status: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + About Bacula Console + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + True + False + + + + + + 1 + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Bacula Console 1.32c (24 Oct 03) + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + + 0 + False + False + + + + + + True + Copyright (c) 1999 - 2002, Kern Sibbald and John Walker + False + False + GTK_JUSTIFY_LEFT + False + False + 0.1 + 0.5 + 0 + 0 + + + 0 + True + False + + + + + + True + Authors: Kern Sibbald and John Walker + False + False + GTK_JUSTIFY_LEFT + False + False + 0.0400001 + 0.5 + 0 + 0 + + + 0 + True + False + + + + + + True + It comes by night and sucks the essence from your computers + False + False + GTK_JUSTIFY_LEFT + False + False + 0.15 + 0.5 + 0 + 0 + + + 0 + True + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + Select Director + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + False + 0 + + + + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 2 + 0 + + + 0 + False + False + + + + + + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.48 + 0.46 + 0 + 0 + + + 0 + False + False + + + + + + True + Select Director + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + 6 + True + False + True + False + True + False + + + + True + True + True + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + Run a Job + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + GTK_BUTTONBOX_END + 8 + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + + + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Run a Job + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 9 + + + 2 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Job: + False + False + GTK_JUSTIFY_RIGHT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 1 + True + True + + + + + + True + Type: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 6 + False + False + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 30 + False + False + + + + + 2 + False + False + + + + + + True + False + 0 + + + + True + Client: + False + False + GTK_JUSTIFY_RIGHT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 1 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 123 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + FileSet: + False + False + GTK_JUSTIFY_RIGHT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + True + View FileSet + True + GTK_RELIEF_NORMAL + + + + 10 + False + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 65 + False + False + + + + + 2 + True + True + + + + + + True + False + 0 + + + + True + Level: + False + False + GTK_JUSTIFY_RIGHT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 100 + False + False + + + + + 2 + True + True + + + + + + True + False + 0 + + + + True + Pool: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 120 + False + False + + + + + 2 + True + True + + + + + + True + False + 0 + + + + True + Storage: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 120 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Messages: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 120 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Where: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 120 + False + False + + + + + 2 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + When: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 120 + False + False + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + Restore File Selection + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + + + + True + False + 0 + + + + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + cwd: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + True + + + + + + True + Enter Commands Here + True + True + True + True + True + True + 0 + + True + * + False + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_FILL + False + False + 0.5 + 0.5 + 59 + 0 + + + 0 + True + False + + + + + + 9 + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + 0 + True + False + + + + + 0 + False + True + + + + + + + + True + Restore Files + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + GTK_BUTTONBOX_END + 8 + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + + + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + 8 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + GTK_PACK_END + + + + + + True + False + 0 + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 2 + + + 0 + False + False + + + + + + 3 + True + True + Select most recent backup + True + GTK_RELIEF_NORMAL + True + False + True + + + 0 + False + False + + + + + + 5 + True + True + Select list of Jobs + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + + 4 + True + True + Find a specific file + True + GTK_RELIEF_NORMAL + False + False + True + + + 0 + False + False + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + Select by: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + False + 0 + + + + + + + + 50 + True + True + gtk-apply + True + GTK_RELIEF_NORMAL + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + Label a Volume + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + True + True + False + True + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + GTK_BUTTONBOX_END + 8 + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + + + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + Label a Volume + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 9 + + + 0 + False + False + + + + + + 5 + True + False + 0 + + + + True + Storage: + False + False + GTK_JUSTIFY_CENTER + False + False + 0.15 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 15 + True + True + + + + + + + + + 0 + False + True + + + + + + 5 + True + False + 0 + + + + True + Pool: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.12 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + True + False + False + True + False + + + + True + True + False + True + 0 + + True + * + False + + + + + + True + GTK_SELECTION_BROWSE + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + True + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + + + + + + + 14 + True + True + + + + + + + + + 0 + False + True + + + + + + 5 + True + False + 0 + + + + True + Volume Name: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.17 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + + + + + 0 + False + True + + + + + + 5 + True + False + 0 + + + + True + Slot: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.09 + 0.5 + 0 + 0 + + + 0 + False + True + + + + + + True + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 0 0 10000 1 10 10 + + + 0 + True + True + + + + + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + 0 + False + True + + + + + + + diff --git a/bacula/src/console2.gladep b/bacula/src/console2.gladep new file mode 100644 index 0000000000..8e701cb6f4 --- /dev/null +++ b/bacula/src/console2.gladep @@ -0,0 +1,8 @@ + + + + + console + gnome-console + gnome2-console + diff --git a/bacula/src/dird/.cvsignore b/bacula/src/dird/.cvsignore index e5ca4c1c7b..fb6ff2128c 100644 --- a/bacula/src/dird/.cvsignore +++ b/bacula/src/dird/.cvsignore @@ -8,3 +8,4 @@ btraceback btraceback.gdb startit stopit +dird.conf diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index 299cf2c663..851d93d336 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -30,7 +30,7 @@ SVRSRCS = dird.c admin.c authenticate.c \ recycle.c restore.c run_conf.c \ scheduler.c sql_cmds.c \ ua_cmds.c ua_dotcmds.c \ - ua_query.c ua_retention.c \ + ua_query.c \ ua_input.c ua_label.c ua_output.c ua_prune.c \ ua_purge.c ua_restore.c ua_run.c \ ua_select.c ua_server.c \ @@ -43,7 +43,7 @@ SVROBJS = dird.o admin.o authenticate.o \ recycle.o restore.o run_conf.o \ scheduler.o sql_cmds.o \ ua_cmds.o ua_dotcmds.o \ - ua_query.o ua_retention.o \ + ua_query.o \ ua_input.o ua_label.o ua_output.o ua_prune.o \ ua_purge.o ua_restore.o ua_run.o \ ua_select.o ua_server.o \ diff --git a/bacula/src/dird/authenticate.c b/bacula/src/dird/authenticate.c index b41ca667c6..9ec6d81bf1 100644 --- a/bacula/src/dird/authenticate.c +++ b/bacula/src/dird/authenticate.c @@ -69,7 +69,7 @@ int authenticate_storage_daemon(JCR *jcr) } if (!cram_md5_get_auth(sd, jcr->store->password, ssl_need) || !cram_md5_auth(sd, jcr->store->password, ssl_need)) { - Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords not the same.\n")); + Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n")); return 0; } Dmsg1(116, ">stored: %s", sd->msg); @@ -106,7 +106,7 @@ int authenticate_file_daemon(JCR *jcr) } if (!cram_md5_get_auth(fd, jcr->client->password, ssl_need) || !cram_md5_auth(fd, jcr->client->password, ssl_need)) { - Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords not the same.\n")); + Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n")); return 0; } Dmsg1(116, ">filed: %s", fd->msg); diff --git a/bacula/src/dird/backup.c b/bacula/src/dird/backup.c index 8d547b4065..0875b3021a 100644 --- a/bacula/src/dird/backup.c +++ b/bacula/src/dird/backup.c @@ -228,7 +228,7 @@ int wait_for_job_termination(JCR *jcr) { int32_t n = 0; BSOCK *fd = jcr->file_bsock; - int fd_ok = FALSE; + bool fd_ok = false; uint32_t JobFiles, Errors; uint64_t ReadBytes, JobBytes; @@ -237,7 +237,7 @@ int wait_for_job_termination(JCR *jcr) while ((n = bget_dirmsg(fd)) >= 0) { if (!fd_ok && sscanf(fd->msg, EndJob, &jcr->FDJobStatus, &JobFiles, &ReadBytes, &JobBytes, &Errors) == 5) { - fd_ok = TRUE; + fd_ok = true; set_jcr_job_status(jcr, jcr->FDJobStatus); Dmsg1(100, "FDStatus=%c\n", (char)jcr->JobStatus); } else { @@ -257,12 +257,15 @@ int wait_for_job_termination(JCR *jcr) /* Note, the SD stores in jcr->JobFiles/ReadBytes/JobBytes/Errors */ wait_for_storage_daemon_termination(jcr); + /* Return values from FD */ if (fd_ok) { jcr->JobFiles = JobFiles; jcr->Errors = Errors; jcr->ReadBytes = ReadBytes; jcr->JobBytes = JobBytes; + } else { + Jmsg(jcr, M_FATAL, 0, _("No Job status returned from FD.\n")); } // Dmsg4(000, "fd_ok=%d FDJS=%d JS=%d SDJS=%d\n", fd_ok, jcr->FDJobStatus, @@ -295,7 +298,7 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr double kbps, compression; utime_t RunTime; - Dmsg0(100, "Enter backup_cleanup()\n"); + Dmsg2(100, "Enter backup_cleanup %d %c\n", TermCode, TermCode); memset(&mr, 0, sizeof(mr)); set_jcr_job_status(jcr, TermCode); @@ -337,8 +340,12 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since, FILESET_DBR *fsr 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. 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); + } + } for (int i=0; i < VolCount; i++) { /* Write the record */ diff --git a/bacula/src/dird/bacula-dir.conf.in b/bacula/src/dird/bacula-dir.conf.in index be3f7e3626..9c00dfbdb4 100644 --- a/bacula/src/dird/bacula-dir.conf.in +++ b/bacula/src/dird/bacula-dir.conf.in @@ -185,7 +185,7 @@ Messages { # # WARNING! the following will create a file that you must cycle from # time to time as it will grow indefinitely. However, it will -# also keep all your messages if the scroll off the console. +# also keep all your messages if they scroll off the console. # append = "@working_dir@/log" = all, !skipped } diff --git a/bacula/src/dird/bsr.c b/bacula/src/dird/bsr.c index ae8ddf2a7e..b2db2e321b 100644 --- a/bacula/src/dird/bsr.c +++ b/bacula/src/dird/bsr.c @@ -35,6 +35,7 @@ /* Forward referenced functions */ static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd); +void print_bsr(UAContext *ua, RBSR *bsr); /* @@ -62,21 +63,31 @@ static void free_findex(RBSR_FINDEX *fi) * range regardless of volume. The FirstIndex and LastIndex * passed in here are for the current volume, so when * writing out the fi, constrain them to those values. + * + * We are called here once for each JobMedia record + * for each Volume. */ -static void write_findex(UAContext *ua, RBSR_FINDEX *fi, +static uint32_t write_findex(UAContext *ua, RBSR_FINDEX *fi, int32_t FirstIndex, int32_t LastIndex, FILE *fd) { - if (fi) { + uint32_t count = 0; + for ( ; fi; fi=fi->next) { int32_t findex, findex2; + if ((fi->findex >= FirstIndex && fi->findex <= LastIndex) || + (fi->findex2 >= FirstIndex && fi->findex2 <= LastIndex) || + (fi->findex < FirstIndex && fi->findex2 > LastIndex)) { findex = fi->findex < FirstIndex ? FirstIndex : fi->findex; findex2 = fi->findex2 > LastIndex ? LastIndex : fi->findex2; if (findex == findex2) { fprintf(fd, "FileIndex=%d\n", findex); + count++; } else { fprintf(fd, "FileIndex=%d-%d\n", findex, findex2); + count += findex2 - findex + 1; + } } - write_findex(ua, fi->next, FirstIndex, LastIndex, fd); } + return count; } /* @@ -101,13 +112,15 @@ static bool is_volume_selected(RBSR_FINDEX *fi, static void print_findex(UAContext *ua, RBSR_FINDEX *fi) { - if (fi) { + bsendmsg(ua, "fi=0x%x\n", (unsigned)fi); + for ( ; fi; fi=fi->next) { if (fi->findex == fi->findex2) { bsendmsg(ua, "FileIndex=%d\n", fi->findex); +// Dmsg1(000, "FileIndex=%d\n", fi->findex); } else { bsendmsg(ua, "FileIndex=%d-%d\n", fi->findex, fi->findex2); +// Dmsg2(000, "FileIndex=%d-%d\n", fi->findex, fi->findex2); } - print_findex(ua, fi->next); } } @@ -124,10 +137,10 @@ void free_bsr(RBSR *bsr) { if (bsr) { free_findex(bsr->fi); - free_bsr(bsr->next); if (bsr->VolParams) { free(bsr->VolParams); } + free_bsr(bsr->next); free(bsr); } } @@ -210,6 +223,11 @@ int write_bsr_file(UAContext *ua, RBSR *bsr) static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) { if (bsr) { + uint32_t count; + /* + * For a given volume, loop over all the JobMedia records. + * VolCount is the number of JobMedia records. + */ for (int i=0; i < bsr->VolCount; i++) { if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex)) { @@ -219,21 +237,32 @@ static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); 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); + } else { 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); + } else { fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, bsr->VolParams[i].EndBlock); - + } // Dmsg2(000, "bsr VolParam FI=%u LI=%u\n", // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); - write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, + + count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex, fd); + if (count) { + fprintf(fd, "Count=%u\n", count); + } } write_bsr(ua, bsr->next, fd); } } -static void print_bsr(UAContext *ua, RBSR *bsr) +void print_bsr(UAContext *ua, RBSR *bsr) { if (bsr) { for (int i=0; i < bsr->VolCount; i++) { @@ -296,7 +325,7 @@ void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex) } /* - * At this point, bsr points to bsr containing JobId, + * At this point, bsr points to bsr containing this JobId, * and we are sure that there is at least one fi record. */ lfi = fi = bsr->fi; @@ -318,6 +347,10 @@ void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex) if (findex == (fi->findex2 + 1)) { /* extend up */ RBSR_FINDEX *nfi; fi->findex2 = findex; + /* + * If the following record contains one higher, merge its + * file index by extending it up. + */ if (fi->next && ((findex+1) == fi->next->findex)) { nfi = fi->next; fi->findex2 = nfi->findex2; diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 05f7f1e884..44bb598019 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -145,8 +145,9 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) /* * Now try recycling if necessary + * reason set non-NULL if we cannot use it */ - is_volume_valid_or_recyclable(jcr, &mr, &reason); + check_if_volume_valid_or_recyclable(jcr, &mr, &reason); } } if (reason == NULL) { @@ -164,7 +165,8 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) Dmsg2(100, "Vol Info for %s: %s", jcr->Job, bs->msg); } else { /* Not suitable volume */ - bnet_fsend(bs, "1998 Volume \"%s\" %s.\n", mr.VolumeName, reason); + bnet_fsend(bs, "1998 Volume \"%s\" status is %s, %s.\n", mr.VolumeName, + mr.VolStatus, reason); } } else { @@ -216,14 +218,6 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus)); mr.Slot = sdmr.Slot; - /* - * Apply expiration periods and limits, if not a label request, - * and ignore status because if !label we won't use it. - */ - if (!label) { - has_volume_expired(jcr, &mr); - } - Dmsg2(200, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName); /* * Write the modified record to the DB diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index eb0a4758ec..410cbb5d36 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -241,7 +241,7 @@ static void terminate_dird(int sig) delete_pid_file(director->pid_directory, "bacula-dir", director->DIRport); stop_watchdog(); - signal(SIGCHLD, SIG_IGN); /* don't worry about children now */ +// signal(SIGCHLD, SIG_IGN); /* don't worry about children now */ term_scheduler(); if (runjob) { free(runjob); diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 47c9f98581..e80d821f9a 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -203,6 +203,7 @@ static struct res_items job_items[] = { {"pool", store_res, ITEM(res_job.pool), R_POOL, 0, 0}, {"client", store_res, ITEM(res_job.client), R_CLIENT, 0, 0}, {"fileset", store_res, ITEM(res_job.fileset), R_FILESET, 0, 0}, + {"verifyjob", store_res, ITEM(res_job.verify_job), R_JOB, 0, 0}, {"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0}, {"replace", store_replace, ITEM(res_job.replace), 0, ITEM_DEFAULT, REPLACE_ALWAYS}, {"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0}, @@ -214,6 +215,7 @@ static struct res_items job_items[] = { {"prunevolumes", store_yesno, ITEM(res_job.PruneVolumes), 1, ITEM_DEFAULT, 0}, {"runbeforejob", store_str, ITEM(res_job.RunBeforeJob), 0, 0, 0}, {"runafterjob", store_str, ITEM(res_job.RunAfterJob), 0, 0, 0}, + {"runafterfailedjob", store_str, ITEM(res_job.RunAfterFailedJob), 0, 0, 0}, {"clientrunbeforejob", store_str, ITEM(res_job.ClientRunBeforeJob), 0, 0, 0}, {"clientrunafterjob", store_str, ITEM(res_job.ClientRunAfterJob), 0, 0, 0}, {"spoolattributes", store_yesno, ITEM(res_job.SpoolAttributes), 1, ITEM_DEFAULT, 0}, @@ -345,6 +347,7 @@ struct s_jl joblevels[] = { {"Catalog", L_VERIFY_CATALOG, JT_VERIFY}, {"InitCatalog", L_VERIFY_INIT, JT_VERIFY}, {"VolumeToCatalog", L_VERIFY_VOLUME_TO_CATALOG, JT_VERIFY}, + {"DiskToCatalog", L_VERIFY_DISK_TO_CATALOG, JT_VERIFY}, {"Data", L_VERIFY_DATA, JT_VERIFY}, {NULL, 0} }; @@ -410,7 +413,7 @@ char *level_to_str(int level) void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...), void *sock) { URES *res = (URES *)reshdr; - int recurse = 1; + bool recurse = true; char ed1[100], ed2[100]; if (res == NULL) { @@ -419,7 +422,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... } if (type < 0) { /* no recursion */ type = - type; - recurse = 0; + recurse = false; } switch (type) { case R_DIRECTOR: @@ -514,6 +517,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... if (res->res_job.RunAfterJob) { sendit(sock, " --> RunAfter=%s\n", NPRT(res->res_job.RunAfterJob)); } + if (res->res_job.RunAfterFailedJob) { + sendit(sock, " --> RunAfterFailed=%s\n", NPRT(res->res_job.RunAfterFailedJob)); + } if (res->res_job.WriteBootstrap) { sendit(sock, " --> WriteBootstrap=%s\n", NPRT(res->res_job.WriteBootstrap)); } @@ -527,6 +533,11 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... } else { sendit(sock, "!!! No Pool resource\n"); } + if (res->res_job.verify_job) { + sendit(sock, " --> "); + dump_resource(-R_JOB, (RES *)res->res_job.verify_job, sendit, sock); + } + break; if (res->res_job.messages) { sendit(sock, " --> "); dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock); @@ -830,6 +841,9 @@ void free_resource(int type) if (res->res_job.RunAfterJob) { free(res->res_job.RunAfterJob); } + if (res->res_job.RunAfterFailedJob) { + free(res->res_job.RunAfterFailedJob); + } if (res->res_job.ClientRunBeforeJob) { free(res->res_job.ClientRunBeforeJob); } @@ -925,6 +939,7 @@ void save_resource(int type, struct res_items *items, int pass) res->res_job.fileset = res_all.res_job.fileset; res->res_job.storage = res_all.res_job.storage; res->res_job.pool = res_all.res_job.pool; + res->res_job.verify_job = res_all.res_job.verify_job; if (res->res_job.JobType == 0) { Emsg1(M_ERROR_TERM, 0, "Job Type not defined for Job resource %s\n", res_all.res_dir.hdr.name); } diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 5c4aad6b66..5ca6706c46 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -185,6 +185,7 @@ struct JOB { 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 */ @@ -207,6 +208,7 @@ struct JOB { FILESET *fileset; /* What to backup -- Fileset */ STORE *storage; /* Where is device -- Storage daemon */ POOL *pool; /* Where is media -- Media Pool */ + JOB *verify_job; /* Job name to verify */ uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ }; diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 4d7f1e25b9..a3341644c7 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -155,7 +155,7 @@ void get_level_since_time(JCR *jcr, char *since, int since_len) bstrncpy(since, ", since=", since_len); bstrncat(since, jcr->stime, since_len); } - Dmsg1(115, "Last start time = %s\n", jcr->stime); + Dmsg1(100, "Last start time = %s\n", jcr->stime); break; } } @@ -250,6 +250,7 @@ static int send_list(JCR *jcr, int list) } else { bstrncpy(buf, "0 ", sizeof(buf)); } + Dmsg1(100, "Opts=%s\n", buf); optlen = strlen(buf); while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) { fd->msglen = Mmsg(&fd->msg, "%s", buf); @@ -279,6 +280,7 @@ static int send_list(JCR *jcr, int list) } else { bstrncpy(buf, "0 ", sizeof(buf)); } + Dmsg1(100, "Opts=%s\n", buf); optlen = strlen(buf); while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) { fd->msglen = Mmsg(&fd->msg, "%s", buf); @@ -293,15 +295,15 @@ static int send_list(JCR *jcr, int list) p++; /* skip over \ */ /* Note, fall through wanted */ default: + Dmsg2(100, "numopts=%d opts=%s\n", ie->num_opts, NPRT(ie->opts_list[0]->opts)); if (ie->num_opts) { pm_strcpy(&fd->msg, ie->opts_list[0]->opts); pm_strcat(&fd->msg, " "); } else { pm_strcpy(&fd->msg, "0 "); } - pm_strcat(&fd->msg, p); + fd->msglen = pm_strcat(&fd->msg, p); Dmsg1(100, "Inc/Exc name=%s\n", fd->msg); - fd->msglen = strlen(fd->msg); if (!bnet_send(fd)) { Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n")); goto bail_out; diff --git a/bacula/src/dird/getmsg.c b/bacula/src/dird/getmsg.c index b2309f3709..34193975c0 100644 --- a/bacula/src/dird/getmsg.c +++ b/bacula/src/dird/getmsg.c @@ -95,7 +95,8 @@ int bget_dirmsg(BSOCK *bs) bnet_fsend(bs, OK_msg); /* send response */ break; case BNET_HEARTBEAT: - /* Dmsg0(000, "Got heartbeat.\n"); */ +// encode_time(time(NULL), Job); +// Dmsg1(000, "%s got heartbeat.\n", Job); break; case BNET_HB_RESPONSE: break; diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index bacd5bbead..1e9c69c694 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -151,8 +151,9 @@ static struct s_fs_opt FS_options[] = { /* - * Scan for old Include options (keyword=option) is converted into one or - * two characters. Verifyopts=xxxx is Vxxxx: + * Scan for right hand side of Include options (keyword=option) is + * converted into one or two characters. Verifyopts=xxxx is Vxxxx: + * Whatever is found is concatenated to the opts string. */ static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) { @@ -167,6 +168,7 @@ static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) bstrncat(opts, "V", optlen); /* indicate Verify */ bstrncat(opts, lc->str, optlen); bstrncat(opts, ":", optlen); /* terminate it */ + Dmsg3(100, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen); /* * Standard keyword options for Include/Exclude @@ -185,7 +187,7 @@ static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen) scan_err1(lc, "Expected a FileSet option keyword, got:%s:", lc->str); } else { /* add option */ bstrncat(opts, option, optlen); - Dmsg3(200, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen); + Dmsg3(100, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen); } } @@ -238,6 +240,7 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass) if ((token=lex_get_token(lc, T_ALL)) != T_EQUALS) { scan_err1(lc, _("expected an = following keyword, got: %s"), lc->str); } else { + /* Scan right hand side of option */ scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts)); } if (token == T_BOB) { @@ -258,7 +261,7 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass) } setup_current_opts(); bstrncpy(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS); - Dmsg1(200, "incexe opts=%s\n", res_incexe.current_opts->opts); + Dmsg2(100, "old pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts); /* Create incexe structure */ Dmsg0(200, "Create INCEXE structure\n"); @@ -472,7 +475,9 @@ static void store_fname(LEX *lc, struct res_items *item, int index, int pass) scan_to_eol(lc); } - +/* + * New style options come here + */ static void store_opts(LEX *lc, struct res_items *item, int index, int pass) { int i; @@ -481,6 +486,7 @@ static void store_opts(LEX *lc, struct res_items *item, int index, int pass) inc_opts[0] = 0; keyword = INC_KW_NONE; + /* Look up the keyword */ for (i=0; FS_option_kw[i].name; i++) { if (strcasecmp(item->name, FS_option_kw[i].name) == 0) { keyword = FS_option_kw[i].token; @@ -490,14 +496,13 @@ static void store_opts(LEX *lc, struct res_items *item, int index, int pass) if (keyword == INC_KW_NONE) { scan_err1(lc, "Expected a FileSet keyword, got: %s", lc->str); } - Dmsg2(200, "keyword=%d %s\n", keyword, FS_option_kw[keyword].name); + /* Now scan for the value */ scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts)); - if (pass == 1) { setup_current_opts(); - bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS); + bstrncpy(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS); + Dmsg2(100, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts); } - scan_to_eol(lc); } diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 597edcfafb..940a8001d4 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -206,13 +206,18 @@ static void *job_thread(void *arg) Pmsg1(0, "Unimplemented job type: %d\n", jcr->JobType); break; } - if (jcr->job->RunAfterJob) { + if ((jcr->job->RunAfterJob && jcr->JobStatus == JS_Terminated) || + (jcr->job->RunAfterFailedJob && jcr->JobStatus != JS_Terminated)) { POOLMEM *after = get_pool_memory(PM_FNAME); int status; BPIPE *bpipe; char line[MAXSTRING]; + if (jcr->JobStatus == JS_Terminated) { after = edit_job_codes(jcr, after, jcr->job->RunAfterJob, ""); + } else { + after = edit_job_codes(jcr, after, jcr->job->RunAfterFailedJob, ""); + } bpipe = open_bpipe(after, 0, "r"); free_pool_memory(after); while (fgets(line, sizeof(line), bpipe->rfd)) { @@ -220,8 +225,13 @@ static void *job_thread(void *arg) } status = close_bpipe(bpipe); if (status != 0) { + if (jcr->JobStatus == JS_Terminated) { Jmsg(jcr, M_FATAL, 0, _("RunAfterJob returned non-zero status=%d\n"), status); + } else { + Jmsg(jcr, M_FATAL, 0, _("RunAfterFailedJob returned non-zero status=%d\n"), + status); + } set_jcr_job_status(jcr, JS_FatalError); update_job_end_record(jcr); } diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 043fd1ac93..65a9a3bfa8 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -100,11 +100,6 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create) if (ok) { /* If we can use the volume, check if it is expired */ if (has_volume_expired(jcr, mr)) { - /* Need to update media */ - if (!db_update_media_record(jcr, jcr->db, mr)) { - Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"), - mr->VolumeName, db_strerror(jcr->db)); - } if (retry++ < 200) { /* sanity check */ continue; /* try again from the top */ } else { @@ -172,6 +167,13 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) } } } + if (expired) { + /* Need to update media */ + if (!db_update_media_record(jcr, jcr->db, mr)) { + Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"), + mr->VolumeName, db_strerror(jcr->db)); + } + } return expired; } @@ -181,39 +183,44 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) * Returns: on failure - reason = NULL * on success - reason - pointer to reason */ -bool is_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason) +void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason) { int ok; *reason = NULL; /* Check if a duration or limit has expired */ - has_volume_expired(jcr, mr); + if (has_volume_expired(jcr, mr)) { + *reason = "volume has expired"; + /* Keep going because we may be able to recycle volume */ + } /* * Now see if we can use the volume as is */ if (strcmp(mr->VolStatus, "Append") == 0 || strcmp(mr->VolStatus, "Recycle") == 0) { - return true; + *reason = NULL; + return; } /* - * Check if the Volume is alreay marked for recycling + * Check if the Volume is already marked for recycling */ if (strcmp(mr->VolStatus, "Purged") == 0) { if (recycle_volume(jcr, mr)) { Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName); - return true; + *reason = NULL; + return; } else { /* In principle this shouldn't happen */ - *reason = "recycling of current volume failed"; - return false; + *reason = "and recycling of current volume failed"; + return; } } /* At this point, the volume is not valid for writing */ - *reason = "not Append, Purged or Recycle"; + *reason = "but should be Append, Purged or Recycle"; /* * What we're trying to do here is see if the current volume is @@ -239,15 +246,14 @@ bool is_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason) /* If fully purged, recycle current volume */ if (recycle_volume(jcr, mr)) { Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName); - return true; /* Good volume */ + *reason = NULL; } else { - *reason = "not Append, Purged or Recycle (recycling of the " + *reason = "but should be Append, Purged or Recycle (recycling of the " "current volume failed)"; } } else { - *reason = "not Append, Purged or Recycle (cannot automatically " + *reason = "but should be Append, Purged or Recycle (cannot automatically " "recycle current volume, as it still contains unpruned data)"; } } - return *reason ? false : true; } diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index a4b48609de..38878c7f7b 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -102,7 +102,7 @@ extern void wait_for_storage_daemon_termination(JCR *jcr); /* next_vol.c */ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create); bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr); -bool is_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason); +void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, char **reason); /* newvol.c */ int newVolume(JCR *jcr, MEDIA_DBR *mr); @@ -132,6 +132,7 @@ int is_volume_name_legal(UAContext *ua, char *name); /* ua_output.c */ void prtit(void *ctx, char *msg); int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool); +RUN *find_next_run(RUN *run, JOB *job, time_t &runtime); /* ua_server.c */ void bsendmsg(void *sock, char *fmt, ...); diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index b40a5dc09c..d5e39203b3 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -88,6 +88,7 @@ int do_restore(JCR *jcr) /* * The following code is kept temporarily for compatibility. * It is the predecessor to the Bootstrap file. + * DEPRECATED */ if (!jcr->RestoreBootstrap) { /* diff --git a/bacula/src/dird/sql_cmds.c b/bacula/src/dird/sql_cmds.c index ce8e774cc7..4d37d86e66 100644 --- a/bacula/src/dird/sql_cmds.c +++ b/bacula/src/dird/sql_cmds.c @@ -85,12 +85,14 @@ char *insert_delcand = /* Select Jobs from the DelCandidates table that have a * more recent backup -- i.e. are not the only backup. * This is the list of Jobs to delete for a Backup Job. + * At the same time, we select "orphanned" jobs + * (i.e. no files, ...) for deletion. */ char *select_backup_del = "SELECT DelCandidates.JobId " "FROM Job,DelCandidates " - "WHERE (DelCandidates.JobFiles=0) OR " - "(DelCandidates.JobStatus!='T') OR " + "WHERE (JobTDate<%s AND ((DelCandidates.JobFiles=0) OR " + "(DelCandidates.JobStatus!='T'))) OR " "(Job.JobTDate>%s " "AND Job.ClientId=%u " "AND Job.Type='B' " @@ -211,7 +213,7 @@ char *uar_inc_dec = "Job.Level,Job.JobFiles,Job.StartTime,Media.VolumeName,JobMedia.StartFile," "Job.VolSessionId,Job.VolSessionTime " "FROM Job,JobMedia,Media " - "WHERE Job.JobTDate>%s AND Job.StartTime < '%s' " + "WHERE Job.JobTDate>%s AND Job.StartTime<'%s' " "AND Job.ClientId=%u " "AND JobMedia.JobId=Job.JobId " "AND JobMedia.MediaId=Media.MediaId " @@ -221,7 +223,9 @@ char *uar_inc_dec = char *uar_list_temp = "SELECT JobId,Level,JobFiles,StartTime,VolumeName,StartFile," - "VolSessionId,VolSessionTime FROM temp"; + "VolSessionId,VolSessionTime FROM temp " + "GROUP by JobId ORDER BY StartTime ASC"; + char *uar_sel_jobid_temp = "SELECT JobId FROM temp"; @@ -239,10 +243,11 @@ char *uar_mediatype = "SELECT MediaType FROM JobMedia,Media WHERE JobMedia.JobId=%u " "AND JobMedia.MediaId=Media.MediaId"; -/* Find JobId, FileIndex for a given path/file */ +/* Find JobId, FileIndex for a given path/file and date */ char *uar_jobid_fileindex = "SELECT Job.JobId, File.FileIndex FROM Job,File,Path,Filename,Client " "WHERE Job.JobId=File.JobId " + "AND Job.StartTime<'%s' " "AND Path.Path='%s' " "AND Filename.Name='%s' " "AND Client.Name='%s' " diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 7acb0d1216..678e569d2b 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -50,11 +50,11 @@ extern int messagescmd(UAContext *ua, char *cmd); extern int autodisplaycmd(UAContext *ua, char *cmd); extern int sqlquerycmd(UAContext *ua, char *cmd); extern int querycmd(UAContext *ua, char *cmd); -extern int runcmd(UAContext *ua, char *cmd); +extern int run_cmd(UAContext *ua, char *cmd); extern int retentioncmd(UAContext *ua, char *cmd); extern int prunecmd(UAContext *ua, char *cmd); extern int purgecmd(UAContext *ua, char *cmd); -extern int restorecmd(UAContext *ua, char *cmd); +extern int restore_cmd(UAContext *ua, char *cmd); extern int label_cmd(UAContext *ua, char *cmd); extern int relabel_cmd(UAContext *ua, char *cmd); extern int update_slots(UAContext *ua); /* ua_label.c */ @@ -75,6 +75,7 @@ static int update_volume(UAContext *ua); static int update_pool(UAContext *ua); static int delete_volume(UAContext *ua); static int delete_pool(UAContext *ua); +static int delete_job(UAContext *ua); static int mount_cmd(UAContext *ua, char *cmd); static int release_cmd(UAContext *ua, char *cmd); static int update_cmd(UAContext *ua, char *cmd); @@ -105,8 +106,8 @@ static struct cmdstruct commands[] = { { N_("quit"), quit_cmd, _("quit")}, { N_("relabel"), relabel_cmd, _("relabel a tape")}, { N_("release"), release_cmd, _("release ")}, - { N_("restore"), restorecmd, _("restore files")}, - { N_("run"), runcmd, _("run ")}, + { N_("restore"), restore_cmd, _("restore files")}, + { N_("run"), run_cmd, _("run ")}, { N_("setdebug"), setdebug_cmd, _("sets debug level")}, { N_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]")}, { N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")}, @@ -799,6 +800,26 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) free_pool_memory(query); } +/* Modify the Pool in which this Volume is located */ +static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr) +{ + POOL_DBR pr; + POOLMEM *query; + memset(&pr, 0, sizeof(pr)); + bstrncpy(pr.Name, val, sizeof(pr.Name)); + if (!get_pool_dbr(ua, &pr)) { + return; + } + query = get_pool_memory(PM_MESSAGE); + Mmsg(&query, "UPDATE Media SET PoolId=%u WHERE MediaId=%u", pr.PoolId, mr->MediaId); + if (!db_sql_query(ua->db, query, NULL, NULL)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New Pool is: %s\n"), pr.Name); + } + free_pool_memory(query); +} + /* * Update a media record -- allows you to change the * Volume status. E.g. if you want Bacula to stop @@ -808,6 +829,7 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) static int update_volume(UAContext *ua) { MEDIA_DBR mr; + POOL_DBR pr; POOLMEM *query; char ed1[30]; bool done = false; @@ -819,6 +841,7 @@ static int update_volume(UAContext *ua) N_("MaxVolFiles"), /* 4 */ N_("MaxVolBytes"), /* 5 */ N_("Recycle"), /* 6 */ + N_("Pool"), /* 7 */ NULL }; for (int i=0; kw[i]; i++) { @@ -849,6 +872,8 @@ static int update_volume(UAContext *ua) case 6: update_volrecycle(ua, ua->argv[j], &mr); break; + case 7: + update_volpool(ua, ua->argv[j], &mr); } done = true; } @@ -869,6 +894,7 @@ static int update_volume(UAContext *ua) add_prompt(ua, _("Recycle Flag")); add_prompt(ua, _("Slot")); add_prompt(ua, _("Volume Files")); + add_prompt(ua, _("Pool")); add_prompt(ua, _("Done")); switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) { case 0: /* Volume Status */ @@ -944,7 +970,6 @@ static int update_volume(UAContext *ua) case 7: /* Slot */ int slot; - POOL_DBR pr; memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; @@ -999,6 +1024,19 @@ static int update_volume(UAContext *ua) free_pool_memory(query); break; + case 9: /* Volume's Pool */ + 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)); + return 0; + } + bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name); + if (!get_cmd(ua, _("Enter new Pool name: "))) { + return 0; + } + update_volpool(ua, ua->cmd, &mr); + return 1; default: /* Done or error */ bsendmsg(ua, "Selection done.\n"); return 1; @@ -1414,15 +1452,13 @@ static int delete_cmd(UAContext *ua, char *cmd) static char *keywords[] = { N_("volume"), N_("pool"), + N_("job"), NULL}; if (!open_db(ua)) { return 1; } - bsendmsg(ua, _( -"In general it is not a good idea to delete either a\n" -"Pool or a Volume since they may contain data.\n\n")); switch (find_arg_keyword(ua, keywords)) { case 0: @@ -1431,9 +1467,17 @@ static int delete_cmd(UAContext *ua, char *cmd) case 1: delete_pool(ua); return 1; + case 2: + delete_job(ua); + return 1; default: break; } + + bsendmsg(ua, _( +"In general it is not a good idea to delete either a\n" +"Pool or a Volume since they may contain data.\n\n")); + switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) { case 0: delete_volume(ua); @@ -1441,6 +1485,9 @@ static int delete_cmd(UAContext *ua, char *cmd) case 1: delete_pool(ua); break; + case 2: + delete_job(ua); + return 1; default: bsendmsg(ua, _("Nothing done.\n")); break; @@ -1448,6 +1495,30 @@ static int delete_cmd(UAContext *ua, char *cmd) return 1; } +static int delete_job(UAContext *ua) +{ + POOLMEM *query = get_pool_memory(PM_MESSAGE); + JobId_t JobId; + + int i = find_arg_with_value(ua, "jobid"); + if (i >= 0) { + JobId = str_to_int64(ua->argv[i]); + } else if (!get_pint(ua, _("Enter JobId to delete: "))) { + return 0; + } else { + JobId = ua->pint32_val; + } + Mmsg(&query, "DELETE FROM Job WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM File WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%u", JobId); + db_sql_query(ua->db, query, NULL, (void *)NULL); + free_pool_memory(query); + bsendmsg(ua, _("Job %u and associated records deleted from the catalog.\n"), JobId); + return 1; +} + /* * Delete media records from database -- dangerous */ diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 028c5e74b7..ecbf8aa38f 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -148,8 +148,8 @@ static int do_label(UAContext *ua, char *cmd, int relabel) char dev_name[MAX_NAME_LENGTH]; MEDIA_DBR mr, omr; POOL_DBR pr; + bool print_reminder = true; int ok = FALSE; - int mounted = FALSE; int i; bool media_record_exists = false; static char *barcode_keyword[] = { @@ -284,12 +284,17 @@ checkName: /* 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 */ - mounted = strncmp(sd->msg, "3001 ", 5) == 0; + if (strncmp(sd->msg, "3001 ", 5) == 0 || + strncmp(sd->msg, "3906 ", 5) == 0) { + print_reminder = false; } } } - if (!mounted) { + } + if (print_reminder) { bsendmsg(ua, _("Do not forget to mount the drive!!!\n")); } bnet_sig(sd, BNET_TERMINATE); diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index b79001982e..779b0ab3df 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -372,6 +372,10 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) strcasecmp(ua->argk[i], _("nextvolume")) == 0) { JOB *job; JCR *jcr = ua->jcr; + POOL *pool; + RUN *run; + time_t runtime; + i = find_arg_with_value(ua, "job"); if (i <= 0) { if ((job = select_job_resource(ua)) == NULL) { @@ -386,7 +390,9 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) } } } - if (!complete_jcr_for_job(jcr, job, NULL)) { + for (run=NULL; (run = find_next_run(run, job, runtime)); ) { + pool = run ? run->pool : NULL; + if (!complete_jcr_for_job(jcr, job, pool)) { return 1; } @@ -399,6 +405,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) bsendmsg(ua, "The next Volume to be used by Job \"%s\" will be %s\n", job->hdr.name, mr.VolumeName); } + } db_close_database(jcr, jcr->db); jcr->db = NULL; } else { @@ -408,6 +415,96 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) return 1; } +/* + * For a given job, we examine all his run records + * to see if it is scheduled today or tomorrow. + */ +RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) +{ + time_t now, tomorrow; + SCHED *sched; + struct tm tm; + int mday, wday, month, wpos, tmday, twday, tmonth, twpos, i, hour; + int tod, tom; + + Dmsg0(200, "enter find_runs()\n"); + + sched = job->schedule; + if (sched == NULL) { /* scheduled? */ + return NULL; /* no nothing to report */ + } + /* Break down current time into components */ + now = time(NULL); + localtime_r(&now, &tm); + mday = tm.tm_mday - 1; + wday = tm.tm_wday; + month = tm.tm_mon; + wpos = (tm.tm_mday - 1) / 7; + + /* Break down tomorrow into components */ + tomorrow = now + 60 * 60 * 24; + localtime_r(&tomorrow, &tm); + tmday = tm.tm_mday - 1; + twday = tm.tm_wday; + tmonth = tm.tm_mon; + twpos = (tm.tm_mday - 1) / 7; + + if (run == NULL) { + run = sched->run; + } else { + run = run->next; + } + for ( ; run; run=run->next) { + /* + * Find runs in next 24 hours + */ + tod = (bit_is_set(mday, run->mday) || bit_is_set(wday, run->wday)) && + bit_is_set(month, run->month) && bit_is_set(wpos, run->wpos); + + tom = (bit_is_set(tmday, run->mday) || bit_is_set(twday, run->wday)) && + bit_is_set(tmonth, run->month) && bit_is_set(wpos, run->wpos); + + Dmsg2(200, "tod=%d tom=%d\n", tod, tom); + if (tod) { /* Jobs scheduled today (next 24 hours) */ + /* find time (time_t) job is to be run */ + localtime_r(&now, &tm); + hour = 0; + for (i=tm.tm_hour; i < 24; i++) { + if (bit_is_set(i, run->hour)) { + tm.tm_hour = i; + tm.tm_min = run->minute; + tm.tm_sec = 0; + runtime = mktime(&tm); + if (runtime > now) { + return run; /* found it, return run resource */ + } + } + } + } + +// Dmsg2(200, "runtime=%d now=%d\n", runtime, now); + if (tom) { /* look at jobs scheduled tomorrow */ + localtime_r(&tomorrow, &tm); + hour = 0; + for (i=0; i < 24; i++) { + if (bit_is_set(i, run->hour)) { + hour = i; + break; + } + } + tm.tm_hour = hour; + tm.tm_min = run->minute; + tm.tm_sec = 0; + runtime = mktime(&tm); + Dmsg2(200, "truntime=%d now=%d\n", runtime, now); + if (runtime < tomorrow) { + return run; /* found it, return run resource */ + } + } + } /* end for loop over runs */ + /* Nothing found */ + return NULL; +} /* * Fill in the remaining fields of the jcr as if it * is going to run the job. diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c index cd6684a3f1..2278405d80 100644 --- a/bacula/src/dird/ua_prune.c +++ b/bacula/src/dird/ua_prune.c @@ -270,7 +270,7 @@ int prune_files(UAContext *ua, CLIENT *client) del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); - /* Now process same set but making delete list */ + /* Now process same set but making a delete list */ db_sql_query(ua->db, query, file_delete_handler, (void *)&del); for (i=0; i < del.num_ids; i++) { @@ -286,7 +286,7 @@ int prune_files(UAContext *ua, CLIENT *client) * Now mark Job as having files purged. This is necessary to * avoid having too many Jobs to process in future prunings. If * we don't do this, the number of JobId's in our in memory list - * will grow very large. + * could grow very large. */ Mmsg(&query, upd_Purged, del.JobId[i]); db_sql_query(ua->db, query, NULL, (void *)NULL); @@ -415,7 +415,7 @@ int prune_jobs(UAContext *ua, CLIENT *client, int JobType) switch (JobType) { case JT_ADMIN: case JT_BACKUP: - Mmsg(&query, select_backup_del, ed1, cr.ClientId); + Mmsg(&query, select_backup_del, ed1, ed1, cr.ClientId); break; case JT_RESTORE: Mmsg(&query, select_restore_del, ed1, cr.ClientId); diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index c195a50ef4..ddf47cc087 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -38,7 +38,8 @@ /* Imported functions */ -extern int runcmd(UAContext *ua, char *cmd); +extern int run_cmd(UAContext *ua, char *cmd); +extern void print_bsr(UAContext *ua, RBSR *bsr); /* Imported variables */ extern char *uar_list_jobs, *uar_file, *uar_sel_files; @@ -100,15 +101,17 @@ static void build_directory_tree(UAContext *ua, RESTORE_CTX *rx); static void free_rx(RESTORE_CTX *rx); static void split_path_and_filename(RESTORE_CTX *rx, char *fname); static int jobid_fileindex_handler(void *ctx, int num_fields, char **row); -static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file); -static void insert_one_file(UAContext *ua, RESTORE_CTX *rx); +static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, + char *date); +static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date); static int get_client_name(UAContext *ua, RESTORE_CTX *rx); +static int get_date(UAContext *ua, char *date, int date_len); /* * Restore files * */ -int restorecmd(UAContext *ua, char *cmd) +int restore_cmd(UAContext *ua, char *cmd) { RESTORE_CTX rx; /* restore context */ JOB *job = NULL; @@ -164,7 +167,7 @@ int restorecmd(UAContext *ua, char *cmd) case 1: /* select by jobid */ build_directory_tree(ua, &rx); break; - case 2: + case 2: /* select by filename, no tree needed */ break; } @@ -174,7 +177,6 @@ int restorecmd(UAContext *ua, char *cmd) free_rx(&rx); return 0; } -// print_bsr(ua, rx.bsr); write_bsr_file(ua, rx.bsr); bsendmsg(ua, _("\n%u file%s selected to restore.\n\n"), rx.selected_files, rx.selected_files==1?"":"s"); @@ -210,10 +212,12 @@ int restorecmd(UAContext *ua, char *cmd) job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"", working_directory); } - + if (find_arg(ua, _("run")) >= 0) { + pm_strcat(&ua->cmd, " run"); /* pass it on to the run command */ + } Dmsg1(400, "Submitting: %s\n", ua->cmd); parse_ua_args(ua); - runcmd(ua, ua->cmd); + run_cmd(ua, ua->cmd); bsendmsg(ua, _("Restore command done.\n")); free_rx(&rx); @@ -223,6 +227,7 @@ int restorecmd(UAContext *ua, char *cmd) static void free_rx(RESTORE_CTX *rx) { free_bsr(rx->bsr); + rx->bsr = NULL; if (rx->JobIds) { free_pool_memory(rx->JobIds); rx->JobIds = NULL; @@ -272,6 +277,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) { char *p; char date[MAX_TIME_LENGTH]; + bool have_date = false; JobId_t JobId; JOB_DBR jr; bool done = false; @@ -284,6 +290,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) "Select the most recent backup for a client", "Select backup for a client before a specified time", "Enter a list of files to restore", + "Enter a list of files to restore before a specified time", "Cancel", NULL }; @@ -292,24 +299,26 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) "current", /* 1 */ "before", /* 2 */ "file", /* 3 */ + "select", /* 4 */ NULL }; + *rx->JobIds = 0; switch (find_arg_keyword(ua, kw)) { case 0: /* jobid */ + for ( ;; ) { i = find_arg_with_value(ua, _("jobid")); if (i < 0) { - return 0; + break; } pm_strcpy(&rx->JobIds, ua->argv[i]); + ua->argk[i][0] = 0; /* "consume" jobid= */ + } done = true; break; case 1: /* current */ bstrutime(date, sizeof(date), time(NULL)); - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = true; + have_date = true; break; case 2: /* before */ i = find_arg_with_value(ua, _("before")); @@ -321,12 +330,12 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) return 0; } bstrncpy(date, ua->argv[i], sizeof(date)); - if (!select_backups_before_date(ua, rx, date)) { - return 0; - } - done = true; + have_date = true; break; case 3: /* file */ + if (!have_date) { + bstrutime(date, sizeof(date), time(NULL)); + } if (!get_client_name(ua, rx)) { return 0; } @@ -336,12 +345,21 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) break; } pm_strcpy(&ua->cmd, ua->argv[i]); - insert_one_file(ua, rx); - ua->argk[i][0] = 0; + insert_one_file(ua, rx, date); + ua->argk[i][0] = 0; /* "consume" the file= */ } /* Check MediaType and select storage that corresponds */ get_storage_from_mediatype(ua, &rx->name_list, rx); return 2; + case 4: /* select */ + if (!have_date) { + bstrutime(date, sizeof(date), time(NULL)); + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + done = true; + break; default: break; } @@ -402,26 +420,44 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) } break; case 5: /* select backup at specified time */ - bsendmsg(ua, _("The restored files will the most current backup\n" - "BEFORE the date you specify below.\n\n")); + if (!get_date(ua, date, sizeof(date))) { + return 0; + } + if (!select_backups_before_date(ua, rx, date)) { + return 0; + } + break; + case 6: /* Enter files */ + bstrutime(date, sizeof(date), time(NULL)); + if (!get_client_name(ua, rx)) { + return 0; + } + bsendmsg(ua, _("Enter file names, or < to enter a filename\n" + "containg a list of file names, and terminate\n" + "them with a blank line.\n")); for ( ;; ) { - if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) { + if (!get_cmd(ua, _("Enter filename: "))) { return 0; } - if (str_to_utime(ua->cmd) != 0) { + len = strlen(ua->cmd); + if (len == 0) { break; } - bsendmsg(ua, _("Improper date format.\n")); + insert_one_file(ua, rx, date); } - bstrncpy(date, ua->cmd, sizeof(date)); - if (!select_backups_before_date(ua, rx, date)) { + /* Check MediaType and select storage that corresponds */ + get_storage_from_mediatype(ua, &rx->name_list, rx); + return 2; + case 7: /* enter files backed up before specified time */ + if (!get_date(ua, date, sizeof(date))) { return 0; } - break; - case 6: /* Enter files */ if (!get_client_name(ua, rx)) { return 0; } + bsendmsg(ua, _("Enter file names, or < to enter a filename\n" + "containg a list of file names, and terminate\n" + "them with a blank line.\n")); for ( ;; ) { if (!get_cmd(ua, _("Enter filename: "))) { return 0; @@ -430,13 +466,14 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) if (len == 0) { break; } - insert_one_file(ua, rx); + insert_one_file(ua, rx, date); } /* Check MediaType and select storage that corresponds */ get_storage_from_mediatype(ua, &rx->name_list, rx); return 2; - case 7: /* Cancel or quit */ + + case 8: /* Cancel or quit */ return 0; } } @@ -473,7 +510,24 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx) return 1; } -static void insert_one_file(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")); + for ( ;; ) { + if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) { + return 0; + } + if (str_to_utime(ua->cmd) != 0) { + break; + } + bsendmsg(ua, _("Improper date format.\n")); + } + bstrncpy(date, ua->cmd, date_len); + return 1; +} + +static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date) { FILE *ffd; char file[5000]; @@ -490,14 +544,14 @@ static void insert_one_file(UAContext *ua, RESTORE_CTX *rx) } while (fgets(file, sizeof(file), ffd)) { line++; - if (!insert_file_into_findex_list(ua, rx, file)) { + if (!insert_file_into_findex_list(ua, rx, file, date)) { bsendmsg(ua, _("Error occurred on line %d of %s\n"), line, p); } } fclose(ffd); break; default: - insert_file_into_findex_list(ua, rx, ua->cmd); + insert_file_into_findex_list(ua, rx, ua->cmd, date); break; } } @@ -507,12 +561,14 @@ static void insert_one_file(UAContext *ua, RESTORE_CTX *rx) * lookup the most recent backup in the catalog to get the JobId * and FileIndex, then insert them into the findex list. */ -static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file) +static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, + char *date) { strip_trailing_junk(file); split_path_and_filename(rx, file); - Mmsg(&rx->query, uar_jobid_fileindex, rx->path, rx->fname, rx->ClientName); + Mmsg(&rx->query, uar_jobid_fileindex, date, rx->path, rx->fname, rx->ClientName); rx->found = false; + /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { bsendmsg(ua, _("Query failed: %s. ERR=%s\n"), rx->query, db_strerror(ua->db)); @@ -718,7 +774,7 @@ static int select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date bsendmsg(ua, "%s\n", db_strerror(ua->db)); goto bail_out; } - /* Note, this is needed as I don't seem to get the callback + /* Note, this is needed because I don't seem to get the callback * from the call just above. */ rx->JobTDate = 0; @@ -891,6 +947,7 @@ static void free_name_list(NAME_LIST *name_list) } if (name_list->name) { free(name_list->name); + name_list->name = NULL; } name_list->max_ids = 0; name_list->num_ids = 0; diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 9a4a559dce..eaef046732 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -44,15 +44,17 @@ extern struct s_kw ReplaceOptions[]; * run jobid=nn * */ -int runcmd(UAContext *ua, char *cmd) +int run_cmd(UAContext *ua, char *cmd) { JCR *jcr; char *job_name, *level_name, *jid, *store_name, *pool_name; char *where, *fileset_name, *client_name, *bootstrap, *replace; - char *when; + char *when, *verify_job_name; int Priority = 0; - int i, j, found, opt; + int i, j, opt; + bool found; JOB *job = NULL; + JOB *verify_job = NULL; STORE *store = NULL; CLIENT *client = NULL; FILESET *fileset = NULL; @@ -71,9 +73,12 @@ int runcmd(UAContext *ua, char *cmd) N_("when"), N_("priority"), N_("yes"), /* 12 -- if you change this change YES_POS too */ + N_("run"), /* 13 -- if you change this change RUN_POS too */ + N_("verifyjob"), NULL}; #define YES_POS 12 +#define RUN_POS 13 if (!open_db(ua)) { return 1; @@ -90,14 +95,15 @@ int runcmd(UAContext *ua, char *cmd) fileset_name = NULL; bootstrap = NULL; replace = NULL; + verify_job_name = NULL; for (i=1; iargc; i++) { - found = False; + found = false; Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]); for (j=0; !found && kw[j]; j++) { if (strcasecmp(ua->argk[i], _(kw[j])) == 0) { - /* Note, yes has no value, so do not err */ - if (!ua->argv[i] && j != YES_POS /*yes*/) { + /* Note, yes and run have no value, so do not err */ + if (!ua->argv[i] && (j != YES_POS /*yes*/ && j != RUN_POS)) { bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]); return 1; } @@ -109,7 +115,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } job_name = ua->argv[i]; - found = True; + found = true; break; case 1: /* JobId */ if (jid) { @@ -117,7 +123,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } jid = ua->argv[i]; - found = True; + found = true; break; case 2: /* client */ if (client_name) { @@ -125,7 +131,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } client_name = ua->argv[i]; - found = True; + found = true; break; case 3: /* fileset */ if (fileset_name) { @@ -133,7 +139,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } fileset_name = ua->argv[i]; - found = True; + found = true; break; case 4: /* level */ if (level_name) { @@ -141,7 +147,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } level_name = ua->argv[i]; - found = True; + found = true; break; case 5: /* storage */ if (store_name) { @@ -149,7 +155,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } store_name = ua->argv[i]; - found = True; + found = true; break; case 6: /* pool */ if (pool_name) { @@ -157,7 +163,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } pool_name = ua->argv[i]; - found = True; + found = true; break; case 7: /* where */ if (where) { @@ -165,7 +171,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } where = ua->argv[i]; - found = True; + found = true; break; case 8: /* bootstrap */ if (bootstrap) { @@ -173,7 +179,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } bootstrap = ua->argv[i]; - found = True; + found = true; break; case 9: /* replace */ if (replace) { @@ -181,7 +187,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } replace = ua->argv[i]; - found = True; + found = true; break; case 10: /* When */ if (when) { @@ -189,7 +195,7 @@ int runcmd(UAContext *ua, char *cmd) return 1; } when = ua->argv[i]; - found = True; + found = true; break; case 11: /* Priority */ if (Priority) { @@ -203,8 +209,18 @@ int runcmd(UAContext *ua, char *cmd) } break; case 12: /* yes */ - found = True; + case 13: /* run */ + found = true; break; + case 14: /* Verify Job */ + if (verify_job_name) { + bsendmsg(ua, _("Verify Job specified twice.\n")); + return 1; + } + verify_job_name = ua->argv[i]; + found = true; + break; + default: break; } @@ -297,6 +313,15 @@ int runcmd(UAContext *ua, char *cmd) return 1; } + 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); + verify_job = select_job_resource(ua); + } + } else { + verify_job = job->verify_job; + } /* Create JCR to run job */ jcr = new_jcr(sizeof(JCR), dird_free_jcr); @@ -396,6 +421,32 @@ Priority: %d\n"), } } level_name = NULL; + if (jcr->JobType == JT_BACKUP) { + bsendmsg(ua, _("Run %s job\n\ +JobName: %s\n\ +FileSet: %s\n\ +Level: %s\n\ +Client: %s\n\ +Storage: %s\n\ +Pool: %s\n\ +When: %s\n\ +Priority: %d\n"), + _("Backup"), + job->hdr.name, + jcr->fileset->hdr.name, + level_to_str(jcr->JobLevel), + jcr->client->hdr.name, + jcr->store->hdr.name, + NPRT(jcr->pool->hdr.name), + bstrutime(dt, sizeof(dt), jcr->sched_time), + jcr->JobPriority); + } else { /* JT_VERIFY */ + char *Name; + if (jcr->job->verify_job) { + Name = jcr->job->verify_job->hdr.name; + } else { + Name = ""; + } bsendmsg(ua, _("Run %s job\n\ JobName: %s\n\ FileSet: %s\n\ @@ -403,17 +454,20 @@ Level: %s\n\ Client: %s\n\ Storage: %s\n\ Pool: %s\n\ +Verify Job: %s\n\ When: %s\n\ Priority: %d\n"), - jcr->JobType==JT_BACKUP?_("Backup"):_("Verify"), + _("Verify"), job->hdr.name, jcr->fileset->hdr.name, level_to_str(jcr->JobLevel), jcr->client->hdr.name, jcr->store->hdr.name, NPRT(jcr->pool->hdr.name), + Name, bstrutime(dt, sizeof(dt), jcr->sched_time), jcr->JobPriority); + } break; case JT_RESTORE: if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) { @@ -513,6 +567,9 @@ Priority: %d\n"), if (jcr->JobType == JT_BACKUP || jcr->JobType == JT_VERIFY) { add_prompt(ua, _("Pool")); /* 7 */ + if (jcr->JobType == JT_VERIFY) { + add_prompt(ua, _("Verify Job")); /* 8 */ + } } else if (jcr->JobType == JT_RESTORE) { add_prompt(ua, _("Bootstrap")); /* 7 */ add_prompt(ua, _("Where")); /* 8 */ @@ -554,6 +611,7 @@ Priority: %d\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: @@ -566,6 +624,9 @@ Priority: %d\n"), jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG; break; case 3: + jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG; + break; + case 4: jcr->JobLevel = L_VERIFY_DATA; break; default: @@ -636,6 +697,7 @@ Priority: %d\n"), } goto try_again; case 7: + /* Pool or Bootstrap depending on JobType */ if (jcr->JobType == JT_BACKUP || jcr->JobType == JT_VERIFY) { /* Pool */ pool = select_pool_resource(ua); @@ -668,6 +730,16 @@ Priority: %d\n"), } goto try_again; case 8: + /* Verify Job */ + if (jcr->JobType == JT_VERIFY) { + JOB *job = select_job_resource(ua); + if (job) { + jcr->job->verify_job = job; + } else { + jcr->job->verify_job = NULL; + } + goto try_again; + } /* Where */ if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) { break; diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index f3afec0d05..3bef0d2bcf 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -84,6 +84,12 @@ int find_arg_keyword(UAContext *ua, char **list) return -1; } +/* + * Given one keyword, find the first one that + * is in the argument list. + * Returns: argk index (always gt 0) + * -1 if not found + */ int find_arg(UAContext *ua, char *keyword) { for (int i=1; iargc; i++) { @@ -341,7 +347,7 @@ int select_client_dbr(UAContext *ua, CLIENT_DBR *cr) return 0; } if (num_clients <= 0) { - bsendmsg(ua, _("No clients defined. Run a job to create one.\n")); + bsendmsg(ua, _("No clients defined. You must run a job before using this command.\n")); return 0; } diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 44ca5bac40..cc1faa66d0 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -202,7 +202,7 @@ static void do_director_status(UAContext *ua, char *cmd) bsendmsg(ua, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs, last_job.NumJobs == 1 ? "" : "s"); if (last_job.NumJobs > 0) { - char termstat[30]; + char termstat[50]; bstrftime(dt, sizeof(dt), last_job.end_time); bsendmsg(ua, _("Last Job %s finished at %s\n"), last_job.Job, dt); @@ -238,6 +238,15 @@ static void do_director_status(UAContext *ua, char *cmd) case JS_ErrorTerminated: msg = _("has erred"); break; + case JS_Error: + msg = _("has errors"); + break; + case JS_FatalError: + msg = _("has a fatal error"); + break; + case JS_Differences: + msg = _("has verify differences"); + break; case JS_Canceled: msg = _("has been canceled"); break; @@ -260,16 +269,15 @@ static void do_director_status(UAContext *ua, char *cmd) case JS_WaitJobRes: msg = _("is waiting on max Job jobs"); break; - case JS_WaitPriority: - msg = _("is waiting for higher priority jobs to finish"); - break; case JS_WaitMaxJobs: msg = _("is waiting on max total jobs"); break; case JS_WaitStartTime: msg = _("is waiting for its start time"); break; - + case JS_WaitPriority: + msg = _("is waiting for higher priority jobs to finish"); + break; default: msg = (char *) get_pool_memory(PM_FNAME); @@ -433,103 +441,29 @@ static void prt_runtime(UAContext *ua, JOB *job, int level, time_t runtime, POOL */ static void print_jobs_scheduled(UAContext *ua) { - time_t now, runtime, tomorrow; + time_t runtime; RUN *run; JOB *job; - SCHED *sched; - struct tm tm; - int mday, wday, month, wpos, tmday, twday, tmonth, twpos, i, hour; - int tod, tom; - int found; - int hdr_printed = FALSE; + bool hdr_printed = false; int level; Dmsg0(200, "enter find_runs()\n"); - now = time(NULL); - localtime_r(&now, &tm); - mday = tm.tm_mday - 1; - wday = tm.tm_wday; - month = tm.tm_mon; - wpos = (tm.tm_mday - 1) / 7; - - tomorrow = now + 60 * 60 * 24; - localtime_r(&tomorrow, &tm); - tmday = tm.tm_mday - 1; - twday = tm.tm_wday; - tmonth = tm.tm_mon; - twpos = (tm.tm_mday - 1) / 7; - /* Loop through all jobs */ LockRes(); for (job=NULL; (job=(JOB *)GetNextRes(R_JOB, (RES *)job)); ) { + for (run=NULL; (run = find_next_run(run, job, runtime)); ) { level = job->level; - sched = job->schedule; - if (sched == NULL) { /* scheduled? */ - continue; /* no, skip this job */ + if (run->level) { + level = run->level; + } + if (!hdr_printed) { + hdr_printed = true; + prt_runhdr(ua); + } + prt_runtime(ua, job, level, runtime, run->pool); } - for (run=sched->run; run; run=run->next) { - if (run->level) { - level = run->level; - } - /* - * Find runs in next 24 hours - */ - tod = (bit_is_set(mday, run->mday) || bit_is_set(wday, run->wday)) && - bit_is_set(month, run->month) && bit_is_set(wpos, run->wpos); - - tom = (bit_is_set(tmday, run->mday) || bit_is_set(twday, run->wday)) && - bit_is_set(tmonth, run->month) && bit_is_set(wpos, run->wpos); - - Dmsg2(200, "tod=%d tom=%d\n", tod, tom); - found = FALSE; - if (tod) { /* Jobs scheduled today (next 24 hours) */ - /* find time (time_t) job is to be run */ - localtime_r(&now, &tm); - hour = 0; - for (i=tm.tm_hour; i < 24; i++) { - if (bit_is_set(i, run->hour)) { - tm.tm_hour = i; - tm.tm_min = run->minute; - tm.tm_sec = 0; - runtime = mktime(&tm); - if (runtime > now) { - if (!hdr_printed) { - hdr_printed = TRUE; - prt_runhdr(ua); - } - prt_runtime(ua, job, level, runtime, run->pool); - found = TRUE; - break; - } - } - } - } -// Dmsg2(200, "runtime=%d now=%d\n", runtime, now); - if (!found && tom) { /* look at jobs scheduled tomorrow */ - localtime_r(&tomorrow, &tm); - hour = 0; - for (i=0; i < 24; i++) { - if (bit_is_set(i, run->hour)) { - hour = i; - break; - } - } - tm.tm_hour = hour; - tm.tm_min = run->minute; - tm.tm_sec = 0; - runtime = mktime(&tm); - Dmsg2(200, "truntime=%d now=%d\n", runtime, now); - if (runtime < tomorrow) { - if (!hdr_printed) { - hdr_printed = TRUE; - prt_runhdr(ua); - } - prt_runtime(ua, job, level, runtime, run->pool); - } - } - } /* end for loop over runs */ } /* end for loop over resources */ UnlockRes(); Dmsg0(200, "Leave find_runs()\n"); diff --git a/bacula/src/dird/ua_tree.c b/bacula/src/dird/ua_tree.c index 29db4a832d..240d782773 100644 --- a/bacula/src/dird/ua_tree.c +++ b/bacula/src/dird/ua_tree.c @@ -163,7 +163,7 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) new_node->FileIndex = atoi(row[2]); new_node->JobId = atoi(row[3]); new_node->type = type; - new_node->extract = 1; /* extract all by default */ + new_node->extract = true; /* extract all by default */ tree->cnt++; return 0; } @@ -174,19 +174,19 @@ int insert_tree_handler(void *ctx, int num_fields, char **row) * down the tree setting all children if the * node is a directory. */ -static void set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, int value) +static void set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, bool extract) { TREE_NODE *n; FILE_DBR fdbr; struct stat statp; - node->extract = value; + node->extract = extract; /* For a non-file (i.e. directory), we see all the children */ if (node->type != TN_FILE) { for (n=node->child; n; n=n->sibling) { - set_extract(ua, n, tree, value); + set_extract(ua, n, tree, extract); } - } else if (value) { + } else if (extract) { char cwd[2000]; /* Ordinary file, we get the full path, look up the * attributes, decode them, and if we are hard linked to @@ -195,7 +195,7 @@ static void set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, int valu tree_getpath(node, cwd, sizeof(cwd)); fdbr.FileId = 0; fdbr.JobId = node->JobId; - if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, &fdbr)) { + if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) { int32_t LinkFI; decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */ /* @@ -206,7 +206,7 @@ static void set_extract(UAContext *ua, TREE_NODE *node, TREE_CTX *tree, int valu if (LinkFI) { for (n=first_tree_node(tree->root); n; n=next_tree_node(n)) { if (n->FileIndex == LinkFI && n->JobId == node->JobId) { - n->extract = 1; + n->extract = true; break; } } @@ -226,7 +226,7 @@ static int markcmd(UAContext *ua, TREE_CTX *tree) } for (node = tree->node->child; node; node=node->sibling) { if (fnmatch(ua->argk[1], node->fname, 0) == 0) { - set_extract(ua, node, tree, 1); + set_extract(ua, node, tree, true); } } return 1; @@ -234,18 +234,18 @@ static int markcmd(UAContext *ua, TREE_CTX *tree) static int countcmd(UAContext *ua, TREE_CTX *tree) { - int total, extract; + int total, num_extract; - total = extract = 0; + total = num_extract = 0; for (TREE_NODE *node=first_tree_node(tree->root); node; node=next_tree_node(node)) { if (node->type != TN_NEWDIR) { total++; if (node->extract) { - extract++; + num_extract++; } } } - bsendmsg(ua, "%d total files. %d marked for restoration.\n", total, extract); + bsendmsg(ua, "%d total files. %d marked for restoration.\n", total, num_extract); return 1; } @@ -293,7 +293,7 @@ extern char *getgroup(gid_t gid); /* * This is actually the long form used for "dir" */ -static void ls_output(char *buf, char *fname, int extract, struct stat *statp) +static void ls_output(char *buf, char *fname, bool extract, struct stat *statp) { char *p, *f; char ec1[30]; @@ -338,7 +338,7 @@ static int dircmd(UAContext *ua, TREE_CTX *tree) tree_getpath(node, cwd, sizeof(cwd)); fdbr.FileId = 0; fdbr.JobId = node->JobId; - if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, &fdbr)) { + if (db_get_file_attributes_record(ua->jcr, ua->db, cwd, NULL, &fdbr)) { int32_t LinkFI; decode_stat(fdbr.LStat, &statp, &LinkFI); /* decode stat pkt */ ls_output(buf, cwd, node->extract, &statp); @@ -421,7 +421,7 @@ static int unmarkcmd(UAContext *ua, TREE_CTX *tree) } for (node = tree->node->child; node; node=node->sibling) { if (fnmatch(ua->argk[1], node->fname, 0) == 0) { - set_extract(ua, node, tree, 0); + set_extract(ua, node, tree, false); } } return 1; diff --git a/bacula/src/dird/verify.c b/bacula/src/dird/verify.c index 40faac1e41..54fb9073af 100644 --- a/bacula/src/dird/verify.c +++ b/bacula/src/dird/verify.c @@ -64,26 +64,41 @@ static int missing_handler(void *ctx, int num_fields, char **row); */ int do_verify(JCR *jcr) { - char *level; + char *level, *Name; BSOCK *fd; - JOB_DBR jr; - JobId_t JobId = 0; + JOB_DBR jr, verify_jr; + JobId_t verify_jobid = 0; int stat; + memset(&verify_jr, 0, sizeof(verify_jr)); + 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); - /* If we are doing a verify from the catalog, - * we must look up the time and date of the - * last full verify. + /* + * Find JobId of last job that ran. E.g. + * for VERIFY_CATALOG we want the JobId of the last INIT. + * for VERIFY_VOLUME_TO_CATALOG, we want the JobId of the + * last backup Job. */ if (jcr->JobLevel == L_VERIFY_CATALOG || - jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { + jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG || + jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) { memcpy(&jr, &jcr->jr, sizeof(jr)); - if (!db_find_last_jobid(jcr, jcr->db, &jr)) { + if (jcr->job->verify_job && + (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG || + jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG)) { + Name = jcr->job->verify_job->hdr.name; + } else { + Name = NULL; + } + Dmsg1(100, "find last jobid for: %s\n", NPRT(Name)); + if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) { if (jcr->JobLevel == L_VERIFY_CATALOG) { Jmsg(jcr, M_FATAL, 0, _( "Unable to find JobId of previous InitCatalog Job.\n" @@ -95,8 +110,8 @@ int do_verify(JCR *jcr) } goto bail_out; } - JobId = jr.JobId; - Dmsg1(20, "Last full id=%d\n", JobId); + verify_jobid = jr.JobId; + Dmsg1(100, "Last full jobid=%d\n", verify_jobid); } jcr->jr.JobId = jcr->JobId; @@ -111,28 +126,30 @@ int do_verify(JCR *jcr) jcr->fname = get_pool_memory(PM_FNAME); } - jcr->jr.JobId = JobId; /* save target JobId */ - /* Print Job Start message */ Jmsg(jcr, M_INFO, 0, _("Start Verify JobId %d Job=%s\n"), jcr->JobId, jcr->Job); + /* + * Now get the job record for the previous backup that interests + * us. We use the verify_jobid that we found above. + */ if (jcr->JobLevel == L_VERIFY_CATALOG || - jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { - memset(&jr, 0, sizeof(jr)); - jr.JobId = JobId; - if (!db_get_job_record(jcr, jcr->db, &jr)) { + jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG || + jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG) { + verify_jr.JobId = verify_jobid; + if (!db_get_job_record(jcr, jcr->db, &verify_jr)) { Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"), db_strerror(jcr->db)); goto bail_out; } - if (jr.JobStatus != 'T') { + if (verify_jr.JobStatus != 'T') { Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"), - JobId, jr.JobStatus); + verify_jobid, verify_jr.JobStatus); goto bail_out; } Jmsg(jcr, M_INFO, 0, _("Verifying against JobId=%d Job=%s\n"), - JobId, jr.Job); + verify_jr.JobId, verify_jr.Job); } /* @@ -144,12 +161,12 @@ int do_verify(JCR *jcr) if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { RBSR *bsr = new_bsr(); UAContext *ua; - bsr->JobId = jr.JobId; + bsr->JobId = verify_jr.JobId; ua = new_ua_context(jcr); complete_bsr(ua, bsr); bsr->fi = new_findex(); bsr->fi->findex = 1; - bsr->fi->findex2 = jr.JobFiles; + bsr->fi->findex2 = verify_jr.JobFiles; if (!write_bsr_file(ua, bsr)) { free_ua_context(ua); free_bsr(bsr); @@ -188,6 +205,12 @@ int do_verify(JCR *jcr) } else { jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */ } + + if (jcr->JobLevel == L_VERIFY_DISK_TO_CATALOG && jcr->job->verify_job) { + jcr->fileset = jcr->job->verify_job->fileset; + } + Dmsg2(100, "ClientId=%u JobLevel=%c\n", verify_jr.ClientId, jcr->JobLevel); + /* * OK, now connect to the File daemon * and ask him for the files. @@ -200,6 +223,7 @@ int do_verify(JCR *jcr) set_jcr_job_status(jcr, JS_Running); fd = jcr->file_bsock; + Dmsg0(30, ">filed: Send include list\n"); if (!send_include_list(jcr)) { goto bail_out; @@ -262,6 +286,9 @@ int do_verify(JCR *jcr) case L_VERIFY_DATA: level = "data"; break; + case L_VERIFY_DISK_TO_CATALOG: + level="disk_to_catalog"; + break; default: Jmsg1(jcr, M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->JobLevel); goto bail_out; @@ -290,12 +317,19 @@ int do_verify(JCR *jcr) Dmsg0(10, "Verify level=catalog\n"); jcr->sd_msg_thread_done = true; /* no SD msg thread, so it is done */ jcr->SDJobStatus = JS_Terminated; - get_attributes_and_compare_to_catalog(jcr, JobId); + get_attributes_and_compare_to_catalog(jcr, verify_jobid); break; case L_VERIFY_VOLUME_TO_CATALOG: Dmsg0(10, "Verify level=volume\n"); - get_attributes_and_compare_to_catalog(jcr, JobId); + get_attributes_and_compare_to_catalog(jcr, verify_jobid); + break; + + case L_VERIFY_DISK_TO_CATALOG: + Dmsg0(10, "Verify level=disk_to_catalog\n"); + jcr->sd_msg_thread_done = true; /* no SD msg thread, so it is done */ + jcr->SDJobStatus = JS_Terminated; + get_attributes_and_compare_to_catalog(jcr, verify_jobid); break; case L_VERIFY_INIT: @@ -312,7 +346,6 @@ int do_verify(JCR *jcr) } stat = wait_for_job_termination(jcr); - verify_cleanup(jcr, stat); return 1; @@ -333,6 +366,7 @@ static void verify_cleanup(JCR *jcr, int TermCode) char *term_msg; int msg_type; JobId_t JobId; + char *Name; // Dmsg1(000, "Enter verify_cleanup() TermCod=%d\n", TermCode); @@ -358,11 +392,17 @@ static void verify_cleanup(JCR *jcr, int TermCode) break; default: term_msg = term_code; - sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode); + bsnprintf(term_code, sizeof(term_code), + _("Inappropriate term code: %d %c\n"), TermCode, TermCode); break; } bstrftime(sdt, sizeof(sdt), jcr->jr.StartTime); bstrftime(edt, sizeof(edt), jcr->jr.EndTime); + if (jcr->job->verify_job) { + Name = jcr->job->verify_job->hdr.name; + } else { + Name = ""; + } jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg)); if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) { @@ -373,6 +413,8 @@ Job: %s\n\ FileSet: %s\n\ Verify Level: %s\n\ Client: %s\n\ +Verify JobId: %d\n\ +Verify Job: %s\n\ Start time: %s\n\ End time: %s\n\ Files Examined: %s\n\ @@ -386,6 +428,8 @@ Termination: %s\n\n"), jcr->fileset->hdr.name, level_to_str(jcr->JobLevel), jcr->client->hdr.name, + jcr->verify_jr->JobId, + Name, sdt, edt, edit_uint64_with_commas(jcr->JobFiles, ec1), @@ -400,6 +444,8 @@ Job: %s\n\ FileSet: %s\n\ Verify Level: %s\n\ Client: %s\n\ +Verify JobId: %d\n\ +Verify Job: %s\n\ Start time: %s\n\ End time: %s\n\ Files Examined: %s\n\ @@ -412,6 +458,8 @@ Termination: %s\n\n"), jcr->fileset->hdr.name, level_to_str(jcr->JobLevel), jcr->client->hdr.name, + jcr->verify_jr->JobId, + Name, sdt, edt, edit_uint64_with_commas(jcr->JobFiles, ec1), @@ -465,7 +513,7 @@ int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId) fname = check_pool_memory_size(fname, fd->msglen); jcr->fname = check_pool_memory_size(jcr->fname, fd->msglen); - Dmsg1(400, "Atts+SIG=%s\n", fd->msg); + Dmsg1(200, "Atts+SIG=%s\n", fd->msg); if ((len = sscanf(fd->msg, "%ld %d %100s", &file_index, &stream, fname)) != 3) { Jmsg3(jcr, M_FATAL, 0, _("birddb, jcr->fname, &fdbr)) { + if (!db_get_file_attributes_record(jcr, jcr->db, jcr->fname, + jcr->verify_jr, &fdbr)) { Jmsg(jcr, M_INFO, 0, _("New file: %s\n"), jcr->fname); Dmsg1(020, _("File not in catalog: %s\n"), jcr->fname); stat = JS_Differences; diff --git a/bacula/src/filed/.cvsignore b/bacula/src/filed/.cvsignore index f97f16974f..9edec26956 100644 --- a/bacula/src/filed/.cvsignore +++ b/bacula/src/filed/.cvsignore @@ -7,3 +7,4 @@ host.h startit static-bacula-fd stopit +filed.conf diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index e79f6142bd..58531ffd36 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -307,7 +307,7 @@ static int estimate_cmd(JCR *jcr) } make_estimate(jcr); bnet_fsend(dir, OKest, jcr->num_files_examined, - edit_uint64(jcr->JobBytes, ed2)); + edit_uint64_with_commas(jcr->JobBytes, ed2)); bnet_sig(dir, BNET_EOD); return 1; } @@ -843,6 +843,8 @@ static int verify_cmd(JCR *jcr) jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG; } else if (strcasecmp(level, "data") == 0){ jcr->JobLevel = L_VERIFY_DATA; + } else if (strcasecmp(level, "disk_to_catalog") == 0) { + jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG; } else { bnet_fsend(dir, "2994 Bad verify level: %s\n", dir->msg); return 0; @@ -875,6 +877,9 @@ static int verify_cmd(JCR *jcr) /* Inform Storage daemon that we are done */ bnet_sig(sd, BNET_TERMINATE); + break; + case L_VERIFY_DISK_TO_CATALOG: + do_verify(jcr); break; default: bnet_fsend(dir, "2994 Bad verify level: %s\n", dir->msg); @@ -1049,6 +1054,7 @@ static void filed_free_jcr(JCR *jcr) if (jcr->RestoreBootstrap) { unlink(jcr->RestoreBootstrap); free_pool_memory(jcr->RestoreBootstrap); + jcr->RestoreBootstrap = NULL; } if (jcr->last_fname) { free_pool_memory(jcr->last_fname); @@ -1096,6 +1102,7 @@ static int send_bootstrap_file(JCR *jcr) char buf[2000]; BSOCK *sd = jcr->store_bsock; char *bootstrap = "bootstrap\n"; + int stat = 0; Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap); if (!jcr->RestoreBootstrap) { @@ -1106,7 +1113,7 @@ static int send_bootstrap_file(JCR *jcr) Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), jcr->RestoreBootstrap, strerror(errno)); set_jcr_job_status(jcr, JS_ErrorTerminated); - return 0; + goto bail_out; } pm_strcpy(&sd->msg, bootstrap); sd->msglen = strlen(sd->msg); @@ -1119,7 +1126,16 @@ static int send_bootstrap_file(JCR *jcr) fclose(bs); if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) { set_jcr_job_status(jcr, JS_ErrorTerminated); - return 0; + goto bail_out; } - return 1; + stat = 1; + +bail_out: + if (jcr->RestoreBootstrap) { + unlink(jcr->RestoreBootstrap); + free_pool_memory(jcr->RestoreBootstrap); + jcr->RestoreBootstrap = NULL; + } + + return stat; } diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 068306b060..b7bb63320a 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -33,6 +33,7 @@ static char rec_header[] = "rechdr %ld %ld %ld %ld %ld"; /* Forward referenced functions */ +static char *zlib_strerror(int stat); #define RETRY 10 /* retry wait time */ @@ -47,7 +48,7 @@ void do_restore(JCR *jcr) uint32_t size; uint32_t VolSessionId, VolSessionTime; int32_t file_index; - int extract = FALSE; + bool extract = false; BFILE bfd; int stat; uint32_t total = 0; /* Job total but only 32 bits for debug */ @@ -125,7 +126,7 @@ void do_restore(JCR *jcr) Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n")); } set_attributes(jcr, attr, &bfd); - extract = FALSE; + extract = false; Dmsg0(30, "Stop extracting.\n"); } @@ -157,14 +158,14 @@ void do_restore(JCR *jcr) jcr->num_files_examined++; Dmsg1(30, "Outfile=%s\n", attr->ofname); - extract = FALSE; + extract = false; stat = create_file(jcr, attr, &bfd, jcr->replace); switch (stat) { case CF_ERROR: case CF_SKIP: break; case CF_EXTRACT: - extract = TRUE; + extract = true; P(jcr->mutex); pm_strcpy(&jcr->last_fname, attr->ofname); V(jcr->mutex); @@ -206,7 +207,8 @@ void do_restore(JCR *jcr) if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd)); - extract = FALSE; + extract = false; + bclose(&bfd); continue; } } @@ -218,7 +220,8 @@ void do_restore(JCR *jcr) if ((uint32_t)bwrite(&bfd, wbuf, wsize) != wsize) { Dmsg0(0, "===Write error===\n"); Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: ERR=%s\n"), attr->ofname, berror(&bfd)); - extract = FALSE; + extract = false; + bclose(&bfd); continue; } total += wsize; @@ -250,7 +253,8 @@ void do_restore(JCR *jcr) if (blseek(&bfd, (off_t)fileAddr, SEEK_SET) < 0) { Jmsg3(jcr, M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"), edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd)); - extract = FALSE; + extract = false; + bclose(&bfd); continue; } } @@ -262,8 +266,10 @@ void do_restore(JCR *jcr) Dmsg2(100, "Comp_len=%d msglen=%d\n", compress_len, wsize); if ((stat=uncompress((Byte *)jcr->compress_buf, &compress_len, (const Byte *)wbuf, (uLong)wsize)) != Z_OK) { - Jmsg(jcr, M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat); - extract = FALSE; + Jmsg(jcr, M_ERROR, 0, _("Uncompression error on file %s. ERR=%s\n"), + attr->ofname, zlib_strerror(stat)); + extract = false; + bclose(&bfd); continue; } @@ -271,7 +277,8 @@ void do_restore(JCR *jcr) if ((uLong)bwrite(&bfd, jcr->compress_buf, compress_len) != compress_len) { Dmsg0(0, "===Write error===\n"); Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, berror(&bfd)); - extract = FALSE; + extract = false; + bclose(&bfd); continue; } total += compress_len; @@ -282,7 +289,8 @@ void do_restore(JCR *jcr) #else if (extract) { Jmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n")); - extract = FALSE; + extract = false; + bclose(&bfd); continue; } #endif @@ -308,7 +316,7 @@ void do_restore(JCR *jcr) Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open but is not.\n")); } set_attributes(jcr, attr, &bfd); - extract = FALSE; + extract = false; } Jmsg(jcr, M_ERROR, 0, _("Unknown stream=%d ignored. This shouldn't happen!\n"), stream); Dmsg2(0, "None of above!!! stream=%d data=%s\n", stream,sd->msg); @@ -333,6 +341,7 @@ ok_out: free(jcr->compress_buf); jcr->compress_buf = NULL; } + bclose(&bfd); free_attr(attr); Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles, jcr->JobBytes); @@ -341,3 +350,29 @@ ok_out: non_support_data, non_support_attr); } } + +/* + * Convert ZLIB error code into an ASCII message + */ +static char *zlib_strerror(int stat) +{ + if (stat >= 0) { + return "None"; + } + switch (stat) { + case Z_ERRNO: + return "Zlib errno"; + case Z_STREAM_ERROR: + return "Zlib stream error"; + case Z_DATA_ERROR: + return "Zlib data error"; + case Z_MEM_ERROR: + return "Zlib memory error"; + case Z_BUF_ERROR: + return "Zlib buffer error"; + case Z_VERSION_ERROR: + return "Zlib version error"; + default: + return "*none*"; + } +} diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index bd5ac212e0..cf414d6320 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -119,7 +119,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) return 1; case FT_DIRNOCHG: case FT_NOCHG: - Jmsg(jcr, M_INFO, -1, _(" Unchanged file skipped: %s\n"), ff_pkt->fname); + Jmsg(jcr, M_SKIPPED, -1, _(" Unchanged file skipped: %s\n"), ff_pkt->fname); return 1; case FT_ISARCH: Jmsg(jcr, M_SKIPPED, -1, _(" Archive file skipped: %s\n"), ff_pkt->fname); @@ -178,6 +178,11 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0); + } else if (ff_pkt->type == FT_DIR) { + /* Here link is the canonical filename (i.e. with trailing slash) */ + stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles, + STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link, + 0, attribs, 0, 0); } else { stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, @@ -192,13 +197,14 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) return 0; } - /* If file opened, compute MD5 */ + /* If file opened, compute MD5 or SHA1 hash */ if (is_bopen(&bfd) && ff_pkt->flags & FO_MD5) { char MD5buf[40]; /* 24 should do */ MD5Init(&md5c); while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) { MD5Update(&md5c, ((unsigned char *) jcr->big_buf), n); jcr->JobBytes += n; + jcr->ReadBytes += n; } if (n < 0) { Jmsg(jcr, M_ERROR, -1, _("Error reading file %s: ERR=%s\n"), @@ -218,6 +224,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt) while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) { SHA1Update(&sha1c, ((unsigned char *) jcr->big_buf), n); jcr->JobBytes += n; + jcr->ReadBytes += n; } if (n < 0) { Jmsg(jcr, M_ERROR, -1, _("Error reading file %s: ERR=%s\n"), diff --git a/bacula/src/filed/win32/bin/README.txt b/bacula/src/filed/win32/bin/README.txt index 08ab12edd8..cefbf6b158 100644 --- a/bacula/src/filed/win32/bin/README.txt +++ b/bacula/src/filed/win32/bin/README.txt @@ -3,7 +3,7 @@ This is the binary distribution of Bacula for Win32 -systems (Win95, Win98, WinMe, WinNT, and Win2000). +systems (Win95, Win98, WinMe, WinXP, WinNT, and Win2000). INSTALLATION @@ -13,7 +13,7 @@ To install it, please UnZip (or detar) the distribution file into your root directory on drive c:\ then follow the instructions in the online manual viewable by any Internet Browser (Netscape, Microsoft Internet Explorer). -See http://www.bacula.net/htm-manual +See http://www.bacula.org/rel-manual/index.html or get the source release Bacula (tm) is released under the GPL license (given below). @@ -41,4 +41,3 @@ cygwin can be found at http://www.cygwin.com MA 02111-1307, USA. */ - diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c index 27d9254262..f0d65be64c 100755 --- a/bacula/src/findlib/attribs.c +++ b/bacula/src/findlib/attribs.c @@ -241,6 +241,7 @@ int set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) if (is_bopen(ofd)) { bclose(ofd); } + pm_strcpy(&attr->ofname, "*none*"); return 1; } @@ -249,6 +250,7 @@ int set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) if (is_bopen(ofd)) { bclose(ofd); } + pm_strcpy(&attr->ofname, "*none*"); return 1; } /* @@ -307,6 +309,7 @@ int set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) stat = 0; } } + pm_strcpy(&attr->ofname, "*none*"); umask(old_mask); return stat; } diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index 3f2c953900..2ade59f41f 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -477,14 +477,21 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) { bfd->fid = open(fname, flags, mode); bfd->berrno = errno; + Dmsg1(50, "Open file %d\n", bfd->fid); return bfd->fid; } int bclose(BFILE *bfd) { - int stat = close(bfd->fid); + int stat; + Dmsg1(50, "Close file %d\n", bfd->fid); + if (bfd->fid == -1) { + return 0; + } + stat = close(bfd->fid); bfd->berrno = errno; bfd->fid = -1; + return stat; } diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index 2900f998d9..766120df91 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -170,6 +170,9 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) mode |= O_CTG; /* set contiguous bit if needed */ } Dmsg1(50, "Create file: %s\n", attr->ofname); + if (is_bopen(bfd)) { + Jmsg1(jcr, M_ERROR, 0, "bpkt already open fid=%d\n", bfd->fid); + } if ((bopen(bfd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), attr->ofname, berror(bfd)); @@ -205,6 +208,9 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) } else { tid = NULL; } + if (is_bopen(bfd)) { + Jmsg1(jcr, M_ERROR, 0, "bpkt already open fid=%d\n", bfd->fid); + } if ((bopen(bfd, attr->ofname, mode, 0)) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), attr->ofname, berror(bfd)); @@ -248,6 +254,9 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) * and saved. */ if (!is_portable_backup(bfd)) { + if (is_bopen(bfd)) { + Jmsg1(jcr, M_ERROR, 0, "bpkt already open fid=%d\n", bfd->fid); + } if ((bopen(bfd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) { Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"), attr->ofname, berror(bfd)); diff --git a/bacula/src/gnome2-console/.cvsignore b/bacula/src/gnome2-console/.cvsignore index b8893fbd69..37844ba1f1 100644 --- a/bacula/src/gnome2-console/.cvsignore +++ b/bacula/src/gnome2-console/.cvsignore @@ -5,3 +5,4 @@ gnome-console.conf 1 2 3 +main.c diff --git a/bacula/src/gnome2-console/Makefile.in b/bacula/src/gnome2-console/Makefile.in new file mode 100644 index 0000000000..65beb83018 --- /dev/null +++ b/bacula/src/gnome2-console/Makefile.in @@ -0,0 +1,125 @@ +# +# Version $Id$ +# +@MCOMMON@ + +srcdir = . +VPATH = . +.PATH: . + +# one up +basedir = .. +# top dir +topdir = ../.. +# this dir relative to top dir +thisdir = src/gnome2-console + +DEBUG=@DEBUG@ + +first_rule: all +dummy: + +GNOME_INCLUDEDIR = @GNOME_INCLUDEDIR@ +GNOMEUI_LIBS = @GNOMEUI_LIBS@ +GNOME_LIBDIR = @GNOME_LIBDIR@ +GNOME_LIBS = @GNOME_LIBS@ + + +# +CONSSRCS = console.c console_conf.c authenticate.c support.c interface.c callbacks.c +CONSOBJS = console.o console_conf.o authenticate.o support.o interface.o callbacks.o + +# these are the objects that are changed by the .configure process +EXTRAOBJS = @OBJLIST@ + +#CONS_INC=@CONS_INC@ $(GNOME_INCLUDEDIR) +#CONS_LIBS=@CONS_LIBS@ $(GNOME_LIBS) +#CONS_LDFLAGS=@CONS_LDFLAGS@ $(GNOME_LIBDIR) $(GNOMEUI_LIBS) + +CONS_INC=$(GNOME_INCLUDEDIR) +CONS_LIBS=$(GNOME_LIBS) +CONS_LDFLAGS=$(GNOME_LIBDIR) $(GNOMEUI_LIBS) + + +.SUFFIXES: .c .o +.PHONY: +.DONTCARE: + +# inference rules +.c.o: + $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) $(CONS_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $< +#------------------------------------------------------------------------- +all: Makefile gnome-console @STATIC_CONS@ + @echo "==== Make of gnome-console is good ====" + @echo " " + +support.o: support.c + rm -f support.c.orig + mv support.c support.c.orig + sed "s%parent = g_object_get_data%parent = \(GtkWidget \*\)g_object_get_data%" support.c.orig >support.c + $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) $(CONS_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $< + +gnome-console: $(CONSOBJS) ../lib/libbac.a ../cats/libsql.a + $(CXX) $(LDFLAGS) $(CONS_LDFLAGS) -L../lib -L../cats -o $@ $(CONSOBJS) \ + $(LIBS) $(DLIB) $(CONS_LIBS) -lbac -lsql -lm + +static-console: static-gnome-console + +static-gnome-console: $(CONSOBJS) ../lib/libbac.a ../cats/libsql.a + $(CXX) $(LDFLAGS) $(CONS_LDFLAGS) -L../lib -L../cats -o $@ $(CONSOBJS) \ + $(LIBS) $(DLIB) $(CONS_LIBS) -lbac -lsql -lm + strip $@ + +Makefile: $(srcdir)/Makefile.in $(topdir)/config.status + cd $(topdir) \ + && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +clean: + @$(RMF) gnome-console core core.* a.out *.o *.bak *~ *.intpro *.extpro 1 2 3 + @$(RMF) static-gnome-console gmon.out + +realclean: clean + @$(RMF) tags + @$(RM) -rf .deps gnome-console.conf + +distclean: realclean + if test $(srcdir) = .; then $(MAKE) realclean; fi + (cd $(srcdir); $(RMF) Makefile; $(RMF) -r CVS) + +install: all + $(INSTALL_SCRIPT) gnome-console $(DESTDIR)$(sbindir)/gnome-console + @srcconf=gnome-console.conf; \ + if test -f ${DESTDIR}${sysconfdir}/$$srcconf; then \ + destconf=$$srcconf.new; \ + echo " ==> Found existing $$srcconf, installing new conf file as $$destconf"; \ + else \ + destconf=$$srcconf; \ + fi; \ + echo "${INSTALL_CONFIG} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf"; \ + ${INSTALL_CONFIG} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf + +uninstall: + (cd $(DESTDIR)$(sbindir); $(RMF) gnome-console) + (cd $(DESTDIR)$(sysconfdir); $(RMF) gnome-console.conf gnome-console.conf.new) + + + +# Semi-automatic generation of dependencies: +# Use gcc -MM because X11 `makedepend' doesn't work on all systems +# and it also includes system headers. +# `semi'-automatic since dependencies are generated at distribution time. + +depend: + @$(MV) Makefile Makefile.bak + @$(SED) "/^# DO NOT DELETE:/,$$ d" Makefile.bak > Makefile + @$(ECHO) "# DO NOT DELETE: nice dependency list follows" >> Makefile + @$(CC) -S -M $(CPPFLAGS) $(XINC) -I$(srcdir) -I$(basedir) $(GNOME_INCLUDEDIR) $(SQL_INC) *.c >> Makefile + @if test -f Makefile ; then \ + $(RMF) Makefile.bak; \ + else \ + $(MV) Makefile.bak Makefile; \ + echo -e "Something went wrong\n\a"; \ + fi + +# ----------------------------------------------------------------------- +# DO NOT DELETE: nice dependency list follows diff --git a/bacula/src/gnome2-console/authenticate.c b/bacula/src/gnome2-console/authenticate.c new file mode 100644 index 0000000000..3fe7a2f1be --- /dev/null +++ b/bacula/src/gnome2-console/authenticate.c @@ -0,0 +1,82 @@ +/* + * + * Bacula UA authentication. Provides authentication with + * the Director. + * + * Kern Sibbald, June MMI + * + * Version $Id$ + * + * This routine runs as a thread and must be thread reentrant. + * + * Basic tasks done here: + * + */ +/* + Copyright (C) 2000, 2001 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "bacula.h" +#include "console.h" + + +/* Commands sent to Director */ +static char hello[] = "Hello %s calling\n"; + +/* Response from Director */ +static char OKhello[] = "1000 OK:"; + +/* Forward referenced functions */ + +/* + * Authenticate Director + */ +int authenticate_director(JCR *jcr, DIRRES *director) +{ + BSOCK *dir = jcr->dir_bsock; + int ssl_need = BNET_SSL_NONE; + + /* + * Send my name to the Director then do authentication + */ + bnet_fsend(dir, hello, "UserAgent"); + + if (!cram_md5_get_auth(dir, director->password, ssl_need) || + !cram_md5_auth(dir, director->password, ssl_need)) { + printf(_("%s: Director authorization problem.\n"), my_name); + set_text(_("Director authorization problem.\n"), -1); + return 0; + } + + Dmsg1(6, ">dird: %s", dir->msg); + if (bnet_recv(dir) <= 0) { + set_textf(_("Bad response to Hello command: ERR=%s\n"), + bnet_strerror(dir)); + printf(_("%s: Bad response to Hello command: ERR=%s\n"), + my_name, bnet_strerror(dir)); + set_text(_("The Director is probably not running.\n"), -1); + return 0; + } + Dmsg1(10, "msg); + if (strncmp(dir->msg, OKhello, sizeof(OKhello)-1) != 0) { + set_text(_("Director rejected Hello command\n"), -1); + return 0; + } else { + set_text(dir->msg, dir->msglen); + } + return 1; +} diff --git a/bacula/src/gnome2-console/callbacks.c b/bacula/src/gnome2-console/callbacks.c new file mode 100644 index 0000000000..2d2f6544d6 --- /dev/null +++ b/bacula/src/gnome2-console/callbacks.c @@ -0,0 +1,504 @@ +/* + * Version $Id$ + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "bacula.h" +#include "console.h" + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define KEY_Enter 65293 +#define KEY_Up 65362 +#define KEY_Down 65364 +#define KEY_Left 65361 +#define KEY_Right 65363 + +gboolean +on_app1_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + gtk_main_quit(); + return FALSE; +} + +void +on_connect_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + if (connect_to_director(user_data)) { + start_director_reader(user_data); + } +} + + +void +on_disconnect_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + if (disconnect_from_director(user_data)) { + stop_director_reader(user_data); + } +} + + +void +on_exit_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_cut1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + +} + + +void +on_copy1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + +} + + +void +on_paste1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + +} + + +void +on_clear1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + +} + + +void +on_properties1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + +} + + +void +on_preferences1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ +} + + +void +on_about_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + gtk_widget_show(about1); + gtk_main(); +} + + +void +on_connect_button_clicked(GtkButton *button, gpointer user_data) +{ + if (connect_to_director(user_data)) { + start_director_reader(user_data); + } +} + +/* Define max length of history and how many to delete when it gets there. + * If you make HIST_DEL > HIST_MAX, you shoot yourself in the foot. + */ +#define HIST_MAX 2500 +#define HIST_DEL 500 + +static GList *hist = NULL; +static GList *hc = NULL; +static int hist_len = 0; + +static void add_to_history(gchar *ecmd) +{ + int len = strlen(ecmd); + + if (len > 0) { + hist = g_list_append(hist, bstrdup(ecmd)); + hist_len++; + } + if (hist_len >= HIST_MAX) { + int i; + GList *hp; + for (i=0; idata); + hist = g_list_remove(hist, hp->data); + } + hist_len -= HIST_DEL; + } + hc = NULL; +} + +/* + * Note, apparently there is a bug in GNOME where some of the + * key press events are lost -- at least it loses every other + * up arrow! + */ +gboolean +on_entry1_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + if (event->keyval == KEY_Enter) { + char *ecmd = (char *)gtk_entry_get_text((GtkEntry *)entry1); + set_text(ecmd, strlen(ecmd)); + set_text("\n", 1); + add_to_history(ecmd); + write_director(ecmd); + gtk_entry_set_text((GtkEntry *)entry1, ""); + } else if (event->keyval == KEY_Up) { + if (!hc) { + hc = g_list_last(hist); + } else { + hc = g_list_previous(hc); + } + if (!hc) { + hc = g_list_first(hist); + } + gtk_entry_set_text((GtkEntry *)entry1, (gchar *)hc->data); + } else if (event->keyval == KEY_Down) { + if (!hc) { + hc = g_list_first(hist); + } else { + hc = g_list_next(hc); + } + if (!hc) { + hc = g_list_last(hist); + } + gtk_entry_set_text((GtkEntry *)entry1, (gchar *)hc->data); + } +// gtk_entry_set_position((GtkEntry *)entry1, -1); +// gtk_window_set_focus((GtkWindow *)app1, entry1); + return FALSE; +} + + +void +on_app1_show(GtkWidget *widget, gpointer user_data) +{ +} + + + +void +on_msgs_button_clicked(GtkButton *button, gpointer user_data) +{ + write_director("messages"); +} + +void +on_msgs_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + write_director("messages"); +} + +void +on_about_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_hide(about1); + gtk_main_quit(); + set_status_ready(); +} + +void +on_select_director_OK_clicked(GtkButton *button, gpointer user_data) +{ + reply = OK; + gtk_widget_hide(dir_dialog); + gtk_main_quit(); + set_status_ready(); +} + + +void +on_select_director_cancel_clicked(GtkButton *button, gpointer user_data) +{ + reply = CANCEL; + gtk_widget_hide(dir_dialog); + gtk_main_quit(); + set_status_ready(); +} + +/* + * Compare list string items + */ +static gint compare_func(const void *data1, const void *data2) +{ + return strcmp((const char *)data1, (const char *)data2); +} + +static GList *find_combo_list(char *name) +{ + if (strcmp(name, "job") == 0) { + return job_list; + } + if (strcmp(name, "pool") == 0) { + return pool_list; + } + if (strcmp(name, "client") == 0) { + return client_list; + } + if (strcmp(name, "storage") == 0) { + return storage_list; + } + if (strcmp(name, "fileset") == 0) { + return fileset_list; + } + if (strcmp(name, "messages") == 0) { + return messages_list; + } + if (strcmp(name, "type") == 0) { + return type_list; + } + if (strcmp(name, "level") == 0) { + return level_list; + } + return NULL; +} + +/* + * Set correct default values in the Run dialog box + */ +static void set_run_defaults() +{ + GtkWidget *combo, *entry; + char *job, *def; + GList *item, *list; + char cmd[1000]; + int pos; + + stop_director_reader(NULL); + + combo = lookup_widget(run_dialog, "combo_job"); + job = (char *)gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); + bsnprintf(cmd, sizeof(cmd), ".defaults job=\"%s\"", job); + write_director(cmd); + while (bnet_recv(UA_sock) > 0) { + def = strchr(UA_sock->msg, '='); + if (!def) { + continue; + } + *def++ = 0; + if (strcmp(UA_sock->msg, "job") == 0 || + strcmp(UA_sock->msg, "when") == 0) { + continue; + } + /* Where is an entry box */ + if (strcmp(UA_sock->msg, "where") == 0) { + entry = lookup_widget(run_dialog, "entry_where"); + gtk_entry_set_text(GTK_ENTRY(entry), def); + continue; + } + + /* Now handle combo boxes */ + list = find_combo_list(UA_sock->msg); + if (!list) { + continue; + } + item = g_list_find_custom(list, def, compare_func); + bsnprintf(cmd, sizeof(cmd), "combo_%s", UA_sock->msg); + combo = lookup_widget(run_dialog, cmd); + if (!combo) { + continue; + } + pos = g_list_position(list, item); + gtk_list_select_item(GTK_LIST(GTK_COMBO(combo)->list), pos); + } + start_director_reader(NULL); +} + +void +on_entry_job_changed(GtkEditable *editable, gpointer user_data) +{ + set_run_defaults(); +} + + +void +on_run_button_clicked(GtkButton *button, gpointer user_data) +{ + char dt[50]; + GtkWidget *entry; + + bstrutime(dt, sizeof(dt), time(NULL)); + entry = lookup_widget(run_dialog, "entry_when"); + gtk_entry_set_text(GTK_ENTRY(entry), dt); + set_run_defaults(); + gtk_widget_show(run_dialog); + gtk_main(); +} + + +static char *get_combo_text(GtkWidget *dialog, char *combo_name) +{ + GtkWidget *combo; + combo = lookup_widget(dialog, combo_name); + if (!combo) { + return NULL; + } + return (char *)gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)); +} + +static char *get_entry_text(GtkWidget *dialog, char *entry_name) +{ + GtkWidget *entry; + entry = lookup_widget(dialog, entry_name); + if (!entry) { + return NULL; + } + return (char *)gtk_entry_get_text(GTK_ENTRY(entry)); +} + +static char *get_spin_text(GtkWidget *dialog, char *spin_name) +{ + GtkSpinButton *spin; + spin = (GtkSpinButton *)lookup_widget(dialog, spin_name); + if (!spin) { + return NULL; + } + return (char *)gtk_entry_get_text(GTK_ENTRY(&spin->entry)); +} + + + + +void +on_run_ok_clicked(GtkButton *button, gpointer user_data) +{ + char *job, *fileset, *level, *client, *pool, *when, *where, *storage; + + gtk_widget_hide(run_dialog); + gtk_main_quit(); + + job = get_combo_text(run_dialog, "combo_job"); + fileset = get_combo_text(run_dialog, "combo_fileset"); + client = get_combo_text(run_dialog, "combo_client"); + pool = get_combo_text(run_dialog, "combo_pool"); + storage = get_combo_text(run_dialog, "combo_storage"); + level = get_combo_text(run_dialog, "combo_level"); + + when = get_entry_text(run_dialog, "entry_when"); + where = get_entry_text(run_dialog, "entry_where"); + + if (!job || !fileset || !client || !pool || !storage || + !level || !when || !where) { + set_status_ready(); + return; + } + + bsnprintf(cmd, sizeof(cmd), + "run job=\"%s\" fileset=\"%s\" level=%s client=\"%s\" pool=\"%s\" " + "when=\"%s\" where=\"%s\" storage=\"%s\"", + job, fileset, level, client, pool, when, where, storage); + write_director(cmd); + write_director("yes"); + return; +} + + +void +on_run_cancel_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_hide(run_dialog); + gtk_main_quit(); + set_status_ready(); +} + +gboolean +on_entry1_key_release_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + return FALSE; +} + +void +on_restore_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_show(restore_dialog); + gtk_main(); +} + +void +on_view_fileset_clicked(GtkButton *button, gpointer user_data) +{ +} + +void +on_restore_ok_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_hide(restore_dialog); + gtk_main_quit(); + set_status_ready(); +} + + +void +on_restore_cancel_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_hide(restore_dialog); + gtk_main_quit(); + set_status_ready(); +} + +void +on_apply_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_show(restore_files); + gtk_main(); +} + +void +on_restore_file_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_hide(restore_files); + gtk_main_quit(); +} + +void +on_label_button_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_show(label_dialog); + gtk_main(); +} + +void +on_label_ok_clicked(GtkButton *button, gpointer user_data) +{ + char *pool, *volume, *storage, *slot; + + gtk_widget_hide(label_dialog); + gtk_main_quit(); + + pool = get_combo_text(label_dialog, "label_combo_pool"); + storage = get_combo_text(label_dialog, "label_combo_storage"); + + volume = get_entry_text(label_dialog, "label_entry_volume"); + + slot = get_spin_text(label_dialog, "label_slot"); + + if (!pool || !storage || !volume || !(*volume)) { + set_status_ready(); + return; + } + + bsnprintf(cmd, sizeof(cmd), + "label name=\"%s\" pool=\"%s\" storage=\"%s\" slot=%s", + volume, pool, storage, slot); + write_director(cmd); +} + + +void +on_label_cancel_clicked(GtkButton *button, gpointer user_data) +{ + gtk_widget_hide(label_dialog); + gtk_main_quit(); + set_status_ready(); +} diff --git a/bacula/src/gnome2-console/callbacks.h b/bacula/src/gnome2-console/callbacks.h new file mode 100644 index 0000000000..184ba9c4ea --- /dev/null +++ b/bacula/src/gnome2-console/callbacks.h @@ -0,0 +1,240 @@ + +/* Version $Id$ */ + +gboolean +on_app1_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_new_file1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_open1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_save1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_save_as1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_exit1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_cut1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_copy1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_paste1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_clear1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_properties1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_preferences1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_about1_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_about1_clicked (GnomeDialog *gnomedialog, + gint arg1, + gpointer user_data); + +gboolean +on_entry1_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +gboolean +on_app1_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_select_director_clicked (GtkButton *button, + gpointer user_data); + +void +on_connect_button1_clicked (GtkButton *button, + gpointer user_data); + +void +on_app1_realize (GtkWidget *widget, + gpointer user_data); + +gboolean +on_combo_entry1_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +gboolean +on_entry1_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +gboolean +on_entry1_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_app1_show (GtkWidget *widget, + gpointer user_data); + +void +on_connect_button1_clicked (GtkButton *button, + gpointer user_data); + +void +on_run_button1_clicked (GtkButton *button, + gpointer user_data); + +void +on_msgs_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_msgs_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_run_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_disconnect_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_about_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_connect_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_connect_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_exit_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_about_clicked (GnomeDialog *gnomedialog, + gint arg1, + gpointer user_data); + +gboolean +on_app2_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_app2_show (GtkWidget *widget, + gpointer user_data); + +gboolean +on_app1_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +void +on_app1_show (GtkWidget *widget, + gpointer user_data); + +gboolean +on_entry1_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_about_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_select_director_OK_clicked (GtkButton *button, + gpointer user_data); + +void +on_select_director_cancel_clicked (GtkButton *button, + gpointer user_data); + +void +on_run_ok_clicked (GtkButton *button, + gpointer user_data); + +void +on_run_cancel_clicked (GtkButton *button, + gpointer user_data); + +gboolean +on_entry1_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +void +on_restore_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_type_combo_selection_received (GtkWidget *widget, + GtkSelectionData *data, + guint time, + gpointer user_data); + +void +on_view_fileset_clicked (GtkButton *button, + gpointer user_data); + +void +on_entry_job_changed (GtkEditable *editable, + gpointer user_data); + +void +on_restore_ok_clicked (GtkButton *button, + gpointer user_data); + +void +on_restore_cancel_clicked (GtkButton *button, + gpointer user_data); + +void +on_apply_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_restore_file_clicked (GtkButton *button, + gpointer user_data); + +void +on_label_button_clicked (GtkButton *button, + gpointer user_data); + +void +on_label_ok_clicked (GtkButton *button, + gpointer user_data); + +void +on_label_cancel_clicked (GtkButton *button, + gpointer user_data); diff --git a/bacula/src/gnome2-console/console.c b/bacula/src/gnome2-console/console.c new file mode 100644 index 0000000000..280f8abc6e --- /dev/null +++ b/bacula/src/gnome2-console/console.c @@ -0,0 +1,607 @@ +/* + * + * Bacula GNOME Console interface to the Director + * + * Kern Sibbald, March MMII + * + * Version $Id$ + */ + +/* + Copyright (C) 2002 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "bacula.h" +#include "console.h" + +#include "interface.h" +#include "support.h" + +/* Imported functions */ +int authenticate_director(JCR *jcr, DIRRES *director); + +/* Exported variables */ +GtkWidget *app1; /* application window */ +GtkWidget *text1; /* text window */ +GtkWidget *entry1; /* entry box */ +GtkWidget *status1; /* status bar */ +GtkWidget *combo1; /* director combo */ +GtkWidget *scroll1; /* main scroll bar */ +GtkWidget *run_dialog; /* run dialog */ +GtkWidget *dir_dialog; /* director selection dialog */ +GtkWidget *restore_dialog; /* restore dialog */ +GtkWidget *restore_files; /* restore files dialog */ +GtkWidget *dir_select; +GtkWidget *about1; /* about box */ +GtkWidget *label_dialog; +GdkFont *text_font = NULL; +PangoFontDescription *font_desc; +pthread_mutex_t cmd_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cmd_wait; +char cmd[1000]; +int reply; +BSOCK *UA_sock = NULL; +GList *job_list, *client_list, *fileset_list; +GList *messages_list, *pool_list, *storage_list; +GList *type_list, *level_list; + +/* Forward referenced functions */ +static void terminate_console(int sig); +static gint message_handler(gpointer data); +static int initial_connect_to_director(gpointer data); +static void set_scroll_bar_to_end(void); + +/* Static variables */ +static char *configfile = NULL; +static DIRRES *dir; +static CONRES *con; +static int ndir; +static int director_reader_running = FALSE; +static bool at_prompt = false; +static bool ready = false; +static bool quit = false; +static guint initial; + +#define CONFIG_FILE "./gnome-console.conf" /* default configuration file */ + +static void usage() +{ + fprintf(stderr, _( +"\nVersion: " VERSION " (" BDATE ") %s %s %s\n\n" +"Usage: gnome-console [-s] [-c config_file] [-d debug_level] [config_file]\n" +" -c set configuration file to file\n" +" -dnn set debug level to nn\n" +" -s no signals\n" +" -t test - read configuration and exit\n" +" -? print this message.\n" +"\n"), HOST_OS, DISTNAME, DISTVER); + + exit(1); +} + + +/********************************************************************* + * + * Main Bacula GNOME Console -- User Interface Program + * + */ +int main(int argc, char *argv[]) +{ + int ch, stat; + int no_signals = TRUE; + int test_config = FALSE; + int gargc = 1; + char *gargv[2] = {"gnome-console", NULL}; + + init_stack_dump(); + my_name_is(argc, argv, "gnome-console"); + init_msg(NULL, NULL); + working_directory = "/tmp"; + + struct sigaction sigignore; + sigignore.sa_flags = 0; + sigignore.sa_handler = SIG_IGN; + sigfillset(&sigignore.sa_mask); + sigaction(SIGPIPE, &sigignore, NULL); + + if ((stat=pthread_cond_init(&cmd_wait, NULL)) != 0) { + Emsg1(M_ABORT, 0, _("Pthread cond init error = %s\n"), + strerror(stat)); + } + + gnome_init("bacula", VERSION, gargc, (char **)&gargv); + + while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) { + switch (ch) { + case 'c': /* configuration file */ + if (configfile != NULL) + free(configfile); + configfile = bstrdup(optarg); + break; + + case 'd': + debug_level = atoi(optarg); + if (debug_level <= 0) + debug_level = 1; + break; + + case 's': /* turn off signals */ + no_signals = TRUE; + break; + + case 't': + test_config = TRUE; + break; + + case '?': + default: + usage(); + + } + } + argc -= optind; + argv += optind; + + + if (!no_signals) { + init_signals(terminate_console); + } + + if (argc) { + usage(); + } + + if (configfile == NULL) { + configfile = bstrdup(CONFIG_FILE); + } + + parse_config(configfile); + + LockRes(); + ndir = 0; + for (dir=NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) { + ndir++; + } + UnlockRes(); + if (ndir == 0) { + Emsg1(M_ERROR_TERM, 0, _("No director resource defined in %s\n\ +Without that I don't how to speak to the Director :-(\n"), configfile); + } + + if (test_config) { + terminate_console(0); + exit(0); + } + + + app1 = create_app1(); + gtk_window_set_default_size(GTK_WINDOW(app1), 800, 700); + run_dialog = create_RunDialog(); + label_dialog = create_label_dialog(); + restore_dialog = create_restore_dialog(); + restore_files = create_restore_files(); + about1 = create_about1(); + + gtk_widget_show(app1); + + text1 = lookup_widget(app1, "text1"); + entry1 = lookup_widget(app1, "entry1"); + status1 = lookup_widget(app1, "status1"); + scroll1 = lookup_widget(app1, "scroll1"); + +/* + * Thanks to Phil Stracchino for providing the font configuration code. + * original default: + text_font = gdk_font_load("-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-koi8-r"); + * this works for me: + text_font = gdk_font_load("-Bigelow & Holmes-lucida console-medium-r-semi condensed-*-12-0-100-100-m-0-iso8859-1"); + * and, new automagic:font specification! + */ + + LockRes(); + for (con = NULL; (con = (CONRES *)GetNextRes(R_CONSOLE, (RES *)con)); ) { + text_font = gdk_font_load(con->fontface); + if (text_font == NULL) { + Dmsg2(404, "Load of requested ConsoleFont \"%s\" (%s) failed!\n", + con->hdr.name, con->fontface); + } else { + Dmsg2(404, "ConsoleFont \"%s\" (%s) loaded.\n", + con->hdr.name, con->fontface); + break; + } + } + UnlockRes(); + + if (text_font == NULL) { + Dmsg1(100, "Attempting to load fallback font %s\n", + "-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1"); + text_font = gdk_font_load("-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1"); + } + font_desc = pango_font_description_from_string("LucidaTypewriter 9"); + gtk_widget_modify_font (app1, font_desc); + gtk_widget_modify_font (text1, font_desc); + gtk_widget_modify_font (entry1, font_desc); + gtk_widget_modify_font (status1, font_desc); + pango_font_description_free (font_desc); + + + initial = gtk_timeout_add(100, initial_connect_to_director, (gpointer)NULL); + + gtk_main(); + quit = true; + disconnect_from_director((gpointer)NULL); + return 0; +} + +/* + * Every 5 seconds, ask the Director for our + * messages. + */ +static gint message_handler(gpointer data) +{ + if (ready && UA_sock) { + bnet_fsend(UA_sock, ".messages"); + } + return TRUE; +} + +int disconnect_from_director(gpointer data) +{ + if (!quit) + set_status(_(" Not Connected")); + if (UA_sock) { + bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */ + bnet_close(UA_sock); + UA_sock = NULL; + } + return 1; +} + +/* + * Called just after the main loop is started to allow + * us to connect to the Director. + */ +static int initial_connect_to_director(gpointer data) +{ + gtk_timeout_remove(initial); + if (connect_to_director(data)) { + start_director_reader(data); + } + gtk_timeout_add(5000, message_handler, (gpointer)NULL); + return TRUE; +} + +static GList *get_list(char *cmd) +{ + GList *options; + char *msg; + + options = NULL; + write_director(cmd); + while (bnet_recv(UA_sock) > 0) { + strip_trailing_junk(UA_sock->msg); + msg = (char *)malloc(strlen(UA_sock->msg) + 1); + strcpy(msg, UA_sock->msg); + options = g_list_append(options, msg); + } + return options; + +} + +static GList *get_and_fill_combo(GtkWidget *dialog, char *combo_name, char *cmd) +{ + GtkWidget *combo; + GList *options; + + combo = lookup_widget(dialog, combo_name); + options = get_list(cmd); + if (combo && options) { + gtk_combo_set_popdown_strings(GTK_COMBO(combo), options); + } + return options; +} + +static void fill_combo(GtkWidget *dialog, char *combo_name, GList *options) +{ + GtkWidget *combo; + + combo = lookup_widget(dialog, combo_name); + if (combo) { + gtk_combo_set_popdown_strings(GTK_COMBO(combo), options); + } + return; +} + + +/* + * Connect to Director. If there are more than one, put up + * a modal dialog so that the user chooses one. + */ +int connect_to_director(gpointer data) +{ + GList *dirs = NULL; + GtkWidget *combo; + char buf[1000]; + JCR jcr; + + + if (UA_sock) { + return 0; + } + + if (ndir > 1) { + LockRes(); + for (dir = NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) { + sprintf(buf, "%s at %s:%d", dir->hdr.name, dir->address, + dir->DIRport); + printf("%s\n", buf); + dirs = g_list_append(dirs, dir->hdr.name); + } + UnlockRes(); + dir_dialog = create_SelectDirectorDialog(); + combo = lookup_widget(dir_dialog, "combo1"); + dir_select = lookup_widget(dir_dialog, "dirselect"); + gtk_combo_set_popdown_strings(GTK_COMBO(combo), dirs); + printf("dialog run\n"); + gtk_widget_show(dir_dialog); + gtk_main(); + + if (reply == OK) { + gchar *ecmd = gtk_editable_get_chars((GtkEditable *)dir_select, 0, -1); + dir = (DIRRES *)GetResWithName(R_DIRECTOR, ecmd); + if (ecmd) { + g_free(ecmd); /* release director name string */ + } + } + if (dirs) { + g_free(dirs); + } + gtk_widget_destroy(dir_dialog); + dir_dialog = NULL; + } else { + /* Just take the first Director */ + LockRes(); + dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL); + UnlockRes(); + } + + if (!dir) { + printf("dir is NULL\n"); + return 0; + } + + memset(&jcr, 0, sizeof(jcr)); + + set_statusf(_(" Connecting to Director %s:%d"), dir->address,dir->DIRport); + set_textf(_("Connecting to Director %s:%d\n\n"), dir->address,dir->DIRport); + + while (gtk_events_pending()) { /* fully paint screen */ + gtk_main_iteration(); + } + UA_sock = bnet_connect(NULL, 5, 15, "Director daemon", dir->address, + NULL, dir->DIRport, 0); + if (UA_sock == NULL) { + return 0; + } + + jcr.dir_bsock = UA_sock; + if (!authenticate_director(&jcr, dir)) { + set_text(UA_sock->msg, UA_sock->msglen); + return 0; + } + + set_status(" Initializing ..."); + + bnet_fsend(UA_sock, "autodisplay on"); + + /* Read and display all initial messages */ + while (bnet_recv(UA_sock) > 0) { + set_text(UA_sock->msg, UA_sock->msglen); + } + + /* Paint changes */ + while (gtk_events_pending()) { + gtk_main_iteration(); + } + + /* Fill the run_dialog combo boxes */ + job_list = get_and_fill_combo(run_dialog, "combo_job", ".jobs"); + client_list = get_and_fill_combo(run_dialog, "combo_client", ".clients"); + fileset_list = get_and_fill_combo(run_dialog, "combo_fileset", ".filesets"); + messages_list = get_and_fill_combo(run_dialog, "combo_messages", ".msgs"); + pool_list = get_and_fill_combo(run_dialog, "combo_pool", ".pools"); + storage_list = get_and_fill_combo(run_dialog, "combo_storage", ".storage"); + type_list = get_and_fill_combo(run_dialog, "combo_type", ".types"); + level_list = get_and_fill_combo(run_dialog, "combo_level", ".levels"); + + fill_combo(label_dialog, "label_combo_storage", storage_list); + fill_combo(label_dialog, "label_combo_pool", pool_list); + + set_status(" Connected"); + return 1; +} + +void write_director(gchar *msg) +{ + if (UA_sock) { + at_prompt = false; + set_status(_(" Processing command ...")); + UA_sock->msglen = strlen(msg); + pm_strcpy(&UA_sock->msg, msg); + bnet_send(UA_sock); + } + if (strcmp(msg, ".quit") == 0 || strcmp(msg, ".exit") == 0) { + disconnect_from_director((gpointer)NULL); + gtk_main_quit(); + } +} + +void read_director(gpointer data, gint fd, GdkInputCondition condition) +{ + int stat; + + if (!UA_sock || UA_sock->fd != fd) { + return; + } + stat = bnet_recv(UA_sock); + if (stat >= 0) { + if (at_prompt) { + set_text("\n", 1); + at_prompt = false; + } + set_text(UA_sock->msg, UA_sock->msglen); + return; + } + if (is_bnet_stop(UA_sock)) { /* error or term request */ + gtk_main_quit(); + return; + } + /* Must be a signal -- either do something or ignore it */ + if (UA_sock->msglen == BNET_PROMPT) { + at_prompt = true; + set_status(_(" At prompt waiting for input ...")); + } + if (UA_sock->msglen == BNET_EOD) { + set_status_ready(); + } + return; +} + +static gint tag; + +void start_director_reader(gpointer data) +{ + + if (director_reader_running || !UA_sock) { + return; + } + director_reader_running = TRUE; + + tag = gdk_input_add(UA_sock->fd, GDK_INPUT_READ, read_director, NULL); +} + +void stop_director_reader(gpointer data) +{ + if (!director_reader_running) { + return; + } + gdk_input_remove(tag); + director_reader_running = FALSE; +} + + + +/* Cleanup and then exit */ +static void terminate_console(int sig) +{ + static int already_here = FALSE; + + if (already_here) /* avoid recursive temination problems */ + exit(1); + already_here = TRUE; + disconnect_from_director((gpointer)NULL); + gtk_main_quit(); + exit(0); +} + + +/* Buffer approx 2000 lines -- assume 60 chars/line */ +#define MAX_TEXT_CHARS (2000 * 60) +static int text_chars = 0; + +static void truncate_text_chars() +{ + GtkTextBuffer *textbuf; + GtkTextIter iter, iter2; + guint len; + int del_chars = MAX_TEXT_CHARS / 4; + + textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text1)); + len = gtk_text_buffer_get_char_count(textbuf); + gtk_text_buffer_get_iter_at_offset (textbuf, &iter, 0); + gtk_text_buffer_get_iter_at_offset (textbuf, &iter2, del_chars); + gtk_text_buffer_delete (textbuf, &iter, &iter2); + text_chars -= del_chars; + len = gtk_text_buffer_get_char_count(textbuf); + gtk_text_iter_set_offset(&iter, len); +} + +void set_textf(char *fmt, ...) +{ + va_list arg_ptr; + char buf[1000]; + int len; + va_start(arg_ptr, fmt); + len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr); + va_end(arg_ptr); + set_text(buf, len); +} + +void set_text(char *buf, int len) +{ + GtkTextBuffer *textbuf; + GtkTextIter iter; + guint buf_len; + + textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text1)); + buf_len = gtk_text_buffer_get_char_count(textbuf); + gtk_text_buffer_get_iter_at_offset(textbuf, &iter, buf_len - 1); + gtk_text_buffer_insert(textbuf, &iter, buf, -1); + text_chars += len; + if (text_chars > MAX_TEXT_CHARS) { + truncate_text_chars(); + } + buf_len = gtk_text_buffer_get_char_count(textbuf); + gtk_text_buffer_get_iter_at_offset(textbuf, &iter, buf_len - 1); + gtk_text_iter_set_offset(&iter, buf_len); + set_scroll_bar_to_end(); +} + +void set_statusf(char *fmt, ...) +{ + va_list arg_ptr; + char buf[1000]; + int len; + va_start(arg_ptr, fmt); + len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr); + va_end(arg_ptr); + gtk_label_set_text(GTK_LABEL(status1), buf); +// set_scroll_bar_to_end(); + ready = false; +} + +void set_status_ready() +{ + gtk_label_set_text(GTK_LABEL(status1), " Ready"); + ready = true; +// set_scroll_bar_to_end(); +} + +void set_status(char *buf) +{ + gtk_label_set_text(GTK_LABEL(status1), buf); +// set_scroll_bar_to_end(); + ready = false; +} + +static void set_scroll_bar_to_end(void) +{ + GtkTextBuffer* buffer = NULL; + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text1)); + gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW(text1), + gtk_text_buffer_get_mark (buffer, "insert")); +} diff --git a/bacula/src/gnome2-console/console.h b/bacula/src/gnome2-console/console.h new file mode 100644 index 0000000000..200ca32288 --- /dev/null +++ b/bacula/src/gnome2-console/console.h @@ -0,0 +1,61 @@ +/* + * Bacula GNOME User Agent specific configuration and defines + * + * Kern Sibbald, March 2002 + * + * Version $Id$ + */ + +#ifndef __CONSOLE_H_ +#define __CONSOLE_H_ + +#include "console_conf.h" +#include "jcr.h" +/* Super kludge for GNOME 2.0 */ +#undef _ +#undef N_ +#undef textdomain + +#include + +extern GtkWidget *app1; /* application window */ +extern GtkWidget *text1; /* text window */ +extern GtkWidget *entry1; /* entry box */ +extern GtkWidget *combo1; /* Directory combo */ +extern GtkWidget *dir_dialog; +extern GtkWidget *dir_select; +extern GtkWidget *run_dialog; /* run dialog */ +extern GtkWidget *label_dialog; +extern GtkWidget *restore_dialog; /* restore dialog */ +extern GtkWidget *restore_files; /* restore files dialog */ +extern GtkWidget *about1; +extern GList *job_list, *client_list, *fileset_list; +extern GList *messages_list, *pool_list, *storage_list; +extern GList *type_list, *level_list; + + +extern pthread_mutex_t cmd_mutex; +extern pthread_cond_t cmd_wait; +extern char cmd[1000]; +extern int cmd_ready; +extern int reply; +extern BSOCK *UA_sock; + + + +#define OK 1 +#define CANCEL 0 + +void set_textf(char *fmt, ...); +void set_text(char *buf, int len); +void set_status(char *buf); +void set_status_ready(); +void set_statusf(char *fmt, ...); +int connect_to_director(gpointer data); +int disconnect_from_director(gpointer data); +void start_director_reader(gpointer data); +void stop_director_reader(gpointer data); +void write_director(gchar *msg); +void read_director(gpointer data, gint fd, GdkInputCondition condition); + +#endif diff --git a/bacula/src/gnome2-console/console_conf.c b/bacula/src/gnome2-console/console_conf.c new file mode 100644 index 0000000000..725fc024d9 --- /dev/null +++ b/bacula/src/gnome2-console/console_conf.c @@ -0,0 +1,268 @@ +/* + * Main configuration file parser for Bacula User Agent + * some parts may be split into separate files such as + * the schedule configuration (sch_config.c). + * + * Note, the configuration file parser consists of three parts + * + * 1. The generic lexical scanner in lib/lex.c and lib/lex.h + * + * 2. The generic config scanner in lib/parse_config.c and + * lib/parse_config.h. + * These files contain the parser code, some utility + * routines, and the common store routines (name, int, + * string). + * + * 3. The daemon specific file, which contains the Resource + * definitions as well as any specific store routines + * for the resource records. + * + * Kern Sibbald, January MM, September MM + * + * Version $Id$ + */ + +/* + Copyright (C) 2000, 2001 Kern Sibbald and John Walker + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "bacula.h" +#include "console_conf.h" + +/* Define the first and last resource ID record + * types. Note, these should be unique for each + * daemon though not a requirement. + */ +int r_first = R_FIRST; +int r_last = R_LAST; +pthread_mutex_t res_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Forward referenced subroutines */ + + +/* We build the current resource here as we are + * scanning the resource configuration definition, + * then move it to allocated memory when the resource + * scan is complete. + */ +URES res_all; +int res_all_size = sizeof(res_all); + +/* Definition of records permitted within each + * resource with the routine to process the record + * information. + */ +static struct res_items dir_items[] = { + {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0}, + {"dirport", store_int, ITEM(res_dir.DIRport), 0, ITEM_DEFAULT, 9101}, + {"address", store_str, ITEM(res_dir.address), 0, ITEM_REQUIRED, 0}, + {"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0}, + {"enablessl", store_yesno, ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0}, + {NULL, NULL, NULL, 0, 0, 0} +}; + +static struct res_items con_items[] = { + {"name", store_name, ITEM(con_dir.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(con_dir.hdr.desc), 0, 0, 0}, + {"font", store_str, ITEM(con_dir.fontface), 0, ITEM_REQUIRED, 0}, + {"requiressl", store_yesno, ITEM(con_dir.require_ssl), 1, ITEM_DEFAULT, 0}, + {NULL, NULL, NULL, 0, 0, 0} +}; + +/* + * This is the master resource definition. + * It must have one item for each of the resources. + */ +struct s_res resources[] = { + {"director", dir_items, R_DIRECTOR, NULL}, + {"consolefont", con_items, R_CONSOLE, NULL}, + {NULL, NULL, 0, NULL} +}; + + +/* Dump contents of resource */ +void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...), void *sock) +{ + URES *res = (URES *)reshdr; + int recurse = 1; + + if (res == NULL) { + printf("No record for %d %s\n", type, res_to_str(type)); + return; + } + if (type < 0) { /* no recursion */ + type = - type; + recurse = 0; + } + switch (type) { + case R_DIRECTOR: + printf("Director: name=%s address=%s DIRport=%d\n", reshdr->name, + res->res_dir.address, res->res_dir.DIRport); + break; + case R_CONSOLE: + printf("Console: name=%s font face=%s\n", + reshdr->name, NPRT(res->con_dir.fontface)); + break; + default: + printf("Unknown resource type %d\n", type); + } + if (recurse && res->res_dir.hdr.next) { + dump_resource(type, res->res_dir.hdr.next, sendit, sock); + } +} + +/* + * Free memory of resource. + * NB, we don't need to worry about freeing any references + * to other resources as they will be freed when that + * resource chain is traversed. Mainly we worry about freeing + * allocated strings (names). + */ +void free_resource(int type) +{ + URES *res; + RES *nres; + int rindex = type - r_first; + + res = (URES *)resources[rindex].res_head; + + if (res == NULL) + return; + + /* common stuff -- free the resource name */ + nres = (RES *)res->res_dir.hdr.next; + if (res->res_dir.hdr.name) { + free(res->res_dir.hdr.name); + } + if (res->res_dir.hdr.desc) { + free(res->res_dir.hdr.desc); + } + + switch (type) { + case R_DIRECTOR: + if (res->res_dir.address) { + free(res->res_dir.address); + } + break; + case R_CONSOLE: + if (res->con_dir.fontface) { + free(res->con_dir.fontface); + } + break; + default: + printf("Unknown resource type %d\n", type); + } + /* Common stuff again -- free the resource, recurse to next one */ + free(res); + resources[rindex].res_head = nres; + if (nres) { + free_resource(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). + */ +void save_resource(int type, struct res_items *items, int pass) +{ + URES *res; + int rindex = type - r_first; + int i, size = 0; + int error = 0; + + /* + * Ensure that all required items are present + */ + for (i=0; items[i].name; i++) { + if (items[i].flags & ITEM_REQUIRED) { + if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { + Emsg2(M_ABORT, 0, "%s item is required in %s resource, but not found.\n", + items[i].name, resources[rindex]); + } + } + } + + /* During pass 2, we looked up pointers to all the resources + * referrenced in the current resource, , now we + * must copy their address from the static record to the allocated + * record. + */ + if (pass == 2) { + switch (type) { + /* Resources not containing a resource */ + case R_DIRECTOR: + break; + + case R_CONSOLE: + break; + + default: + Emsg1(M_ERROR, 0, "Unknown resource type %d\n", type); + error = 1; + break; + } + /* Note, the resoure name was already saved during pass 1, + * so here, we can just release it. + */ + if (res_all.res_dir.hdr.name) { + free(res_all.res_dir.hdr.name); + res_all.res_dir.hdr.name = NULL; + } + if (res_all.res_dir.hdr.desc) { + free(res_all.res_dir.hdr.desc); + res_all.res_dir.hdr.desc = NULL; + } + return; + } + + /* The following code is only executed during pass 1 */ + switch (type) { + case R_DIRECTOR: + size = sizeof(DIRRES); + break; + case R_CONSOLE: + size = sizeof(CONRES); + break; + default: + printf("Unknown resource type %d\n", type); + error = 1; + break; + } + /* Common */ + if (!error) { + res = (URES *)malloc(size); + memcpy(res, &res_all, size); + if (!resources[rindex].res_head) { + resources[rindex].res_head = (RES *)res; /* store first entry */ + } else { + RES *next; + /* Add new res to end of chain */ + for (next=resources[rindex].res_head; next->next; next=next->next) { + if (strcmp(next->name, res->res_dir.hdr.name) == 0) { + Emsg2(M_ERROR_TERM, 0, + _("Attempt to define second %s resource named \"%s\" is not permitted.\n"), + resources[rindex].name, res->res_dir.hdr.name); + } + } + next->next = (RES *)res; + Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type), + res->res_dir.hdr.name); + } + } +} diff --git a/bacula/src/gnome2-console/console_conf.h b/bacula/src/gnome2-console/console_conf.h new file mode 100644 index 0000000000..b63d20ccc8 --- /dev/null +++ b/bacula/src/gnome2-console/console_conf.h @@ -0,0 +1,60 @@ +/* + * Bacula GNOME User Agent specific configuration and defines + * + * Kern Sibbald, March 2002 + * + * Version $Id$ + */ + +#ifndef __CONSOLE_CONF_H_ +#define __CONSOLE_CONF_H_ + +/* + * Resource codes -- they must be sequential for indexing + */ +#define R_FIRST 1001 + +#define R_DIRECTOR 1001 +#define R_CONSOLE 1002 + +#define R_LAST R_CONSOLE + +/* + * Some resource attributes + */ +#define R_NAME 1020 +#define R_ADDRESS 1021 +#define R_PASSWORD 1022 +#define R_TYPE 1023 +#define R_BACKUP 1024 + + +/* Definition of the contents of each Resource */ +struct s_res_dir { + RES hdr; + int DIRport; /* UA server port */ + char *address; /* UA server address */ + char *password; /* UA server password */ + int enable_ssl; /* Use SSL */ +}; +typedef struct s_res_dir DIRRES; + +struct s_con_dir { + RES hdr; + char *fontface; /* Console Font specification */ + int require_ssl; /* Require SSL on all connections */ +}; +typedef struct s_con_dir CONRES; + +/* Define the Union of all the above + * resource structure definitions. + */ +union u_res { + struct s_res_dir res_dir; + struct s_con_dir con_dir; + RES hdr; +}; + +typedef union u_res URES; + +#endif diff --git a/bacula/src/gnome2-console/gnome-console.conf.in b/bacula/src/gnome2-console/gnome-console.conf.in new file mode 100644 index 0000000000..8ca3533b3d --- /dev/null +++ b/bacula/src/gnome2-console/gnome-console.conf.in @@ -0,0 +1,15 @@ +# +# Bacula User Agent (or Console) Configuration File +# + +Director { + Name = @hostname@-dir + DIRport = @dir_port@ + address = @hostname@ + Password = "@dir_password@" +} + +ConsoleFont { + Name = Default + Font = "-misc-fixed-medium-r-normal-*-*-130-*-*-c-*-iso8859-1" +} diff --git a/bacula/src/gnome2-console/interface.c b/bacula/src/gnome2-console/interface.c new file mode 100644 index 0000000000..d536d15a2d --- /dev/null +++ b/bacula/src/gnome2-console/interface.c @@ -0,0 +1,1464 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include "callbacks.h" +#include "interface.h" +#include "support.h" + +#define GLADE_HOOKUP_OBJECT(component,widget,name) \ + g_object_set_data_full (G_OBJECT (component), name, \ + gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref) + +#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \ + g_object_set_data (G_OBJECT (component), name, widget) + +static GnomeUIInfo file1_menu_uiinfo[] = +{ + { + GNOME_APP_UI_ITEM, N_("_Connect"), + N_("Connect to Director"), + (gpointer) on_connect_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("_Disconnect"), + N_("Disconnect from Director"), + (gpointer) on_disconnect_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_ITEM, N_("gtk-quit"), + NULL, + (gpointer) on_exit_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_END +}; + +static GnomeUIInfo edit1_menu_uiinfo[] = +{ + { + GNOME_APP_UI_ITEM, N_("gtk-cut"), + NULL, + (gpointer) on_cut1_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("gtk-copy"), + NULL, + (gpointer) on_copy1_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("gtk-paste"), + NULL, + (gpointer) on_paste1_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("gtk-clear"), + NULL, + (gpointer) on_clear1_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_SEPARATOR, + GNOMEUIINFO_END +}; + +static GnomeUIInfo item1_menu_uiinfo[] = +{ + { + GNOME_APP_UI_ITEM, N_("_Display Messages"), + NULL, + (gpointer) on_msgs_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_END +}; + +static GnomeUIInfo settings1_menu_uiinfo[] = +{ + { + GNOME_APP_UI_ITEM, N_("gtk-preferences"), + NULL, + (gpointer) on_preferences1_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_END +}; + +static GnomeUIInfo help1_menu_uiinfo[] = +{ + { + GNOME_APP_UI_ITEM, N_("gnome-stock-about"), + NULL, + (gpointer) on_about_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_END +}; + +static GnomeUIInfo menubar1_uiinfo[] = +{ + { + GNOME_APP_UI_SUBTREE, N_("_File"), + NULL, + file1_menu_uiinfo, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_SUBTREE, N_("_Edit"), + NULL, + edit1_menu_uiinfo, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_SUBTREE, N_("_View"), + N_("Display Messages"), + item1_menu_uiinfo, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_SUBTREE, N_("_Settings"), + NULL, + settings1_menu_uiinfo, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_SUBTREE, N_("_Help"), + NULL, + help1_menu_uiinfo, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_END +}; + +GtkWidget* +create_app1 (void) +{ + GtkWidget *app1; + GtkWidget *vbox6; + GtkWidget *handlebox1; + GtkWidget *menubar1; + GtkWidget *handlebox2; + GtkWidget *toolbar2; + GtkWidget *tmp_toolbar_icon; + GtkWidget *connect_button1; + GtkWidget *run_button1; + GtkWidget *msgs_button; + GtkWidget *restore_button; + GtkWidget *label_button; + GtkWidget *vbox7; + GtkWidget *scroll1; + GtkWidget *text1; + GtkWidget *hbox18; + GtkWidget *label38; + GtkWidget *entry1; + GtkWidget *hbox19; + GtkWidget *frame1; + GtkWidget *label39; + GtkWidget *frame2; + GtkWidget *status1; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + app1 = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (app1), _("Bacula Console")); + gtk_window_set_position (GTK_WINDOW (app1), GTK_WIN_POS_CENTER); + + vbox6 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox6); + gtk_container_add (GTK_CONTAINER (app1), vbox6); + + handlebox1 = gtk_handle_box_new (); + gtk_widget_show (handlebox1); + gtk_box_pack_start (GTK_BOX (vbox6), handlebox1, FALSE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (handlebox1), 1); + + menubar1 = gtk_menu_bar_new (); + gtk_widget_show (menubar1); + gtk_container_add (GTK_CONTAINER (handlebox1), menubar1); + gnome_app_fill_menu (GTK_MENU_SHELL (menubar1), menubar1_uiinfo, + NULL, FALSE, 0); + + handlebox2 = gtk_handle_box_new (); + gtk_widget_show (handlebox2); + gtk_box_pack_start (GTK_BOX (vbox6), handlebox2, FALSE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (handlebox2), 1); + + toolbar2 = gtk_toolbar_new (); + gtk_widget_show (toolbar2); + gtk_container_add (GTK_CONTAINER (handlebox2), toolbar2); + gtk_container_set_border_width (GTK_CONTAINER (toolbar2), 1); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar2), GTK_TOOLBAR_BOTH); + + tmp_toolbar_icon = gtk_image_new_from_stock ("gtk-new", gtk_toolbar_get_icon_size (GTK_TOOLBAR (toolbar2))); + connect_button1 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar2), + GTK_TOOLBAR_CHILD_BUTTON, + NULL, + _("Connect"), + _("Connect to Director"), NULL, + tmp_toolbar_icon, NULL, NULL); + gtk_label_set_use_underline (GTK_LABEL (((GtkToolbarChild*) (g_list_last (GTK_TOOLBAR (toolbar2)->children)->data))->label), TRUE); + gtk_widget_show (connect_button1); + + tmp_toolbar_icon = gtk_image_new_from_stock ("gtk-execute", gtk_toolbar_get_icon_size (GTK_TOOLBAR (toolbar2))); + run_button1 = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar2), + GTK_TOOLBAR_CHILD_BUTTON, + NULL, + _("Run"), + _("Run a Job"), NULL, + tmp_toolbar_icon, NULL, NULL); + gtk_label_set_use_underline (GTK_LABEL (((GtkToolbarChild*) (g_list_last (GTK_TOOLBAR (toolbar2)->children)->data))->label), TRUE); + gtk_widget_show (run_button1); + + tmp_toolbar_icon = gtk_image_new_from_stock ("gtk-find", gtk_toolbar_get_icon_size (GTK_TOOLBAR (toolbar2))); + msgs_button = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar2), + GTK_TOOLBAR_CHILD_BUTTON, + NULL, + _("Msgs"), + _("Display Messages"), NULL, + tmp_toolbar_icon, NULL, NULL); + gtk_label_set_use_underline (GTK_LABEL (((GtkToolbarChild*) (g_list_last (GTK_TOOLBAR (toolbar2)->children)->data))->label), TRUE); + gtk_widget_show (msgs_button); + + tmp_toolbar_icon = gtk_image_new_from_stock ("gtk-revert-to-saved", gtk_toolbar_get_icon_size (GTK_TOOLBAR (toolbar2))); + restore_button = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar2), + GTK_TOOLBAR_CHILD_BUTTON, + NULL, + _("Restore"), + NULL, NULL, + tmp_toolbar_icon, NULL, NULL); + gtk_label_set_use_underline (GTK_LABEL (((GtkToolbarChild*) (g_list_last (GTK_TOOLBAR (toolbar2)->children)->data))->label), TRUE); + gtk_widget_show (restore_button); + + tmp_toolbar_icon = gtk_image_new_from_stock ("gtk-save-as", gtk_toolbar_get_icon_size (GTK_TOOLBAR (toolbar2))); + label_button = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar2), + GTK_TOOLBAR_CHILD_BUTTON, + NULL, + _("Label"), + NULL, NULL, + tmp_toolbar_icon, NULL, NULL); + gtk_label_set_use_underline (GTK_LABEL (((GtkToolbarChild*) (g_list_last (GTK_TOOLBAR (toolbar2)->children)->data))->label), TRUE); + gtk_widget_show (label_button); + + vbox7 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox7); + gtk_box_pack_start (GTK_BOX (vbox6), vbox7, TRUE, TRUE, 0); + + scroll1 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scroll1); + gtk_box_pack_start (GTK_BOX (vbox7), scroll1, TRUE, TRUE, 0); + GTK_WIDGET_UNSET_FLAGS (scroll1, GTK_CAN_FOCUS); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll1), GTK_SHADOW_IN); + + text1 = gtk_text_view_new (); + gtk_widget_show (text1); + gtk_container_add (GTK_CONTAINER (scroll1), text1); + GTK_WIDGET_UNSET_FLAGS (text1, GTK_CAN_FOCUS); + gtk_text_view_set_editable (GTK_TEXT_VIEW (text1), FALSE); + gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text1), GTK_WRAP_WORD); + + hbox18 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox18); + gtk_box_pack_start (GTK_BOX (vbox7), hbox18, FALSE, TRUE, 0); + + label38 = gtk_label_new (_(" Command: ")); + gtk_widget_show (label38); + gtk_box_pack_start (GTK_BOX (hbox18), label38, FALSE, TRUE, 0); + + entry1 = gtk_entry_new (); + gtk_widget_show (entry1); + gtk_box_pack_start (GTK_BOX (hbox18), entry1, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (entry1, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, entry1, _("Enter Commands Here"), NULL); + gtk_entry_set_max_length (GTK_ENTRY (entry1), 150); + + hbox19 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox19); + gtk_box_pack_start (GTK_BOX (vbox7), hbox19, FALSE, FALSE, 0); + + frame1 = gtk_frame_new (NULL); + gtk_widget_show (frame1); + gtk_box_pack_start (GTK_BOX (hbox19), frame1, FALSE, TRUE, 0); + + label39 = gtk_label_new (_(" Status: ")); + gtk_widget_show (label39); + gtk_container_add (GTK_CONTAINER (frame1), label39); + + frame2 = gtk_frame_new (NULL); + gtk_widget_show (frame2); + gtk_box_pack_start (GTK_BOX (hbox19), frame2, TRUE, TRUE, 0); + + status1 = gtk_label_new (""); + gtk_widget_show (status1); + gtk_container_add (GTK_CONTAINER (frame2), status1); + gtk_label_set_justify (GTK_LABEL (status1), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (status1), 0, 0.5); + + g_signal_connect ((gpointer) app1, "delete_event", + G_CALLBACK (on_app1_delete_event), + NULL); + g_signal_connect ((gpointer) connect_button1, "clicked", + G_CALLBACK (on_connect_button_clicked), + NULL); + g_signal_connect ((gpointer) run_button1, "clicked", + G_CALLBACK (on_run_button_clicked), + NULL); + g_signal_connect ((gpointer) msgs_button, "clicked", + G_CALLBACK (on_msgs_button_clicked), + NULL); + g_signal_connect ((gpointer) restore_button, "clicked", + G_CALLBACK (on_restore_button_clicked), + NULL); + g_signal_connect ((gpointer) label_button, "clicked", + G_CALLBACK (on_label_button_clicked), + NULL); + g_signal_connect ((gpointer) entry1, "key_press_event", + G_CALLBACK (on_entry1_key_press_event), + NULL); + g_signal_connect ((gpointer) entry1, "key_release_event", + G_CALLBACK (on_entry1_key_release_event), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (app1, app1, "app1"); + GLADE_HOOKUP_OBJECT (app1, vbox6, "vbox6"); + GLADE_HOOKUP_OBJECT (app1, handlebox1, "handlebox1"); + GLADE_HOOKUP_OBJECT (app1, menubar1, "menubar1"); + GLADE_HOOKUP_OBJECT (app1, menubar1_uiinfo[0].widget, "file1"); + GLADE_HOOKUP_OBJECT (app1, file1_menu_uiinfo[0].widget, "connect1"); + GLADE_HOOKUP_OBJECT (app1, file1_menu_uiinfo[1].widget, "disconnect1"); + GLADE_HOOKUP_OBJECT (app1, file1_menu_uiinfo[2].widget, "menuitem4"); + GLADE_HOOKUP_OBJECT (app1, file1_menu_uiinfo[3].widget, "exit1"); + GLADE_HOOKUP_OBJECT (app1, menubar1_uiinfo[1].widget, "edit1"); + GLADE_HOOKUP_OBJECT (app1, edit1_menu_uiinfo[0].widget, "cut1"); + GLADE_HOOKUP_OBJECT (app1, edit1_menu_uiinfo[1].widget, "copy1"); + GLADE_HOOKUP_OBJECT (app1, edit1_menu_uiinfo[2].widget, "paste1"); + GLADE_HOOKUP_OBJECT (app1, edit1_menu_uiinfo[3].widget, "clear1"); + GLADE_HOOKUP_OBJECT (app1, edit1_menu_uiinfo[4].widget, "separator1"); + GLADE_HOOKUP_OBJECT (app1, menubar1_uiinfo[2].widget, "item1"); + GLADE_HOOKUP_OBJECT (app1, item1_menu_uiinfo[0].widget, "msgs"); + GLADE_HOOKUP_OBJECT (app1, menubar1_uiinfo[3].widget, "settings1"); + GLADE_HOOKUP_OBJECT (app1, settings1_menu_uiinfo[0].widget, "preferences1"); + GLADE_HOOKUP_OBJECT (app1, menubar1_uiinfo[4].widget, "help1"); + GLADE_HOOKUP_OBJECT (app1, help1_menu_uiinfo[0].widget, "about1"); + GLADE_HOOKUP_OBJECT (app1, handlebox2, "handlebox2"); + GLADE_HOOKUP_OBJECT (app1, toolbar2, "toolbar2"); + GLADE_HOOKUP_OBJECT (app1, connect_button1, "connect_button1"); + GLADE_HOOKUP_OBJECT (app1, run_button1, "run_button1"); + GLADE_HOOKUP_OBJECT (app1, msgs_button, "msgs_button"); + GLADE_HOOKUP_OBJECT (app1, restore_button, "restore_button"); + GLADE_HOOKUP_OBJECT (app1, label_button, "label_button"); + GLADE_HOOKUP_OBJECT (app1, vbox7, "vbox7"); + GLADE_HOOKUP_OBJECT (app1, scroll1, "scroll1"); + GLADE_HOOKUP_OBJECT (app1, text1, "text1"); + GLADE_HOOKUP_OBJECT (app1, hbox18, "hbox18"); + GLADE_HOOKUP_OBJECT (app1, label38, "label38"); + GLADE_HOOKUP_OBJECT (app1, entry1, "entry1"); + GLADE_HOOKUP_OBJECT (app1, hbox19, "hbox19"); + GLADE_HOOKUP_OBJECT (app1, frame1, "frame1"); + GLADE_HOOKUP_OBJECT (app1, label39, "label39"); + GLADE_HOOKUP_OBJECT (app1, frame2, "frame2"); + GLADE_HOOKUP_OBJECT (app1, status1, "status1"); + GLADE_HOOKUP_OBJECT_NO_REF (app1, tooltips, "tooltips"); + + gtk_widget_grab_focus (entry1); + gtk_widget_grab_default (entry1); + return app1; +} + +GtkWidget* +create_about1 (void) +{ + GtkWidget *about1; + GtkWidget *dialog_vbox5; + GtkWidget *vbox8; + GtkWidget *vbox9; + GtkWidget *about_head; + GtkWidget *hseparator1; + GtkWidget *copyright; + GtkWidget *authors; + GtkWidget *theme; + GtkWidget *dialog_action_area5; + GtkWidget *hbox20; + GtkWidget *label44; + GtkWidget *about_button; + + about1 = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (about1), _("About Bacula Console")); + gtk_window_set_modal (GTK_WINDOW (about1), TRUE); + + dialog_vbox5 = GTK_DIALOG (about1)->vbox; + gtk_widget_show (dialog_vbox5); + + vbox8 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox8); + gtk_box_pack_start (GTK_BOX (dialog_vbox5), vbox8, TRUE, TRUE, 0); + + vbox9 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox9); + gtk_box_pack_start (GTK_BOX (vbox8), vbox9, TRUE, TRUE, 0); + + about_head = gtk_label_new (_("Bacula Console 1.32c (24 Oct 03)\n")); + gtk_widget_show (about_head); + gtk_box_pack_start (GTK_BOX (vbox9), about_head, FALSE, FALSE, 0); + + hseparator1 = gtk_hseparator_new (); + gtk_widget_show (hseparator1); + gtk_box_pack_start (GTK_BOX (vbox9), hseparator1, FALSE, FALSE, 0); + + copyright = gtk_label_new (_("Copyright (c) 1999 - 2002, Kern Sibbald and John Walker")); + gtk_widget_show (copyright); + gtk_box_pack_start (GTK_BOX (vbox9), copyright, TRUE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (copyright), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (copyright), 0.1, 0.5); + + authors = gtk_label_new (_("Authors: Kern Sibbald and John Walker")); + gtk_widget_show (authors); + gtk_box_pack_start (GTK_BOX (vbox9), authors, TRUE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (authors), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (authors), 0.0400001, 0.5); + + theme = gtk_label_new (_("It comes by night and sucks the essence from your computers")); + gtk_widget_show (theme); + gtk_box_pack_start (GTK_BOX (vbox9), theme, TRUE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (theme), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (theme), 0.15, 0.5); + + dialog_action_area5 = GTK_DIALOG (about1)->action_area; + gtk_widget_show (dialog_action_area5); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area5), GTK_BUTTONBOX_END); + + hbox20 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox20); + gtk_container_add (GTK_CONTAINER (dialog_action_area5), hbox20); + + label44 = gtk_label_new (""); + gtk_widget_show (label44); + gtk_box_pack_start (GTK_BOX (hbox20), label44, TRUE, FALSE, 0); + + about_button = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (about_button); + gtk_box_pack_start (GTK_BOX (hbox20), about_button, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (about_button), 1); + GTK_WIDGET_SET_FLAGS (about_button, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) about_button, "clicked", + G_CALLBACK (on_about_button_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (about1, about1, "about1"); + GLADE_HOOKUP_OBJECT_NO_REF (about1, dialog_vbox5, "dialog_vbox5"); + GLADE_HOOKUP_OBJECT (about1, vbox8, "vbox8"); + GLADE_HOOKUP_OBJECT (about1, vbox9, "vbox9"); + GLADE_HOOKUP_OBJECT (about1, about_head, "about_head"); + GLADE_HOOKUP_OBJECT (about1, hseparator1, "hseparator1"); + GLADE_HOOKUP_OBJECT (about1, copyright, "copyright"); + GLADE_HOOKUP_OBJECT (about1, authors, "authors"); + GLADE_HOOKUP_OBJECT (about1, theme, "theme"); + GLADE_HOOKUP_OBJECT_NO_REF (about1, dialog_action_area5, "dialog_action_area5"); + GLADE_HOOKUP_OBJECT (about1, hbox20, "hbox20"); + GLADE_HOOKUP_OBJECT (about1, label44, "label44"); + GLADE_HOOKUP_OBJECT (about1, about_button, "about_button"); + + return about1; +} + +GtkWidget* +create_SelectDirectorDialog (void) +{ + GtkWidget *SelectDirectorDialog; + GtkWidget *dialog_vbox6; + GtkWidget *vbox10; + GtkWidget *label48; + GtkWidget *label47; + GtkWidget *combo1; + GList *combo1_items = NULL; + GtkWidget *dirselect; + GtkWidget *dialog_action_area2; + GtkWidget *hbox21; + GtkWidget *button11; + GtkWidget *label46; + GtkWidget *button13; + + SelectDirectorDialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (SelectDirectorDialog), _("Select Director")); + gtk_window_set_modal (GTK_WINDOW (SelectDirectorDialog), TRUE); + + dialog_vbox6 = GTK_DIALOG (SelectDirectorDialog)->vbox; + gtk_widget_show (dialog_vbox6); + + vbox10 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox10); + gtk_box_pack_start (GTK_BOX (dialog_vbox6), vbox10, TRUE, TRUE, 0); + + label48 = gtk_label_new (""); + gtk_widget_show (label48); + gtk_box_pack_start (GTK_BOX (vbox10), label48, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (label48), 0.48, 0.46); + + label47 = gtk_label_new (_("Select Director")); + gtk_widget_show (label47); + gtk_box_pack_start (GTK_BOX (vbox10), label47, FALSE, FALSE, 0); + + combo1 = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo1)->popwin), + "GladeParentKey", combo1); + gtk_widget_show (combo1); + gtk_box_pack_start (GTK_BOX (vbox10), combo1, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (combo1), 6); + combo1_items = g_list_append (combo1_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo1), combo1_items); + g_list_free (combo1_items); + + dirselect = GTK_COMBO (combo1)->entry; + gtk_widget_show (dirselect); + + dialog_action_area2 = GTK_DIALOG (SelectDirectorDialog)->action_area; + gtk_widget_show (dialog_action_area2); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area2), GTK_BUTTONBOX_END); + + hbox21 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox21); + gtk_container_add (GTK_CONTAINER (dialog_action_area2), hbox21); + + button11 = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (button11); + gtk_box_pack_start (GTK_BOX (hbox21), button11, FALSE, FALSE, 0); + + label46 = gtk_label_new (_(" ")); + gtk_widget_show (label46); + gtk_box_pack_start (GTK_BOX (hbox21), label46, FALSE, FALSE, 0); + gtk_misc_set_padding (GTK_MISC (label46), 2, 0); + + button13 = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (button13); + gtk_box_pack_start (GTK_BOX (hbox21), button13, FALSE, FALSE, 0); + + g_signal_connect ((gpointer) button11, "clicked", + G_CALLBACK (on_select_director_OK_clicked), + NULL); + g_signal_connect ((gpointer) button13, "clicked", + G_CALLBACK (on_select_director_cancel_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (SelectDirectorDialog, SelectDirectorDialog, "SelectDirectorDialog"); + GLADE_HOOKUP_OBJECT_NO_REF (SelectDirectorDialog, dialog_vbox6, "dialog_vbox6"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, vbox10, "vbox10"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, label48, "label48"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, label47, "label47"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, combo1, "combo1"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, dirselect, "dirselect"); + GLADE_HOOKUP_OBJECT_NO_REF (SelectDirectorDialog, dialog_action_area2, "dialog_action_area2"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, hbox21, "hbox21"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, button11, "button11"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, label46, "label46"); + GLADE_HOOKUP_OBJECT (SelectDirectorDialog, button13, "button13"); + + return SelectDirectorDialog; +} + +GtkWidget* +create_RunDialog (void) +{ + GtkWidget *RunDialog; + GtkWidget *dialog_vbox7; + GtkWidget *vbox11; + GtkWidget *vbox12; + GtkWidget *label62; + GtkWidget *hbox28; + GtkWidget *hbox29; + GtkWidget *label63; + GtkWidget *combo_job; + GList *combo_job_items = NULL; + GtkWidget *entry_job; + GtkWidget *label64; + GtkWidget *combo_type; + GList *combo_type_items = NULL; + GtkWidget *entry_type; + GtkWidget *label65; + GtkWidget *hbox30; + GtkWidget *label66; + GtkWidget *combo_client; + GList *combo_client_items = NULL; + GtkWidget *entry_client; + GtkWidget *label67; + GtkWidget *hbox31; + GtkWidget *label68; + GtkWidget *combo_fileset; + GList *combo_fileset_items = NULL; + GtkWidget *entry_fileset; + GtkWidget *view_fileset_button; + GtkWidget *label69; + GtkWidget *hbox32; + GtkWidget *label70; + GtkWidget *combo_level; + GList *combo_level_items = NULL; + GtkWidget *entry_level; + GtkWidget *label71; + GtkWidget *hbox33; + GtkWidget *label72; + GtkWidget *combo_pool; + GList *combo_pool_items = NULL; + GtkWidget *entry_pool; + GtkWidget *label73; + GtkWidget *hbox39; + GtkWidget *label96; + GtkWidget *combo_storage; + GList *combo_storage_items = NULL; + GtkWidget *entry_storage; + GtkWidget *label97; + GtkWidget *hbox40; + GtkWidget *label98; + GtkWidget *combo_messages; + GList *combo_messages_items = NULL; + GtkWidget *entry_messages; + GtkWidget *label99; + GtkWidget *hbox34; + GtkWidget *label77; + GtkWidget *entry_where; + GtkWidget *label78; + GtkWidget *hbox41; + GtkWidget *label100; + GtkWidget *entry_when; + GtkWidget *label101; + GtkWidget *label84; + GtkWidget *dialog_action_area6; + GtkWidget *hbuttonbox1; + GtkWidget *run_ok; + GtkWidget *run_cancel; + + RunDialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (RunDialog), _("Run a Job")); + + dialog_vbox7 = GTK_DIALOG (RunDialog)->vbox; + gtk_widget_show (dialog_vbox7); + + vbox11 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox11); + gtk_box_pack_start (GTK_BOX (dialog_vbox7), vbox11, TRUE, TRUE, 0); + + vbox12 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox12); + gtk_box_pack_start (GTK_BOX (vbox11), vbox12, TRUE, TRUE, 0); + + label62 = gtk_label_new (_("Run a Job")); + gtk_widget_show (label62); + gtk_box_pack_start (GTK_BOX (vbox12), label62, FALSE, FALSE, 2); + gtk_misc_set_padding (GTK_MISC (label62), 0, 9); + + hbox28 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox28); + gtk_box_pack_start (GTK_BOX (vbox12), hbox28, FALSE, FALSE, 2); + + hbox29 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox29); + gtk_box_pack_start (GTK_BOX (hbox28), hbox29, TRUE, TRUE, 0); + + label63 = gtk_label_new (_("Job:")); + gtk_widget_show (label63); + gtk_box_pack_start (GTK_BOX (hbox29), label63, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label63), GTK_JUSTIFY_RIGHT); + + combo_job = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_job)->popwin), + "GladeParentKey", combo_job); + gtk_widget_show (combo_job); + gtk_box_pack_start (GTK_BOX (hbox29), combo_job, TRUE, TRUE, 1); + gtk_combo_set_value_in_list (GTK_COMBO (combo_job), TRUE, FALSE); + combo_job_items = g_list_append (combo_job_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_job), combo_job_items); + g_list_free (combo_job_items); + + entry_job = GTK_COMBO (combo_job)->entry; + gtk_widget_show (entry_job); + gtk_editable_set_editable (GTK_EDITABLE (entry_job), FALSE); + + label64 = gtk_label_new (_(" Type:")); + gtk_widget_show (label64); + gtk_box_pack_start (GTK_BOX (hbox29), label64, FALSE, FALSE, 0); + + combo_type = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_type)->popwin), + "GladeParentKey", combo_type); + gtk_widget_show (combo_type); + gtk_box_pack_start (GTK_BOX (hbox29), combo_type, FALSE, FALSE, 6); + gtk_combo_set_value_in_list (GTK_COMBO (combo_type), TRUE, FALSE); + combo_type_items = g_list_append (combo_type_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_type), combo_type_items); + g_list_free (combo_type_items); + + entry_type = GTK_COMBO (combo_type)->entry; + gtk_widget_show (entry_type); + gtk_editable_set_editable (GTK_EDITABLE (entry_type), FALSE); + + label65 = gtk_label_new (_(" ")); + gtk_widget_show (label65); + gtk_box_pack_start (GTK_BOX (hbox28), label65, FALSE, FALSE, 30); + + hbox30 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox30); + gtk_box_pack_start (GTK_BOX (vbox12), hbox30, TRUE, TRUE, 0); + + label66 = gtk_label_new (_("Client:")); + gtk_widget_show (label66); + gtk_box_pack_start (GTK_BOX (hbox30), label66, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label66), GTK_JUSTIFY_RIGHT); + + combo_client = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_client)->popwin), + "GladeParentKey", combo_client); + gtk_widget_show (combo_client); + gtk_box_pack_start (GTK_BOX (hbox30), combo_client, TRUE, TRUE, 1); + gtk_combo_set_value_in_list (GTK_COMBO (combo_client), TRUE, FALSE); + combo_client_items = g_list_append (combo_client_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_client), combo_client_items); + g_list_free (combo_client_items); + + entry_client = GTK_COMBO (combo_client)->entry; + gtk_widget_show (entry_client); + gtk_editable_set_editable (GTK_EDITABLE (entry_client), FALSE); + + label67 = gtk_label_new (_(" ")); + gtk_widget_show (label67); + gtk_box_pack_start (GTK_BOX (hbox30), label67, FALSE, FALSE, 123); + + hbox31 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox31); + gtk_box_pack_start (GTK_BOX (vbox12), hbox31, TRUE, TRUE, 2); + + label68 = gtk_label_new (_("FileSet: ")); + gtk_widget_show (label68); + gtk_box_pack_start (GTK_BOX (hbox31), label68, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label68), GTK_JUSTIFY_RIGHT); + + combo_fileset = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_fileset)->popwin), + "GladeParentKey", combo_fileset); + gtk_widget_show (combo_fileset); + gtk_box_pack_start (GTK_BOX (hbox31), combo_fileset, TRUE, TRUE, 0); + gtk_combo_set_value_in_list (GTK_COMBO (combo_fileset), TRUE, FALSE); + combo_fileset_items = g_list_append (combo_fileset_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_fileset), combo_fileset_items); + g_list_free (combo_fileset_items); + + entry_fileset = GTK_COMBO (combo_fileset)->entry; + gtk_widget_show (entry_fileset); + gtk_editable_set_editable (GTK_EDITABLE (entry_fileset), FALSE); + + view_fileset_button = gtk_button_new_with_mnemonic (_(" View FileSet ")); + gtk_widget_show (view_fileset_button); + gtk_box_pack_start (GTK_BOX (hbox31), view_fileset_button, FALSE, TRUE, 10); + + label69 = gtk_label_new (_(" ")); + gtk_widget_show (label69); + gtk_box_pack_start (GTK_BOX (hbox31), label69, FALSE, FALSE, 65); + + hbox32 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox32); + gtk_box_pack_start (GTK_BOX (vbox12), hbox32, TRUE, TRUE, 2); + + label70 = gtk_label_new (_("Level:")); + gtk_widget_show (label70); + gtk_box_pack_start (GTK_BOX (hbox32), label70, FALSE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label70), GTK_JUSTIFY_RIGHT); + + combo_level = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_level)->popwin), + "GladeParentKey", combo_level); + gtk_widget_show (combo_level); + gtk_box_pack_start (GTK_BOX (hbox32), combo_level, TRUE, TRUE, 0); + gtk_combo_set_value_in_list (GTK_COMBO (combo_level), TRUE, FALSE); + combo_level_items = g_list_append (combo_level_items, (gpointer) ""); + combo_level_items = g_list_append (combo_level_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_level), combo_level_items); + g_list_free (combo_level_items); + + entry_level = GTK_COMBO (combo_level)->entry; + gtk_widget_show (entry_level); + gtk_editable_set_editable (GTK_EDITABLE (entry_level), FALSE); + + label71 = gtk_label_new (_(" ")); + gtk_widget_show (label71); + gtk_box_pack_start (GTK_BOX (hbox32), label71, FALSE, FALSE, 100); + + hbox33 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox33); + gtk_box_pack_start (GTK_BOX (vbox12), hbox33, TRUE, TRUE, 2); + + label72 = gtk_label_new (_("Pool:")); + gtk_widget_show (label72); + gtk_box_pack_start (GTK_BOX (hbox33), label72, FALSE, FALSE, 0); + + combo_pool = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_pool)->popwin), + "GladeParentKey", combo_pool); + gtk_widget_show (combo_pool); + gtk_box_pack_start (GTK_BOX (hbox33), combo_pool, TRUE, TRUE, 0); + gtk_combo_set_value_in_list (GTK_COMBO (combo_pool), TRUE, FALSE); + combo_pool_items = g_list_append (combo_pool_items, (gpointer) ""); + combo_pool_items = g_list_append (combo_pool_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_pool), combo_pool_items); + g_list_free (combo_pool_items); + + entry_pool = GTK_COMBO (combo_pool)->entry; + gtk_widget_show (entry_pool); + gtk_editable_set_editable (GTK_EDITABLE (entry_pool), FALSE); + + label73 = gtk_label_new (_(" ")); + gtk_widget_show (label73); + gtk_box_pack_start (GTK_BOX (hbox33), label73, FALSE, FALSE, 120); + + hbox39 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox39); + gtk_box_pack_start (GTK_BOX (vbox12), hbox39, TRUE, TRUE, 0); + + label96 = gtk_label_new (_("Storage:")); + gtk_widget_show (label96); + gtk_box_pack_start (GTK_BOX (hbox39), label96, FALSE, FALSE, 0); + + combo_storage = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_storage)->popwin), + "GladeParentKey", combo_storage); + gtk_widget_show (combo_storage); + gtk_box_pack_start (GTK_BOX (hbox39), combo_storage, TRUE, TRUE, 0); + gtk_combo_set_value_in_list (GTK_COMBO (combo_storage), TRUE, FALSE); + combo_storage_items = g_list_append (combo_storage_items, (gpointer) ""); + combo_storage_items = g_list_append (combo_storage_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_storage), combo_storage_items); + g_list_free (combo_storage_items); + + entry_storage = GTK_COMBO (combo_storage)->entry; + gtk_widget_show (entry_storage); + gtk_editable_set_editable (GTK_EDITABLE (entry_storage), FALSE); + + label97 = gtk_label_new (_(" ")); + gtk_widget_show (label97); + gtk_box_pack_start (GTK_BOX (hbox39), label97, FALSE, FALSE, 120); + + hbox40 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox40); + gtk_box_pack_start (GTK_BOX (vbox12), hbox40, TRUE, TRUE, 0); + + label98 = gtk_label_new (_("Messages:")); + gtk_widget_show (label98); + gtk_box_pack_start (GTK_BOX (hbox40), label98, FALSE, FALSE, 0); + + combo_messages = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (combo_messages)->popwin), + "GladeParentKey", combo_messages); + gtk_widget_show (combo_messages); + gtk_box_pack_start (GTK_BOX (hbox40), combo_messages, TRUE, TRUE, 0); + gtk_combo_set_value_in_list (GTK_COMBO (combo_messages), TRUE, FALSE); + combo_messages_items = g_list_append (combo_messages_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (combo_messages), combo_messages_items); + g_list_free (combo_messages_items); + + entry_messages = GTK_COMBO (combo_messages)->entry; + gtk_widget_show (entry_messages); + gtk_editable_set_editable (GTK_EDITABLE (entry_messages), FALSE); + + label99 = gtk_label_new (_(" ")); + gtk_widget_show (label99); + gtk_box_pack_start (GTK_BOX (hbox40), label99, FALSE, FALSE, 120); + + hbox34 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox34); + gtk_box_pack_start (GTK_BOX (vbox12), hbox34, TRUE, TRUE, 2); + + label77 = gtk_label_new (_("Where: ")); + gtk_widget_show (label77); + gtk_box_pack_start (GTK_BOX (hbox34), label77, FALSE, FALSE, 0); + + entry_where = gtk_entry_new (); + gtk_widget_show (entry_where); + gtk_box_pack_start (GTK_BOX (hbox34), entry_where, TRUE, TRUE, 0); + + label78 = gtk_label_new (_(" ")); + gtk_widget_show (label78); + gtk_box_pack_start (GTK_BOX (hbox34), label78, FALSE, FALSE, 120); + + hbox41 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox41); + gtk_box_pack_start (GTK_BOX (vbox11), hbox41, TRUE, TRUE, 0); + + label100 = gtk_label_new (_("When:")); + gtk_widget_show (label100); + gtk_box_pack_start (GTK_BOX (hbox41), label100, FALSE, FALSE, 0); + + entry_when = gtk_entry_new (); + gtk_widget_show (entry_when); + gtk_box_pack_start (GTK_BOX (hbox41), entry_when, TRUE, TRUE, 0); + + label101 = gtk_label_new (_(" ")); + gtk_widget_show (label101); + gtk_box_pack_start (GTK_BOX (hbox41), label101, FALSE, FALSE, 120); + + label84 = gtk_label_new (_(" ")); + gtk_widget_show (label84); + gtk_box_pack_start (GTK_BOX (vbox11), label84, FALSE, FALSE, 0); + + dialog_action_area6 = GTK_DIALOG (RunDialog)->action_area; + gtk_widget_show (dialog_action_area6); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area6), GTK_BUTTONBOX_END); + + hbuttonbox1 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox1); + gtk_container_add (GTK_CONTAINER (dialog_action_area6), hbuttonbox1); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox1), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (hbuttonbox1), 8); + + run_ok = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (run_ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), run_ok); + GTK_WIDGET_SET_FLAGS (run_ok, GTK_CAN_DEFAULT); + + run_cancel = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (run_cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), run_cancel); + GTK_WIDGET_SET_FLAGS (run_cancel, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) entry_job, "changed", + G_CALLBACK (on_entry_job_changed), + NULL); + g_signal_connect ((gpointer) view_fileset_button, "clicked", + G_CALLBACK (on_view_fileset_clicked), + NULL); + g_signal_connect ((gpointer) run_ok, "clicked", + G_CALLBACK (on_run_ok_clicked), + NULL); + g_signal_connect ((gpointer) run_cancel, "clicked", + G_CALLBACK (on_run_cancel_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (RunDialog, RunDialog, "RunDialog"); + GLADE_HOOKUP_OBJECT_NO_REF (RunDialog, dialog_vbox7, "dialog_vbox7"); + GLADE_HOOKUP_OBJECT (RunDialog, vbox11, "vbox11"); + GLADE_HOOKUP_OBJECT (RunDialog, vbox12, "vbox12"); + GLADE_HOOKUP_OBJECT (RunDialog, label62, "label62"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox28, "hbox28"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox29, "hbox29"); + GLADE_HOOKUP_OBJECT (RunDialog, label63, "label63"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_job, "combo_job"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_job, "entry_job"); + GLADE_HOOKUP_OBJECT (RunDialog, label64, "label64"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_type, "combo_type"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_type, "entry_type"); + GLADE_HOOKUP_OBJECT (RunDialog, label65, "label65"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox30, "hbox30"); + GLADE_HOOKUP_OBJECT (RunDialog, label66, "label66"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_client, "combo_client"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_client, "entry_client"); + GLADE_HOOKUP_OBJECT (RunDialog, label67, "label67"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox31, "hbox31"); + GLADE_HOOKUP_OBJECT (RunDialog, label68, "label68"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_fileset, "combo_fileset"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_fileset, "entry_fileset"); + GLADE_HOOKUP_OBJECT (RunDialog, view_fileset_button, "view_fileset_button"); + GLADE_HOOKUP_OBJECT (RunDialog, label69, "label69"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox32, "hbox32"); + GLADE_HOOKUP_OBJECT (RunDialog, label70, "label70"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_level, "combo_level"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_level, "entry_level"); + GLADE_HOOKUP_OBJECT (RunDialog, label71, "label71"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox33, "hbox33"); + GLADE_HOOKUP_OBJECT (RunDialog, label72, "label72"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_pool, "combo_pool"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_pool, "entry_pool"); + GLADE_HOOKUP_OBJECT (RunDialog, label73, "label73"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox39, "hbox39"); + GLADE_HOOKUP_OBJECT (RunDialog, label96, "label96"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_storage, "combo_storage"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_storage, "entry_storage"); + GLADE_HOOKUP_OBJECT (RunDialog, label97, "label97"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox40, "hbox40"); + GLADE_HOOKUP_OBJECT (RunDialog, label98, "label98"); + GLADE_HOOKUP_OBJECT (RunDialog, combo_messages, "combo_messages"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_messages, "entry_messages"); + GLADE_HOOKUP_OBJECT (RunDialog, label99, "label99"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox34, "hbox34"); + GLADE_HOOKUP_OBJECT (RunDialog, label77, "label77"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_where, "entry_where"); + GLADE_HOOKUP_OBJECT (RunDialog, label78, "label78"); + GLADE_HOOKUP_OBJECT (RunDialog, hbox41, "hbox41"); + GLADE_HOOKUP_OBJECT (RunDialog, label100, "label100"); + GLADE_HOOKUP_OBJECT (RunDialog, entry_when, "entry_when"); + GLADE_HOOKUP_OBJECT (RunDialog, label101, "label101"); + GLADE_HOOKUP_OBJECT (RunDialog, label84, "label84"); + GLADE_HOOKUP_OBJECT_NO_REF (RunDialog, dialog_action_area6, "dialog_action_area6"); + GLADE_HOOKUP_OBJECT (RunDialog, hbuttonbox1, "hbuttonbox1"); + GLADE_HOOKUP_OBJECT (RunDialog, run_ok, "run_ok"); + GLADE_HOOKUP_OBJECT (RunDialog, run_cancel, "run_cancel"); + + return RunDialog; +} + +GtkWidget* +create_restore_files (void) +{ + GtkWidget *restore_files; + GtkWidget *vbox13; + GtkWidget *scrolledwindow4; + GtkWidget *ctree2; + GtkWidget *hbox38; + GtkWidget *label88; + GtkWidget *entry25; + GtkWidget *hbox44; + GtkWidget *label105; + GtkWidget *restore_file; + GtkTooltips *tooltips; + + tooltips = gtk_tooltips_new (); + + restore_files = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (restore_files), _("Restore File Selection")); + gtk_window_set_modal (GTK_WINDOW (restore_files), TRUE); + + vbox13 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox13); + gtk_container_add (GTK_CONTAINER (restore_files), vbox13); + + scrolledwindow4 = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolledwindow4); + gtk_box_pack_start (GTK_BOX (vbox13), scrolledwindow4, TRUE, TRUE, 0); + GTK_WIDGET_UNSET_FLAGS (scrolledwindow4, GTK_CAN_FOCUS); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow4), GTK_SHADOW_IN); + + ctree2 = gtk_tree_view_new (); + gtk_widget_show (ctree2); + gtk_container_add (GTK_CONTAINER (scrolledwindow4), ctree2); + + hbox38 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox38); + gtk_box_pack_start (GTK_BOX (vbox13), hbox38, FALSE, TRUE, 0); + + label88 = gtk_label_new (_(" cwd:")); + gtk_widget_show (label88); + gtk_box_pack_start (GTK_BOX (hbox38), label88, FALSE, TRUE, 0); + + entry25 = gtk_entry_new (); + gtk_widget_show (entry25); + gtk_box_pack_start (GTK_BOX (hbox38), entry25, TRUE, TRUE, 0); + GTK_WIDGET_SET_FLAGS (entry25, GTK_CAN_DEFAULT); + gtk_tooltips_set_tip (tooltips, entry25, _("Enter Commands Here"), NULL); + + hbox44 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox44); + gtk_box_pack_start (GTK_BOX (vbox13), hbox44, FALSE, TRUE, 0); + + label105 = gtk_label_new (_(" ")); + gtk_widget_show (label105); + gtk_box_pack_start (GTK_BOX (hbox44), label105, TRUE, FALSE, 0); + gtk_label_set_justify (GTK_LABEL (label105), GTK_JUSTIFY_FILL); + gtk_misc_set_padding (GTK_MISC (label105), 59, 0); + + restore_file = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (restore_file); + gtk_box_pack_start (GTK_BOX (hbox44), restore_file, TRUE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (restore_file), 9); + + g_signal_connect ((gpointer) entry25, "key_press_event", + G_CALLBACK (on_entry1_key_press_event), + NULL); + g_signal_connect ((gpointer) entry25, "key_release_event", + G_CALLBACK (on_entry1_key_release_event), + NULL); + g_signal_connect ((gpointer) restore_file, "clicked", + G_CALLBACK (on_restore_file_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (restore_files, restore_files, "restore_files"); + GLADE_HOOKUP_OBJECT (restore_files, vbox13, "vbox13"); + GLADE_HOOKUP_OBJECT (restore_files, scrolledwindow4, "scrolledwindow4"); + GLADE_HOOKUP_OBJECT (restore_files, ctree2, "ctree2"); + GLADE_HOOKUP_OBJECT (restore_files, hbox38, "hbox38"); + GLADE_HOOKUP_OBJECT (restore_files, label88, "label88"); + GLADE_HOOKUP_OBJECT (restore_files, entry25, "entry25"); + GLADE_HOOKUP_OBJECT (restore_files, hbox44, "hbox44"); + GLADE_HOOKUP_OBJECT (restore_files, label105, "label105"); + GLADE_HOOKUP_OBJECT (restore_files, restore_file, "restore_file"); + GLADE_HOOKUP_OBJECT_NO_REF (restore_files, tooltips, "tooltips"); + + gtk_widget_grab_focus (entry25); + gtk_widget_grab_default (entry25); + return restore_files; +} + +GtkWidget* +create_restore_dialog (void) +{ + GtkWidget *restore_dialog; + GtkWidget *dialog_vbox8; + GtkWidget *hbox42; + GtkWidget *frame3; + GtkWidget *hbox43; + GtkWidget *label102; + GtkWidget *vbox15; + GtkWidget *label103; + GtkWidget *rb_most_recent; + GSList *rb_most_recent_group = NULL; + GtkWidget *rb_jobs; + GSList *rb_jobs_group = NULL; + GtkWidget *rb_file; + GSList *rb_file_group = NULL; + GtkWidget *label104; + GtkWidget *label106; + GtkWidget *vbox14; + GtkWidget *apply_button; + GtkWidget *dialog_action_area7; + GtkWidget *hbuttonbox2; + GtkWidget *restore_ok; + GtkWidget *restore_cancel; + + restore_dialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (restore_dialog), _("Restore Files")); + gtk_window_set_modal (GTK_WINDOW (restore_dialog), TRUE); + + dialog_vbox8 = GTK_DIALOG (restore_dialog)->vbox; + gtk_widget_show (dialog_vbox8); + + hbox42 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox42); + gtk_box_pack_start (GTK_BOX (dialog_vbox8), hbox42, TRUE, TRUE, 0); + + frame3 = gtk_frame_new (NULL); + gtk_widget_show (frame3); + gtk_box_pack_start (GTK_BOX (hbox42), frame3, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (frame3), 8); + + hbox43 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox43); + gtk_container_add (GTK_CONTAINER (frame3), hbox43); + + label102 = gtk_label_new (_(" ")); + gtk_widget_show (label102); + gtk_box_pack_end (GTK_BOX (hbox43), label102, FALSE, FALSE, 0); + + vbox15 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox15); + gtk_box_pack_start (GTK_BOX (hbox43), vbox15, TRUE, TRUE, 0); + + label103 = gtk_label_new (""); + gtk_widget_show (label103); + gtk_box_pack_start (GTK_BOX (vbox15), label103, FALSE, FALSE, 0); + gtk_misc_set_padding (GTK_MISC (label103), 0, 2); + + rb_most_recent = gtk_radio_button_new_with_mnemonic (NULL, _("Select most recent backup")); + gtk_widget_show (rb_most_recent); + gtk_box_pack_start (GTK_BOX (vbox15), rb_most_recent, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (rb_most_recent), 3); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (rb_most_recent), rb_most_recent_group); + rb_most_recent_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (rb_most_recent)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (rb_most_recent), TRUE); + + rb_jobs = gtk_radio_button_new_with_mnemonic (NULL, _("Select list of Jobs")); + gtk_widget_show (rb_jobs); + gtk_box_pack_start (GTK_BOX (vbox15), rb_jobs, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (rb_jobs), 5); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (rb_jobs), rb_jobs_group); + rb_jobs_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (rb_jobs)); + + rb_file = gtk_radio_button_new_with_mnemonic (NULL, _("Find a specific file")); + gtk_widget_show (rb_file); + gtk_box_pack_start (GTK_BOX (vbox15), rb_file, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (rb_file), 4); + gtk_radio_button_set_group (GTK_RADIO_BUTTON (rb_file), rb_file_group); + rb_file_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (rb_file)); + + label104 = gtk_label_new (""); + gtk_widget_show (label104); + gtk_box_pack_start (GTK_BOX (vbox15), label104, FALSE, FALSE, 0); + + label106 = gtk_label_new (_("Select by:")); + gtk_widget_show (label106); + gtk_frame_set_label_widget (GTK_FRAME (frame3), label106); + gtk_label_set_justify (GTK_LABEL (label106), GTK_JUSTIFY_LEFT); + + vbox14 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox14); + gtk_box_pack_start (GTK_BOX (hbox42), vbox14, FALSE, FALSE, 0); + + apply_button = gtk_button_new_from_stock ("gtk-apply"); + gtk_widget_show (apply_button); + gtk_box_pack_start (GTK_BOX (vbox14), apply_button, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (apply_button), 50); + + dialog_action_area7 = GTK_DIALOG (restore_dialog)->action_area; + gtk_widget_show (dialog_action_area7); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area7), GTK_BUTTONBOX_END); + + hbuttonbox2 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox2); + gtk_container_add (GTK_CONTAINER (dialog_action_area7), hbuttonbox2); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox2), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (hbuttonbox2), 8); + + restore_ok = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (restore_ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), restore_ok); + GTK_WIDGET_SET_FLAGS (restore_ok, GTK_CAN_DEFAULT); + + restore_cancel = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (restore_cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox2), restore_cancel); + GTK_WIDGET_SET_FLAGS (restore_cancel, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) apply_button, "clicked", + G_CALLBACK (on_apply_button_clicked), + NULL); + g_signal_connect ((gpointer) restore_ok, "clicked", + G_CALLBACK (on_restore_ok_clicked), + NULL); + g_signal_connect ((gpointer) restore_cancel, "clicked", + G_CALLBACK (on_restore_cancel_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (restore_dialog, restore_dialog, "restore_dialog"); + GLADE_HOOKUP_OBJECT_NO_REF (restore_dialog, dialog_vbox8, "dialog_vbox8"); + GLADE_HOOKUP_OBJECT (restore_dialog, hbox42, "hbox42"); + GLADE_HOOKUP_OBJECT (restore_dialog, frame3, "frame3"); + GLADE_HOOKUP_OBJECT (restore_dialog, hbox43, "hbox43"); + GLADE_HOOKUP_OBJECT (restore_dialog, label102, "label102"); + GLADE_HOOKUP_OBJECT (restore_dialog, vbox15, "vbox15"); + GLADE_HOOKUP_OBJECT (restore_dialog, label103, "label103"); + GLADE_HOOKUP_OBJECT (restore_dialog, rb_most_recent, "rb_most_recent"); + GLADE_HOOKUP_OBJECT (restore_dialog, rb_jobs, "rb_jobs"); + GLADE_HOOKUP_OBJECT (restore_dialog, rb_file, "rb_file"); + GLADE_HOOKUP_OBJECT (restore_dialog, label104, "label104"); + GLADE_HOOKUP_OBJECT (restore_dialog, label106, "label106"); + GLADE_HOOKUP_OBJECT (restore_dialog, vbox14, "vbox14"); + GLADE_HOOKUP_OBJECT (restore_dialog, apply_button, "apply_button"); + GLADE_HOOKUP_OBJECT_NO_REF (restore_dialog, dialog_action_area7, "dialog_action_area7"); + GLADE_HOOKUP_OBJECT (restore_dialog, hbuttonbox2, "hbuttonbox2"); + GLADE_HOOKUP_OBJECT (restore_dialog, restore_ok, "restore_ok"); + GLADE_HOOKUP_OBJECT (restore_dialog, restore_cancel, "restore_cancel"); + + return restore_dialog; +} + +GtkWidget* +create_label_dialog (void) +{ + GtkWidget *label_dialog; + GtkWidget *dialog_vbox9; + GtkWidget *vbox16; + GtkWidget *label106; + GtkWidget *hbox45; + GtkWidget *label107; + GtkWidget *label_combo_storage; + GList *label_combo_storage_items = NULL; + GtkWidget *entry26; + GtkWidget *hbox46; + GtkWidget *label109; + GtkWidget *label_combo_pool; + GList *label_combo_pool_items = NULL; + GtkWidget *entry27; + GtkWidget *hbox47; + GtkWidget *label111; + GtkWidget *label_entry_volume; + GtkWidget *hbox48; + GtkWidget *slot1; + GtkObject *label_slot_adj; + GtkWidget *label_slot; + GtkWidget *label113; + GtkWidget *dialog_action_area8; + GtkWidget *hbuttonbox3; + GtkWidget *label_ok; + GtkWidget *label_cancel; + + label_dialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (label_dialog), _("Label a Volume")); + gtk_window_set_modal (GTK_WINDOW (label_dialog), TRUE); + + dialog_vbox9 = GTK_DIALOG (label_dialog)->vbox; + gtk_widget_show (dialog_vbox9); + + vbox16 = gtk_vbox_new (FALSE, 0); + gtk_widget_show (vbox16); + gtk_box_pack_start (GTK_BOX (dialog_vbox9), vbox16, FALSE, TRUE, 0); + + label106 = gtk_label_new (_("Label a Volume")); + gtk_widget_show (label106); + gtk_box_pack_start (GTK_BOX (vbox16), label106, FALSE, FALSE, 0); + gtk_misc_set_padding (GTK_MISC (label106), 0, 9); + + hbox45 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox45); + gtk_box_pack_start (GTK_BOX (vbox16), hbox45, FALSE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox45), 5); + + label107 = gtk_label_new (_("Storage:")); + gtk_widget_show (label107); + gtk_box_pack_start (GTK_BOX (hbox45), label107, TRUE, TRUE, 0); + gtk_misc_set_alignment (GTK_MISC (label107), 0.15, 0.5); + + label_combo_storage = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (label_combo_storage)->popwin), + "GladeParentKey", label_combo_storage); + gtk_widget_show (label_combo_storage); + gtk_box_pack_start (GTK_BOX (hbox45), label_combo_storage, TRUE, TRUE, 15); + gtk_combo_set_value_in_list (GTK_COMBO (label_combo_storage), TRUE, FALSE); + label_combo_storage_items = g_list_append (label_combo_storage_items, (gpointer) ""); + label_combo_storage_items = g_list_append (label_combo_storage_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (label_combo_storage), label_combo_storage_items); + g_list_free (label_combo_storage_items); + + entry26 = GTK_COMBO (label_combo_storage)->entry; + gtk_widget_show (entry26); + gtk_editable_set_editable (GTK_EDITABLE (entry26), FALSE); + + hbox46 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox46); + gtk_box_pack_start (GTK_BOX (vbox16), hbox46, FALSE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox46), 5); + + label109 = gtk_label_new (_("Pool:")); + gtk_widget_show (label109); + gtk_box_pack_start (GTK_BOX (hbox46), label109, TRUE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label109), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label109), 0.12, 0.5); + + label_combo_pool = gtk_combo_new (); + g_object_set_data (G_OBJECT (GTK_COMBO (label_combo_pool)->popwin), + "GladeParentKey", label_combo_pool); + gtk_widget_show (label_combo_pool); + gtk_box_pack_start (GTK_BOX (hbox46), label_combo_pool, TRUE, TRUE, 14); + gtk_combo_set_value_in_list (GTK_COMBO (label_combo_pool), TRUE, FALSE); + label_combo_pool_items = g_list_append (label_combo_pool_items, (gpointer) ""); + label_combo_pool_items = g_list_append (label_combo_pool_items, (gpointer) ""); + gtk_combo_set_popdown_strings (GTK_COMBO (label_combo_pool), label_combo_pool_items); + g_list_free (label_combo_pool_items); + + entry27 = GTK_COMBO (label_combo_pool)->entry; + gtk_widget_show (entry27); + gtk_editable_set_editable (GTK_EDITABLE (entry27), FALSE); + + hbox47 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox47); + gtk_box_pack_start (GTK_BOX (vbox16), hbox47, FALSE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox47), 5); + + label111 = gtk_label_new (_("Volume Name:")); + gtk_widget_show (label111); + gtk_box_pack_start (GTK_BOX (hbox47), label111, TRUE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (label111), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (label111), 0.17, 0.5); + + label_entry_volume = gtk_entry_new (); + gtk_widget_show (label_entry_volume); + gtk_box_pack_start (GTK_BOX (hbox47), label_entry_volume, TRUE, TRUE, 0); + + hbox48 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox48); + gtk_box_pack_start (GTK_BOX (vbox16), hbox48, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox48), 5); + + slot1 = gtk_label_new (_("Slot:")); + gtk_widget_show (slot1); + gtk_box_pack_start (GTK_BOX (hbox48), slot1, FALSE, TRUE, 0); + gtk_label_set_justify (GTK_LABEL (slot1), GTK_JUSTIFY_LEFT); + gtk_misc_set_alignment (GTK_MISC (slot1), 0.09, 0.5); + + label_slot_adj = gtk_adjustment_new (0, 0, 10000, 1, 10, 10); + label_slot = gtk_spin_button_new (GTK_ADJUSTMENT (label_slot_adj), 1, 0); + gtk_widget_show (label_slot); + gtk_box_pack_start (GTK_BOX (hbox48), label_slot, TRUE, TRUE, 0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (label_slot), TRUE); + + label113 = gtk_label_new (_(" ")); + gtk_widget_show (label113); + gtk_box_pack_start (GTK_BOX (vbox16), label113, FALSE, FALSE, 0); + + dialog_action_area8 = GTK_DIALOG (label_dialog)->action_area; + gtk_widget_show (dialog_action_area8); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area8), GTK_BUTTONBOX_END); + + hbuttonbox3 = gtk_hbutton_box_new (); + gtk_widget_show (hbuttonbox3); + gtk_container_add (GTK_CONTAINER (dialog_action_area8), hbuttonbox3); + gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox3), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX (hbuttonbox3), 8); + + label_ok = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (label_ok); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), label_ok); + GTK_WIDGET_SET_FLAGS (label_ok, GTK_CAN_DEFAULT); + + label_cancel = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (label_cancel); + gtk_container_add (GTK_CONTAINER (hbuttonbox3), label_cancel); + GTK_WIDGET_SET_FLAGS (label_cancel, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) label_ok, "clicked", + G_CALLBACK (on_label_ok_clicked), + NULL); + g_signal_connect ((gpointer) label_cancel, "clicked", + G_CALLBACK (on_label_cancel_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (label_dialog, label_dialog, "label_dialog"); + GLADE_HOOKUP_OBJECT_NO_REF (label_dialog, dialog_vbox9, "dialog_vbox9"); + GLADE_HOOKUP_OBJECT (label_dialog, vbox16, "vbox16"); + GLADE_HOOKUP_OBJECT (label_dialog, label106, "label106"); + GLADE_HOOKUP_OBJECT (label_dialog, hbox45, "hbox45"); + GLADE_HOOKUP_OBJECT (label_dialog, label107, "label107"); + GLADE_HOOKUP_OBJECT (label_dialog, label_combo_storage, "label_combo_storage"); + GLADE_HOOKUP_OBJECT (label_dialog, entry26, "entry26"); + GLADE_HOOKUP_OBJECT (label_dialog, hbox46, "hbox46"); + GLADE_HOOKUP_OBJECT (label_dialog, label109, "label109"); + GLADE_HOOKUP_OBJECT (label_dialog, label_combo_pool, "label_combo_pool"); + GLADE_HOOKUP_OBJECT (label_dialog, entry27, "entry27"); + GLADE_HOOKUP_OBJECT (label_dialog, hbox47, "hbox47"); + GLADE_HOOKUP_OBJECT (label_dialog, label111, "label111"); + GLADE_HOOKUP_OBJECT (label_dialog, label_entry_volume, "label_entry_volume"); + GLADE_HOOKUP_OBJECT (label_dialog, hbox48, "hbox48"); + GLADE_HOOKUP_OBJECT (label_dialog, slot1, "slot1"); + GLADE_HOOKUP_OBJECT (label_dialog, label_slot, "label_slot"); + GLADE_HOOKUP_OBJECT (label_dialog, label113, "label113"); + GLADE_HOOKUP_OBJECT_NO_REF (label_dialog, dialog_action_area8, "dialog_action_area8"); + GLADE_HOOKUP_OBJECT (label_dialog, hbuttonbox3, "hbuttonbox3"); + GLADE_HOOKUP_OBJECT (label_dialog, label_ok, "label_ok"); + GLADE_HOOKUP_OBJECT (label_dialog, label_cancel, "label_cancel"); + + return label_dialog; +} + diff --git a/bacula/src/gnome2-console/interface.h b/bacula/src/gnome2-console/interface.h new file mode 100644 index 0000000000..f9853e1742 --- /dev/null +++ b/bacula/src/gnome2-console/interface.h @@ -0,0 +1,11 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +GtkWidget* create_app1 (void); +GtkWidget* create_about1 (void); +GtkWidget* create_SelectDirectorDialog (void); +GtkWidget* create_RunDialog (void); +GtkWidget* create_restore_files (void); +GtkWidget* create_restore_dialog (void); +GtkWidget* create_label_dialog (void); diff --git a/bacula/src/gnome2-console/support.c b/bacula/src/gnome2-console/support.c new file mode 100644 index 0000000000..7f065549dc --- /dev/null +++ b/bacula/src/gnome2-console/support.c @@ -0,0 +1,115 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include + +#include "support.h" + +GtkWidget* +lookup_widget (GtkWidget *widget, + const gchar *widget_name) +{ + GtkWidget *parent, *found_widget; + + for (;;) + { + if (GTK_IS_MENU (widget)) + parent = gtk_menu_get_attach_widget (GTK_MENU (widget)); + else + parent = widget->parent; + if (!parent) + parent = (GtkWidget *)g_object_get_data (G_OBJECT (widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget), + widget_name); + if (!found_widget) + g_warning ("Widget not found: %s", widget_name); + return found_widget; +} + +/* This is an internally used function to create pixmaps. */ +GtkWidget* +create_pixmap (GtkWidget *widget, + const gchar *filename) +{ + GtkWidget *pixmap; + gchar *pathname; + + if (!filename || !filename[0]) + return gtk_image_new (); + + pathname = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP, + filename, TRUE, NULL); + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return gtk_image_new (); + } + + pixmap = gtk_image_new_from_file (pathname); + g_free (pathname); + return pixmap; +} + +/* This is an internally used function to create pixmaps. */ +GdkPixbuf* +create_pixbuf (const gchar *filename) +{ + gchar *pathname = NULL; + GdkPixbuf *pixbuf; + GError *error = NULL; + + if (!filename || !filename[0]) + return NULL; + + pathname = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP, + filename, TRUE, NULL); + + if (!pathname) + { + g_warning (_("Couldn't find pixmap file: %s"), filename); + return NULL; + } + + pixbuf = gdk_pixbuf_new_from_file (pathname, &error); + if (!pixbuf) + { + fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", + pathname, error->message); + g_error_free (error); + } + g_free (pathname); + return pixbuf; +} + +/* This is used to set ATK action descriptions. */ +void +glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description) +{ + gint n_actions, i; + + n_actions = atk_action_get_n_actions (action); + for (i = 0; i < n_actions; i++) + { + if (!strcmp (atk_action_get_name (action, i), action_name)) + atk_action_set_description (action, i, description); + } +} + diff --git a/bacula/src/gnome2-console/support.h b/bacula/src/gnome2-console/support.h new file mode 100644 index 0000000000..13d1746904 --- /dev/null +++ b/bacula/src/gnome2-console/support.h @@ -0,0 +1,37 @@ +/* + * DO NOT EDIT THIS FILE - it is generated by Glade. + */ + +#include + +/* + * Public Functions. + */ + +/* + * This function returns a widget in a component created by Glade. + * Call it with the toplevel widget in the component (i.e. a window/dialog), + * or alternatively any widget in the component, and the name of the widget + * you want returned. + */ +GtkWidget* lookup_widget (GtkWidget *widget, + const gchar *widget_name); + + + +/* + * Private Functions. + */ + +/* This is used to create the pixmaps used in the interface. */ +GtkWidget* create_pixmap (GtkWidget *widget, + const gchar *filename); + +/* This is used to create the pixbufs used in the interface. */ +GdkPixbuf* create_pixbuf (const gchar *filename); + +/* This is used to set ATK action descriptions. */ +void glade_set_atk_action_description (AtkAction *action, + const gchar *action_name, + const gchar *description); + diff --git a/bacula/src/gnome2-console/test-gnome-console.conf b/bacula/src/gnome2-console/test-gnome-console.conf new file mode 100644 index 0000000000..b2725a1f9f --- /dev/null +++ b/bacula/src/gnome2-console/test-gnome-console.conf @@ -0,0 +1,10 @@ +# +# Bacula User Agent (or Console) Configuration File +# + +Director { + Name = rufus-dir + DIRport = 8101 + address = rufus + Password = UA_password +} diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index e3e012b61c..88217eeb26 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -40,6 +40,7 @@ #define L_VERIFY_CATALOG 'C' /* verify from catalog */ #define L_VERIFY_INIT 'V' /* verify save (init DB) */ #define L_VERIFY_VOLUME_TO_CATALOG 'O' /* verify Volume to catalog entries */ +#define L_VERIFY_DISK_TO_CATALOG 'd' /* verify Disk attributes to catalog */ #define L_VERIFY_DATA 'A' /* verify data on volume */ #define L_BASE 'B' /* Base level job */ @@ -154,7 +155,8 @@ struct JCR { POOLMEM *fname; /* name to put into catalog */ int fn_printed; /* printed filename */ POOLMEM *stime; /* start time for incremental/differential */ - JOB_DBR jr; /* Job record in Database */ + JOB_DBR jr; /* Job DB record for current job */ + JOB_DBR *verify_jr; /* Pointer to target job */ uint32_t RestoreJobId; /* Id specified by UA */ POOLMEM *client_uname; /* client uname */ int replace; /* Replace option */ diff --git a/bacula/src/lib/bpipe.c b/bacula/src/lib/bpipe.c index a44290b75d..1501e18d2c 100644 --- a/bacula/src/lib/bpipe.c +++ b/bacula/src/lib/bpipe.c @@ -92,6 +92,9 @@ BPIPE *open_bpipe(char *prog, int wait, char *mode) dup2(readp[1], 1); /* dup our read to his stdout */ dup2(readp[1], 2); /* and his stderr */ } + for (int i=3; i<=32; i++) { /* close any open file descriptors */ + close(i); + } execvp(bargv[0], bargv); /* call the program */ exit(errno); /* shouldn't get here */ diff --git a/bacula/src/lib/cram-md5.c b/bacula/src/lib/cram-md5.c index 948892dc24..be1ed8db4c 100644 --- a/bacula/src/lib/cram-md5.c +++ b/bacula/src/lib/cram-md5.c @@ -96,6 +96,7 @@ int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need) if (sscanf(mp_chr(bs->msg), "auth cram-md5 %s ssl=%d\n", chal, &ssl_has) != 2) { ssl_has = BNET_SSL_NONE; if (sscanf(mp_chr(bs->msg), "auth cram-md5 %s\n", chal) != 1) { + bnet_fsend(bs, "1999 Authorization failed.\n"); Dmsg1(100, "Cannot scan challenge: %s\n", bs->msg); bmicrosleep(5, 0); return 0; diff --git a/bacula/src/lib/daemon.c b/bacula/src/lib/daemon.c index b5ced0cb79..7008d129ba 100644 --- a/bacula/src/lib/daemon.c +++ b/bacula/src/lib/daemon.c @@ -57,17 +57,10 @@ daemon_start() setsid(); /* In the PRODUCTION system, we close ALL - * file descriptors. It is useful - * for debugging to leave the STDOUT ane STDERR open. + * file descriptors except stdin, stdout, and stderr. */ - for (i=sysconf(_SC_OPEN_MAX)-1; i >=0; i--) { -#ifdef DEBUG - if (i != STDOUT_FILENO && i != STDERR_FILENO) { - close(i); - } -#else + for (i=sysconf(_SC_OPEN_MAX)-1; i > 2; i--) { close(i); -#endif } /* Move to root directory. For debug we stay diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index dc7c4723ff..98c03a86b5 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -158,12 +158,29 @@ void init_msg(JCR *jcr, MSGS *msg) { DEST *d, *dnew, *temp_chain = NULL; + int i, fd; + + /* + * Make sure we have fd's 0, 1, 2 open + * If we don't do this one of our sockets may open + * there and if we then use stdout, it could + * send total garbage to our socket. + * + */ + fd = open("/dev/null", O_RDONLY, 0644); + if (fd > 2) { + close(fd); + } else { + for(i=1; fd + i <= 2; i++) { + dup2(fd, fd+i); + } + } + /* * If msg is NULL, initialize global chain for STDOUT and syslog */ if (msg == NULL) { - int i; daemon_msgs = (MSGS *)malloc(sizeof(MSGS)); memset(daemon_msgs, 0, sizeof(MSGS)); for (i=1; i<=M_MAX; i++) { diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index 6b612deb0a..2c3ac1b43e 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -284,7 +284,7 @@ static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd str = &lc->str[0]; } for (i=0; msg_types[i].name; i++) { - if (strcmp(str, msg_types[i].name) == 0) { + if (strcasecmp(str, msg_types[i].name) == 0) { msg_type = msg_types[i].token; found = TRUE; break; @@ -678,7 +678,8 @@ parse_config(char *cf) if (i >= 0) { Dmsg2(150, "level=%d id=%s\n", level, lc->str); Dmsg1(150, "Keyword = %s\n", lc->str); - scan_err1(lc, "Keyword \"%s\" not permitted in this resource", 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); /* NOT REACHED */ } break; diff --git a/bacula/src/lib/tree.c b/bacula/src/lib/tree.c index 1927f26ba7..ba3242f683 100755 --- a/bacula/src/lib/tree.c +++ b/bacula/src/lib/tree.c @@ -32,6 +32,15 @@ #define MAXPATHLEN 1000 #endif +#undef Dmsg0 +#undef Dmsg1 +#undef Dmsg2 +#undef Dmsg3 +#define Dmsg0(n,f) +#define Dmsg1(n,f,a1) +#define Dmsg2(n,f,a1,a2) +#define Dmsg3(n,f,a1,a2,a3) + /* * This subroutine gets a big buffer. */ @@ -40,11 +49,13 @@ static void malloc_buf(TREE_ROOT *root, int size) struct s_mem *mem; mem = (struct s_mem *)malloc(size); + root->total_size += size; + root->blocks++; mem->next = root->mem; root->mem = mem; mem->mem = mem->first; mem->rem = (char *)mem + size - mem->mem; - Dmsg2(400, "malloc buf size=%d rem=%d\n", size, mem->rem); + Dmsg2(200, "malloc buf size=%d rem=%d\n", size, mem->rem); } @@ -65,9 +76,9 @@ TREE_ROOT *new_tree(int count) root = (TREE_ROOT *)malloc(sizeof(TREE_ROOT)); memset(root, 0, sizeof(TREE_ROOT)); root->type = TN_ROOT; - /* Assume filename = 20 characters average length */ - size = count * (BALIGN(sizeof(TREE_NODE)) + 20); - if (size > 10000000) { + /* Assume filename + node = 40 characters average length */ + size = count * (BALIGN(sizeof(TREE_NODE)) + 40); + if (count > 1000000 || size > 10000000) { size = 10000000; } Dmsg2(400, "count=%d size=%d\n", count, size); @@ -82,15 +93,20 @@ TREE_ROOT *new_tree(int count) TREE_NODE *new_tree_node(TREE_ROOT *root, int type) { TREE_NODE *node; - int size = BALIGN(sizeof(TREE_NODE)); + int asize = BALIGN(sizeof(TREE_NODE)); - if (root->mem->rem < size) { - malloc_buf(root, 20000); + if (root->mem->rem < asize) { + uint32_t mb_size; + if (root->total_size >= 1000000) { + mb_size = 1000000; + } else { + mb_size = 100000; } - - root->mem->rem -= size; + malloc_buf(root, mb_size); + } + root->mem->rem -= asize; node = (TREE_NODE *)root->mem->mem; - root->mem->mem += size; + root->mem->mem += asize; memset(node, 0, sizeof(TREE_NODE)); node->type = type; return node; @@ -108,7 +124,13 @@ static char *tree_alloc(TREE_ROOT *root, int size) int asize = BALIGN(size); if (root->mem->rem < asize) { - malloc_buf(root, 20000+asize); + uint32_t mb_size; + if (root->total_size >= 1000000) { + mb_size = 1000000; + } else { + mb_size = 100000; + } + malloc_buf(root, mb_size); } root->mem->rem -= asize; buf = root->mem->mem; @@ -130,6 +152,7 @@ void free_tree(TREE_ROOT *root) if (root->cached_path) { free_pool_memory(root->cached_path); } + Dmsg2(400, "Total size=%u blocks=%d\n", root->total_size, root->blocks); free(root); return; } @@ -137,7 +160,8 @@ void free_tree(TREE_ROOT *root) /* - * Insert a node in the tree + * Insert a node in the tree. This is the main subroutine + * called when building a tree. * */ TREE_NODE *insert_tree_node(char *path, TREE_NODE *node, @@ -145,14 +169,14 @@ TREE_NODE *insert_tree_node(char *path, TREE_NODE *node, { TREE_NODE *sibling; char *p, *q, *fname; - int len = strlen(path); + int path_len = strlen(path); Dmsg1(100, "insert_tree_node: %s\n", path); /* * If trailing slash, strip it */ - if (len > 0) { - q = path + len - 1; + if (path_len > 0) { + q = path + path_len - 1; if (*q == '/') { *q = 0; /* strip trailing slash */ } else { @@ -167,11 +191,12 @@ TREE_NODE *insert_tree_node(char *path, TREE_NODE *node, if (!parent) { /* if no parent, we need to make one */ *p = 0; /* terminate path */ Dmsg1(100, "make_tree_path for %s\n", path); - if ((int)strlen(path) == root->cached_path_len && + path_len = strlen(path); /* get new length */ + if (path_len == root->cached_path_len && strcmp(path, root->cached_path) == 0) { parent = root->cached_parent; } else { - root->cached_path_len = strlen(path); + root->cached_path_len = path_len; pm_strcpy(&root->cached_path, path); parent = make_tree_path(path, root); root->cached_parent = parent; @@ -188,9 +213,11 @@ TREE_NODE *insert_tree_node(char *path, TREE_NODE *node, Dmsg1(100, "No / found: %s\n", path); } + uint16_t fname_len = strlen(fname); for (sibling=parent->child; sibling; sibling=sibling->sibling) { Dmsg2(100, "sibling->fname=%s fname=%s\n", sibling->fname, fname); - if (strcmp(sibling->fname, fname) == 0) { + if (sibling->fname_len == fname_len && + strcmp(sibling->fname, fname) == 0) { Dmsg1(100, "make_tree_path: found parent=%s\n", parent->fname); if (q) { /* if trailing slash on entry */ *q = '/'; /* restore it */ @@ -234,9 +261,11 @@ TREE_NODE *make_tree_path(char *path, TREE_ROOT *root) type = TN_DIR_NLS; } /* Is it already a sibling? */ + uint16_t fname_len = strlen(fname); for (sibling=parent->child; sibling; sibling=sibling->sibling) { Dmsg2(100, "sibling->fname=%s fname=%s\n", sibling->fname, fname); - if (strcmp(sibling->fname, fname) == 0) { + if (sibling->fname_len == fname_len && + strcmp(sibling->fname, fname) == 0) { Dmsg1(100, "make_tree_path: found parent=%s\n", parent->fname); return sibling; } @@ -256,7 +285,8 @@ void append_tree_node(char *fname, TREE_NODE *node, TREE_ROOT *root, TREE_NODE * TREE_NODE *child; Dmsg1(100, "append_tree_node: %s\n", fname); - node->fname = tree_alloc(root, strlen(fname) + 1); + node->fname_len = strlen(fname); + node->fname = tree_alloc(root, node->fname_len + 1); strcpy(node->fname, fname); node->parent = parent; if (!parent->child) { @@ -280,6 +310,8 @@ item_link: return; } +#ifdef SLOW_WAY +/* Moved to tree.h to eliminate subroutine call */ TREE_NODE *first_tree_node(TREE_ROOT *root) { return root->first; @@ -289,6 +321,7 @@ TREE_NODE *next_tree_node(TREE_NODE *node) { return node->next; } +#endif void print_tree(char *path, TREE_NODE *tree) @@ -435,6 +468,7 @@ int main(int argc, char *argv[]) root = new_tree(); root->fname = tree_alloc(root, 1); *root->fname = 0; + root->fname_len = 0; FillDirectoryTree("/home/kern/bacula/k", root, NULL); diff --git a/bacula/src/lib/tree.h b/bacula/src/lib/tree.h index 2fd3386b02..e92c567216 100644 --- a/bacula/src/lib/tree.h +++ b/bacula/src/lib/tree.h @@ -31,12 +31,17 @@ struct s_mem { char first[1]; /* first byte */ }; +/* + * Keep this node as small as possible because + * there is one for each file. + */ struct s_tree_node { char *fname; /* file name */ int32_t FileIndex; /* file index */ uint32_t JobId; /* JobId */ - short type; /* node type */ - short extract; /* set if extracting */ + uint16_t fname_len; /* length of string */ + uint8_t type; /* node type */ + bool extract; /* set if extracting */ struct s_tree_node *parent; struct s_tree_node *sibling; struct s_tree_node *child; @@ -48,8 +53,9 @@ struct s_tree_root { char *fname; /* file name */ int32_t FileIndex; /* file index */ uint32_t JobId; /* JobId */ - short type; /* node type */ - short extract; /* set if extracting */ + uint16_t fname_len; /* length of string */ + uint8_t type; /* node type */ + bool extract; /* set if extracting */ struct s_tree_node *parent; struct s_tree_node *sibling; struct s_tree_node *child; @@ -59,6 +65,8 @@ struct s_tree_root { struct s_tree_node *first; /* first entry in the tree */ struct s_tree_node *last; /* last entry in tree */ struct s_mem *mem; /* tree memory */ + uint32_t total_size; /* total bytes allocated */ + uint32_t blocks; /* total mallocs */ int cached_path_len; /* length of cached path */ char *cached_path; /* cached current path */ TREE_NODE *cached_parent; /* cached parent for above path */ @@ -77,11 +85,17 @@ TREE_NODE *new_tree_node(TREE_ROOT *root, int type); TREE_NODE *insert_tree_node(char *fname, TREE_NODE *node, TREE_ROOT *root, TREE_NODE *parent); TREE_NODE *make_tree_path(char *path, TREE_ROOT *root); -TREE_NODE *first_tree_node(TREE_ROOT *root); -TREE_NODE *next_tree_node(TREE_NODE *node); TREE_NODE *tree_cwd(char *path, TREE_ROOT *root, TREE_NODE *node); TREE_NODE *tree_relcwd(char *path, TREE_ROOT *root, TREE_NODE *node); void append_tree_node(char *path, TREE_NODE *node, TREE_ROOT *root, TREE_NODE *parent); void print_tree(char *path, TREE_NODE *root); void free_tree(TREE_ROOT *root); int tree_getpath(TREE_NODE *node, char *buf, int buf_size); + +#ifdef SLOW_WAY +TREE_NODE *first_tree_node(TREE_ROOT *root); +TREE_NODE *next_tree_node(TREE_NODE *node); +#else + #define first_tree_node(r) (r)->first + #define next_tree_node(n) (n)->next +#endif diff --git a/bacula/src/lib/util.c b/bacula/src/lib/util.c index 9c1ce536c3..6dc6015b26 100644 --- a/bacula/src/lib/util.c +++ b/bacula/src/lib/util.c @@ -38,18 +38,22 @@ /* Return true of buffer has all zero bytes */ int is_buf_zero(char *buf, int len) { - uint64_t *ip = (uint64_t *)buf; + uint64_t *ip; char *p; int i, len64, done, rem; + if (buf[0] != 0) { + return 0; + } + ip = (uint64_t *)buf; /* Optimize by checking uint64_t for zero */ - len64 = len >> sizeof(uint64_t); + len64 = len / sizeof(uint64_t); for (i=0; i < len64; i++) { if (ip[i] != 0) { return 0; } } - done = len64 << sizeof(uint64_t); /* bytes already checked */ + done = len64 * sizeof(uint64_t); /* bytes already checked */ p = buf + done; rem = len - done; for (i = 0; i < rem; i++) { @@ -141,32 +145,76 @@ int pm_strcpy(POOLMEM **pm, char *str) */ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen) { - char *termstat, jstat[2]; + char *jobstat; + char buf[100]; switch (JobStatus) { + case JS_Created: + jobstat = _("Created"); + break; + case JS_Running: + jobstat = _("Running"); + break; + case JS_Blocked: + jobstat = _("Blocked"); + break; case JS_Terminated: - termstat = _("OK"); + jobstat = _("OK"); break; case JS_FatalError: case JS_ErrorTerminated: - termstat = _("Error"); + jobstat = _("Error"); break; case JS_Error: - termstat = _("Non-fatal error"); + jobstat = _("Non-fatal error"); break; case JS_Canceled: - termstat = _("Canceled"); + jobstat = _("Canceled"); break; case JS_Differences: - termstat = _("Verify differences"); + jobstat = _("Verify differences"); + break; + case JS_WaitFD: + jobstat = _("Waiting on FD"); + break; + case JS_WaitSD: + jobstat = _("Wait on SD"); + break; + case JS_WaitMedia: + jobstat = _("Wait for new Volume"); + break; + case JS_WaitMount: + jobstat = _("Waiting for mount"); break; + case JS_WaitStoreRes: + jobstat = _("Waiting for Storage resource"); + break; + case JS_WaitJobRes: + jobstat = _("Waiting for Job resource"); + break; + case JS_WaitClientRes: + jobstat = _("Waiting for Client resource"); + break; + case JS_WaitMaxJobs: + jobstat = _("Waiting on Max Jobs"); + break; + case JS_WaitStartTime: + jobstat = _("Waiting for Start Time"); + break; + case JS_WaitPriority: + jobstat = _("Waiting on Priority"); + break; + default: - jstat[0] = last_job.JobStatus; - jstat[1] = 0; - termstat = jstat; + if (JobStatus == 0) { + buf[0] = 0; + } else { + bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus); + } + jobstat = buf; break; } - bstrncpy(msg, termstat, maxlen); + bstrncpy(msg, jobstat, maxlen); } /* @@ -259,6 +307,9 @@ char *job_level_to_str(int level) case L_VERIFY_VOLUME_TO_CATALOG: str = _("Verify Volume to Catalog"); break; + case L_VERIFY_DISK_TO_CATALOG: + str = _("Verify Disk to Catalog"); + break; case L_VERIFY_DATA: str = _("Verify Data"); break; @@ -430,6 +481,7 @@ void make_session_key(char *key, char *seed, int mode) * %n = Unadorned Job name * %t = Job type (Backup, ...) * %r = Recipients + * %v = Volume name * * omsg = edited output message * imsg = input string containing edit codes (%x) @@ -488,6 +540,13 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to) case 't': str = job_type_to_str(jcr->JobType); break; + case 'v': + if (jcr->VolumeName && jcr->VolumeName[0]) { + str = jcr->VolumeName; + } else { + str = ""; + } + break; default: add[0] = '%'; add[1] = *p; diff --git a/bacula/src/lib/var.c b/bacula/src/lib/var.c index 2b0bcb1400..8022a0ab4e 100644 --- a/bacula/src/lib/var.c +++ b/bacula/src/lib/var.c @@ -2605,21 +2605,13 @@ var_formatv( const char *fmt, va_list ap) { var_rc_t rc; - va_list apbak; char *cpBuf; - int nBuf; + int nBuf = 5000; /* argument sanity checks */ if (var == NULL || dst_ptr == NULL || fmt == NULL) return VAR_RC(VAR_ERR_INVALID_ARGUMENT); - /* determine formatting buffer length */ - apbak = ap; - nBuf = var_mvsnprintf(NULL, 0, fmt, ap); - ap = apbak; - if (nBuf == -1) - return VAR_RC(VAR_ERR_FORMATTING_FAILURE); - /* perform formatting */ if ((cpBuf = (char *)malloc(nBuf+1)) == NULL) return VAR_RC(VAR_ERR_OUT_OF_MEMORY); diff --git a/bacula/src/stored/.cvsignore b/bacula/src/stored/.cvsignore index a3104e4eea..6f6270578f 100644 --- a/bacula/src/stored/.cvsignore +++ b/bacula/src/stored/.cvsignore @@ -18,3 +18,4 @@ startit stopit changer.out mtx-changer +stored.conf diff --git a/bacula/src/stored/acquire.c b/bacula/src/stored/acquire.c index 940b0171f2..44e00b6bd7 100644 --- a/bacula/src/stored/acquire.c +++ b/bacula/src/stored/acquire.c @@ -294,7 +294,10 @@ int release_device(JCR *jcr, DEVICE *dev) /* If we are the only writer, write EOF after job */ if (dev->state & ST_LABEL) { Dmsg0(100, "dir_create_jobmedia_record. Release\n"); - dir_create_jobmedia_record(jcr); + if (!dir_create_jobmedia_record(jcr)) { + Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), + jcr->VolCatInfo.VolCatName, jcr->Job); + } if (dev_can_write(dev)) { weof_dev(dev, 1); } @@ -311,14 +314,17 @@ int release_device(JCR *jcr, DEVICE *dev) } } else if (dev->state & ST_LABEL) { Dmsg0(100, "dir_create_jobmedia_record. Release\n"); - dir_create_jobmedia_record(jcr); + if (!dir_create_jobmedia_record(jcr)) { + Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"), + jcr->VolCatInfo.VolCatName, jcr->Job); + } Dmsg0(200, "dir_update_vol_info. Release1\n"); dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */ dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */ } } else { - Jmsg2(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s, Volume %s not in use.\n"), + Jmsg2(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"), dev_name(dev), NPRT(jcr->VolumeName)); } detach_jcr_from_device(dev, jcr); diff --git a/bacula/src/stored/bcopy.c b/bacula/src/stored/bcopy.c index 36a4a45ce5..fc9452c16a 100644 --- a/bacula/src/stored/bcopy.c +++ b/bacula/src/stored/bcopy.c @@ -57,11 +57,11 @@ static void usage() "Usage: bcopy [-d debug_level] \n" " -b bootstrap specify a bootstrap file\n" " -c specify configuration file\n" -" -dnn set debug level to nn\n" +" -d set debug level to nn\n" " -v verbose\n" " -i specify input Volume names (separated by |)\n" " -o specify output Volume names (separated by |)\n" -" -w dir specify working directory (default /tmp)\n" +" -w specify working directory (default /tmp)\n" " -? print this message\n\n")); exit(1); } diff --git a/bacula/src/stored/bextract.c b/bacula/src/stored/bextract.c index 6f058b4c4a..3b8d4794fd 100644 --- a/bacula/src/stored/bextract.c +++ b/bacula/src/stored/bextract.c @@ -71,13 +71,13 @@ static void usage() { fprintf(stderr, "\nVersion: " VERSION " (" BDATE ")\n\n" -"Usage: bextract [-d debug_level] \n" +"Usage: bextract \n" " -b specify a bootstrap file\n" " -c specify a configuration file\n" -" -dnn set debug level to nn\n" +" -d set debug level to nn\n" " -e exclude list\n" " -i include list\n" -" -V specify Volume names (separated by |)\n" +" -V specify Volume names (separated by |)\n" " -? print this message\n\n"); exit(1); } diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index bdb2fab383..e815e3cd8b 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -131,11 +131,11 @@ DEV_BLOCK *new_block(DEVICE *dev) * Only the first block checksum error was reported. * If there are more, report it now. */ -void print_block_errors(JCR *jcr, DEV_BLOCK *block) +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block) { - if (block->checksum_errors > 1) { - Jmsg(jcr, M_ERROR, 0, _("%d block checksum errors ignored.\n"), - block->checksum_errors); + if (block->read_errors > 1) { + Jmsg(jcr, M_ERROR, 0, _("%d block read errors ignored.\n"), + block->read_errors); } } @@ -223,7 +223,10 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (strncmp(Id, BLKHDR1_ID, BLKHDR_ID_LENGTH) != 0) { Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"), BLKHDR1_ID, Id); - Emsg0(M_ERROR, 0, dev->errmsg); + if (block->read_errors == 0 || verbose >= 2) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } + block->read_errors++; return 0; } } else if (Id[3] == '2') { @@ -235,12 +238,18 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (strncmp(Id, BLKHDR2_ID, BLKHDR_ID_LENGTH) != 0) { Mmsg2(&dev->errmsg, _("Buffer ID error. Wanted: %s, got %s. Buffer discarded.\n"), BLKHDR2_ID, Id); - Emsg0(M_ERROR, 0, dev->errmsg); + if (block->read_errors == 0 || verbose >= 2) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } + block->read_errors++; return 0; } } else { Mmsg1(&dev->errmsg, _("Expected block-id BB01 or BB02, got %s. Buffer discarded.\n"), Id); - Emsg0(M_ERROR, 0, dev->errmsg); + if (block->read_errors == 0 || verbose >= 2) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } + block->read_errors++; return 0; } @@ -248,7 +257,10 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (block_len > MAX_BLOCK_LENGTH) { Mmsg1(&dev->errmsg, _("Block length %u is insane (too large), probably due to a bad archive.\n"), block_len); - Emsg0(M_ERROR, 0, dev->errmsg); + if (block->read_errors == 0 || verbose >= 2) { + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } + block->read_errors++; return 0; } @@ -268,14 +280,13 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) BlockCheckSum = bcrc32((uint8_t *)block->buf+BLKHDR_CS_LENGTH, block_len-BLKHDR_CS_LENGTH); if (BlockCheckSum != CheckSum) { - Dmsg2(00, "Block checksum mismatch: calc=%x blk=%x\n", BlockCheckSum, - CheckSum); Mmsg3(&dev->errmsg, _("Block checksum mismatch in block %u: calc=%x blk=%x\n"), (unsigned)BlockNumber, BlockCheckSum, CheckSum); - if (block->checksum_errors == 0) { + if (block->read_errors == 0 || verbose >= 2) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } - block->checksum_errors++; + block->read_errors++; + return 0; } } return 1; @@ -399,7 +410,8 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Jmsg(jcr, M_INFO, 0, _("User defined maximum volume capacity %s exceeded on device %s.\n"), edit_uint64(max_cap, ed1), dev->dev_name); block->write_failed = true; - weof_dev(dev, 2); /* end the tape */ + weof_dev(dev, 1); /* end the tape */ + weof_dev(dev, 1); dev->state |= (ST_EOF | ST_EOT | ST_WEOT); return 0; } @@ -472,7 +484,8 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) wlen, stat, dev->block_num, block->BlockNumber, dev->dev_errno, strerror(dev->dev_errno)); block->write_failed = true; - if (weof_dev(dev, 2) != 0) { /* end the tape */ + weof_dev(dev,1); + if (weof_dev(dev, 1) != 0) { /* end the tape */ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } dev->state |= (ST_EOF | ST_EOT | ST_WEOT); @@ -489,12 +502,12 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) if (dev->state & ST_TAPE && dev_cap(dev, CAP_BSR)) { /* Now back up over what we wrote and read the last block */ - if (bsf_dev(dev, 1) != 0 || bsf_dev(dev, 1) != 0) { + if (!bsf_dev(dev, 1) || !bsf_dev(dev, 1)) { ok = false; Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno)); } /* Backspace over record */ - if (ok && bsr_dev(dev, 1) != 0) { + if (ok && !bsr_dev(dev, 1)) { ok = false; Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"), strerror(dev->dev_errno)); /* @@ -585,7 +598,7 @@ int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_bloc ssize_t stat; int looping; uint32_t BlockNumber; - int retry = 0; + int retry; if (dev_state(dev, ST_EOT)) { return 0; @@ -601,12 +614,14 @@ reread: block->read_len = 0; return 0; } + retry = 0; do { stat = read(dev->fd, block->buf, (size_t)block->buf_len); if (retry == 1) { dev->VolCatInfo.VolCatErrors++; } } while (stat == -1 && (errno == EINTR || errno == EIO) && retry++ < 11); +// Dmsg1(000, "read stat = %d\n", stat); if (stat < 0) { Dmsg1(90, "Read device got: ERR=%s\n", strerror(errno)); clrerror_dev(dev, -1); @@ -646,7 +661,6 @@ reread: BlockNumber = block->BlockNumber + 1; if (!unser_block_header(jcr, dev, block)) { - Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); block->read_len = 0; return 0; } @@ -664,8 +678,8 @@ reread: /* Attempt to reposition to re-read the block */ if (dev->state & ST_TAPE) { Dmsg0(100, "Backspace record for reread.\n"); - if (bsr_dev(dev, 1) != 0) { - Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + if (!bsr_dev(dev, 1)) { + Jmsg(jcr, M_ERROR, 0, "%s", strerror_dev(dev)); block->read_len = 0; return 0; } diff --git a/bacula/src/stored/block.h b/bacula/src/stored/block.h index 6827457935..1c3c304bb0 100644 --- a/bacula/src/stored/block.h +++ b/bacula/src/stored/block.h @@ -96,10 +96,10 @@ struct DEV_BLOCK { uint32_t read_len; /* bytes read into buffer, if zero, block empty */ uint32_t VolSessionId; /* */ uint32_t VolSessionTime; /* */ + uint32_t read_errors; /* block errors (checksum, header, ...) */ int BlockVer; /* block version 1 or 2 */ bool write_failed; /* set if write failed */ bool block_read; /* set when block read */ - int checksum_errors; /* count of block checksum errors */ int32_t FirstIndex; /* first index this block */ int32_t LastIndex; /* last index this block */ char *bufp; /* pointer into buffer */ diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 897ff9e664..56f311f6be 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -102,17 +102,17 @@ static void usage() "Usage: bscan [-d debug_level] \n" " -b bootstrap specify a bootstrap file\n" " -c specify configuration file\n" -" -dnn set debug level to nn\n" +" -d set debug level to nn\n" " -m update media info in database\n" -" -n name specify the database name (default bacula)\n" -" -u user specify database user name (default bacula)\n" -" -p password specify database password (default none)\n" -" -h host specify database host (default NULL)\n" +" -n specify the database name (default bacula)\n" +" -u specify database user name (default bacula)\n" +" -p specify database host (default NULL)\n" " -r list records\n" " -s synchronize or store in database\n" " -v verbose\n" -" -V specify Volume names (separated by |)\n" -" -w dir specify working directory (default from conf file)\n" +" -V specify Volume names (separated by |)\n" +" -w specify working directory (default from conf file)\n" " -? print this message\n\n")); exit(1); } @@ -575,7 +575,7 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec) } fr.JobId = mjcr->JobId; fr.FileId = 0; - if (db_get_file_attributes_record(bjcr, db, attr->fname, &fr)) { + if (db_get_file_attributes_record(bjcr, db, attr->fname, NULL, &fr)) { if (verbose > 1) { Pmsg1(000, _("File record already exists for: %s\n"), attr->fname); } diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 7b2c5642fe..445fd46678 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -414,7 +414,7 @@ static void weofcmd() static void eomcmd() { if (!eod_dev(dev)) { - Pmsg1(0, _("Bad status from MTEOD. ERR=%s\n"), strerror_dev(dev)); + Pmsg1(0, "%s", strerror_dev(dev)); return; } else { Pmsg0(0, _("Moved to end of medium.\n")); @@ -435,10 +435,9 @@ static void eodcmd() */ static void bsfcmd() { - int stat; - if ((stat=bsf_dev(dev, 1)) < 0) { - Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror(errno)); + if (!bsf_dev(dev, 1)) { + Pmsg1(0, _("Bad status from bsf. ERR=%s\n"), strerror_dev(dev)); } else { Pmsg0(0, _("Backspaced one file.\n")); } @@ -449,10 +448,8 @@ static void bsfcmd() */ static void bsrcmd() { - int stat; - - if ((stat=bsr_dev(dev, 1)) < 0) { - Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), strerror(errno)); + if (!bsr_dev(dev, 1)) { + Pmsg1(0, _("Bad status from bsr. ERR=%s\n"), strerror_dev(dev)); } else { Pmsg0(0, _("Backspaced one record.\n")); } @@ -464,7 +461,7 @@ static void bsrcmd() */ static void capcmd() { - printf(_("Device capabilities:\n")); + printf(_("Configured device capabilities:\n")); printf("%sEOF ", dev->capabilities & CAP_EOF ? "" : "!"); printf("%sBSR ", dev->capabilities & CAP_BSR ? "" : "!"); printf("%sBSF ", dev->capabilities & CAP_BSF ? "" : "!"); @@ -613,17 +610,17 @@ static int re_read_block_test() } weofcmd(); weofcmd(); - if (bsf_dev(dev, 1) != 0) { - Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror(dev->dev_errno)); + if (!bsf_dev(dev, 1)) { + Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); goto bail_out; } - if (bsf_dev(dev, 1) != 0) { - Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror(dev->dev_errno)); + if (!bsf_dev(dev, 1)) { + Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); goto bail_out; } Pmsg0(0, "Backspaced over two EOFs OK.\n"); - if (bsr_dev(dev, 1) != 0) { - Pmsg1(0, _("Backspace record failed! ERR=%s\n"), strerror(dev->dev_errno)); + if (!bsr_dev(dev, 1)) { + Pmsg1(0, _("Backspace record failed! ERR=%s\n"), strerror_dev(dev)); goto bail_out; } Pmsg0(0, "Backspace record OK.\n"); @@ -780,7 +777,7 @@ all_done: "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 = 451136\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" @@ -1735,6 +1732,7 @@ static void helpcmd() { unsigned int i; usage(); + printf(_("Interactive commands:\n")); printf(_(" Command Description\n ======= ===========\n")); for (i=0; i \n" " -c set configuration file to file\n" -" -dnn set debug level to nn\n" +" -d set debug level to nn\n" " -s turn off signals\n" " -t open the default tape device\n" " -? print this message.\n" diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index dfde94eba2..bf7eb065fb 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -418,6 +418,9 @@ eod_dev(DEVICE *dev) dev->state |= ST_EOT; return 1; } + dev->dev_errno = errno; + Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"), + dev->dev_name, strerror(dev->dev_errno)); return 0; } #ifdef MTEOM @@ -465,7 +468,7 @@ eod_dev(DEVICE *dev) * the second EOF. */ if (dev_cap(dev, CAP_BSFATEOM)) { - stat = (bsf_dev(dev, 1) == 0); + stat = bsf_dev(dev, 1); dev->file++; /* keep same file */ } else { update_pos_dev(dev); /* update position */ @@ -830,12 +833,14 @@ bsf_dev(DEVICE *dev, int num) if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to bsf_dev. Archive not open\n")); + Mmsg0(&dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); return 0; } if (!(dev_state(dev, ST_TAPE))) { + Mmsg1(&dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"), + dev->dev_name); return 0; } Dmsg0(29, "bsf_dev\n"); @@ -1002,7 +1007,7 @@ weof_dev(DEVICE *dev, int num) if (dev->fd < 0) { dev->dev_errno = EBADF; - Mmsg0(&dev->errmsg, _("Bad call to weof_dev. Archive not open\n")); + Mmsg0(&dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n")); Emsg0(M_FATAL, 0, dev->errmsg); return -1; } @@ -1021,8 +1026,10 @@ weof_dev(DEVICE *dev, int num) dev->file_addr = 0; } else { clrerror_dev(dev, MTWEOF); + if (stat == -1) { Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"), dev->dev_name, strerror(dev->dev_errno)); + } } return stat; } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 143ee339bb..49bf888671 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -324,10 +324,10 @@ static int do_label(JCR *jcr, int relabel) label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); } else if (dev->state & ST_READ || dev->num_writers) { if (dev->state & ST_READ) { - bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), + bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"), dev_name(dev)); } else { - bnet_fsend(dir, _("3902 Device %s is busy with %d writer(s).\n"), + bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"), dev_name(dev), dev->num_writers); } } else { /* device not being used */ @@ -581,7 +581,7 @@ static int mount_cmd(JCR *jcr) } } else { pm_strcpy(&jcr->errmsg, dir->msg); - bnet_fsend(dir, _("3906 Error scanning mount command: %s\n"), jcr->errmsg); + bnet_fsend(dir, _("3909 Error scanning mount command: %s\n"), jcr->errmsg); } free_memory(dev_name); bnet_sig(dir, BNET_EOD); @@ -823,7 +823,7 @@ static int autochanger_cmd(JCR *jcr) } } else { /* error on scanf */ pm_strcpy(&jcr->errmsg, dir->msg); - bnet_fsend(dir, _("3907 Error scanning autocharger list command: %s\n"), + bnet_fsend(dir, _("3908 Error scanning autocharger list command: %s\n"), jcr->errmsg); } free_memory(devname); diff --git a/bacula/src/stored/fd_cmds.c b/bacula/src/stored/fd_cmds.c index e4eaf9df49..78b96b7d25 100644 --- a/bacula/src/stored/fd_cmds.c +++ b/bacula/src/stored/fd_cmds.c @@ -317,6 +317,7 @@ static int bootstrap_cmd(JCR *jcr) BSOCK *fd = jcr->file_bsock; POOLMEM *fname = get_pool_memory(PM_FNAME); FILE *bs; + int stat = 0; if (jcr->RestoreBootstrap) { unlink(jcr->RestoreBootstrap); @@ -345,15 +346,18 @@ static int bootstrap_cmd(JCR *jcr) if (debug_level > 20) { dump_bsr(jcr->bsr, true); } - return bnet_fsend(fd, OK_bootstrap); + stat = 1; bail_out: unlink(jcr->RestoreBootstrap); free_pool_memory(jcr->RestoreBootstrap); jcr->RestoreBootstrap = NULL; + if (stat) { + return bnet_fsend(fd, OK_bootstrap); + } else { bnet_fsend(fd, ERROR_bootstrap); return 0; - + } } diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index 8673fa4757..57902162b0 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -103,7 +103,7 @@ int job_cmd(JCR *jcr) */ ojcr = get_jcr_by_full_name(job); if (ojcr && !ojcr->authenticated) { - Dmsg2(000, "Found ojcr=0x%x Job %s\n", (unsigned)ojcr, job); + Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)ojcr, job); free_jcr(ojcr); } jcr->JobId = JobId; diff --git a/bacula/src/stored/match_bsr.c b/bacula/src/stored/match_bsr.c index ece77a6bd2..45dcc15cca 100755 --- a/bacula/src/stored/match_bsr.c +++ b/bacula/src/stored/match_bsr.c @@ -77,10 +77,16 @@ int match_bsr_block(BSR *bsr, DEV_BLOCK *block) return 1; /* cannot fast reject */ } - if (match_block_sesstime(bsr, bsr->sesstime, block)) { + for ( ; bsr; bsr=bsr->next) { + if (!match_block_sesstime(bsr, bsr->sesstime, block)) { + continue; + } + if (!match_block_sessid(bsr, bsr->sessid, block)) { + continue; + } return 1; } - return match_block_sessid(bsr, bsr->sessid, block); + return 0; } static int match_block_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_BLOCK *block) @@ -135,7 +141,7 @@ int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *se /* * Note, bsr->reposition is set by match_all when * a bsr is done. We turn it off if a match was - * found or if we cannot use poistioning + * found or if we cannot use positioning */ if (stat != 0 || !bsr->use_positioning) { bsr->reposition = false; @@ -157,10 +163,10 @@ BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev) if (!root_bsr || !root_bsr->use_positioning || !root_bsr->reposition || !dev_is_tape(dev)) { - Dmsg2(100, "use_pos=%d repos=%d\n", root_bsr->use_positioning, - root_bsr->reposition); + Dmsg2(100, "No nxt_bsr use_pos=%d repos=%d\n", root_bsr->use_positioning, root_bsr->reposition); return NULL; } + Dmsg2(100, "use_pos=%d repos=%d\n", root_bsr->use_positioning, root_bsr->reposition); root_bsr->mount_next_volume = false; for (bsr=root_bsr; bsr; bsr=bsr->next) { if (bsr->done || !match_volume(bsr, bsr->volume, &dev->VolHdr, 1)) { @@ -231,6 +237,34 @@ static BSR *find_smallest_volfile(BSR *found_bsr, BSR *bsr) return return_bsr; } +/* + * Called to tell the matcher that the end of + * the current file has been reached. + * The bsr argument is not used, but is included + * for consistency with the other match calls. + * + * Returns: true if we should reposition + * : false otherwise. + */ +bool match_set_eof(BSR *bsr, DEV_RECORD *rec) +{ + BSR *rbsr = rec->bsr; + Dmsg1(100, "match_set %d\n", rbsr != NULL); + if (!rbsr) { + return false; + } + rec->bsr = NULL; + rbsr->found++; + if (rbsr->count && rbsr->found >= rbsr->count) { + rbsr->done = true; + rbsr->root->reposition = true; + Dmsg2(100, "match_set_eof reposition count=%d found=%d\n", + rbsr->count, rbsr->found); + return true; + } + return false; +} + /* * Match all the components of current record * returns 1 on match @@ -243,33 +277,54 @@ static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, if (bsr->done) { goto no_match; } - if (bsr->count && bsr->count <= bsr->found) { - bsr->done = true; - bsr->root->reposition = true; - Dmsg0(100, "bsr done from count\n"); - goto no_match; - } if (!match_volume(bsr, bsr->volume, volrec, 1)) { goto no_match; } if (!match_volfile(bsr, bsr->volfile, rec, 1)) { + Dmsg2(100, "Fail on file. bsr=%d rec=%d\n", bsr->volfile->efile, + rec->File); goto no_match; } if (!match_sesstime(bsr, bsr->sesstime, rec, 1)) { + Dmsg2(100, "Fail on sesstime. bsr=%d rec=%d\n", + bsr->sesstime->sesstime, rec->VolSessionTime); goto no_match; } /* NOTE!! This test MUST come after the sesstime test */ if (!match_sessid(bsr, bsr->sessid, rec)) { + Dmsg2(100, "Fail on sessid. bsr=%d rec=%d\n", + bsr->sessid->sessid, rec->VolSessionId); goto no_match; } /* NOTE!! This test MUST come after sesstime and sessid tests */ if (!match_findex(bsr, bsr->FileIndex, rec, 1)) { + Dmsg2(100, "Fail on findex. bsr=%d rec=%d\n", + bsr->FileIndex->findex2, rec->FileIndex); goto no_match; } + /* + * If a count was specified and we have a FileIndex, assume + * it is a Bacula created bsr (or the equivalent). We + * then save the bsr where the match occurred so that + * after processing the record or records, we can update + * the found count. I.e. rec->bsr points to the bsr that + * satisfied the match. + */ + if (bsr->count && bsr->FileIndex) { + rec->bsr = bsr; + return 1; /* this is a complete match */ + } + + /* + * The selections below are not used by Bacula's + * restore command, and don't work because of + * the rec->bsr = bsr optimization above. + */ if (!match_jobid(bsr, bsr->JobId, sessrec, 1)) { goto no_match; + } if (!match_job(bsr, bsr->job, sessrec, 1)) { goto no_match; @@ -286,7 +341,6 @@ static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, if (!match_stream(bsr, bsr->stream, rec, 1)) { goto no_match; } - bsr->found++; return 1; no_match: @@ -409,7 +463,8 @@ static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool d if (volfile->done && done) { bsr->done = true; bsr->root->reposition = true; - Dmsg0(100, "bsr done from volfile\n"); + Dmsg2(100, "bsr done from volfile rec=%d volefile=%d\n", + rec->File, volfile->efile); } return 0; } @@ -464,6 +519,10 @@ static int match_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_RECORD *rec) return 0; } +/* + * When reading the Volume, the Volume Findex (rec->FileIndex) always + * are found in sequential order. Thus we can make optimizations. + */ static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, bool done) { if (!findex) { diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 4d45f4e384..3b419860dd 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -44,7 +44,6 @@ * This routine returns a 0 only if it is REALLY * impossible to get the requested Volume. * - * *****FIXME****** handle "Recycle" volume ****** */ int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release) { @@ -116,7 +115,7 @@ mount_next_vol: release = 1; /* release next time if we "recurse" */ -ask_again: +// ask_again: if (ask && !dir_ask_sysop_to_mount_next_volume(jcr, dev)) { Dmsg0(100, "Error return ask_sysop ...\n"); return 0; /* error return */ @@ -227,7 +226,8 @@ mount_error: Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg); Dmsg0(100, "Default\n"); ask = true; - goto ask_again; + /* was - goto ask_again; */ + goto mount_next_vol; } break; } @@ -240,7 +240,7 @@ mount_error: * VOL_LABEL. We rewind and return the label (reconstructed) * in the block so that in the case of a new tape, data can * be appended just after the block label. If we are writing - * an second volume, the calling routine will write the label + * a second volume, the calling routine will write the label * before writing the overflow block. * * If the tape is marked as Recycle, we rewrite the label. diff --git a/bacula/src/stored/parse_bsr.c b/bacula/src/stored/parse_bsr.c index 83343dcb7a..7805c1c9d9 100755 --- a/bacula/src/stored/parse_bsr.c +++ b/bacula/src/stored/parse_bsr.c @@ -713,9 +713,12 @@ void dump_bsr(BSR *bsr, bool recurse) } if (bsr->count) { Dmsg1(-1, "count : %u\n", bsr->count); + Dmsg1(-1, "found : %u\n", bsr->found); } + Dmsg1(-1, "done : %s\n", bsr->done?"yes":"no"); Dmsg1(-1, "positioning : %d\n", bsr->use_positioning); + Dmsg1(-1, "fast_reject : %d\n", bsr->use_fast_rejection); if (recurse && bsr->next) { Dmsg0(-1, "\n"); dump_bsr(bsr->next, true); diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 8ad2262660..e84cfc1f15 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -58,7 +58,7 @@ void empty_block(DEV_BLOCK *block); void free_block(DEV_BLOCK *block); int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block); -void print_block_errors(JCR *jcr, DEV_BLOCK *block); +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false @@ -155,6 +155,7 @@ int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, 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 */ int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release); diff --git a/bacula/src/stored/read_record.c b/bacula/src/stored/read_record.c index 8e34737869..9962ff8302 100644 --- a/bacula/src/stored/read_record.c +++ b/bacula/src/stored/read_record.c @@ -33,7 +33,10 @@ #include "bacula.h" #include "stored.h" +/* Forward referenced functions */ static void handle_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); +static BSR *position_to_first_file(JCR *jcr, DEVICE *dev); +static int try_repositioning(JCR *jcr, DEV_RECORD *rec, DEVICE *dev); #ifdef DEBUG static char *rec_state_to_str(DEV_RECORD *rec); #endif @@ -52,6 +55,7 @@ int read_records(JCR *jcr, DEVICE *dev, block = new_block(dev); recs = new dlist(rec, &rec->link); + position_to_first_file(jcr, dev); for ( ; ok && !done; ) { if (job_canceled(jcr)) { @@ -59,18 +63,13 @@ int read_records(JCR *jcr, DEVICE *dev, break; } if (!read_block_from_device(jcr, dev, block, CHECK_BLOCK_NUMBERS)) { - Dmsg0(20, "!read_record()\n"); if (dev_state(dev, ST_EOT)) { DEV_RECORD *trec = new_record(); - Dmsg3(100, "EOT. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), - block->BlockNumber, rec->remainder); Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n", dev->file, dev_name(dev), jcr->VolumeName); if (!mount_cb(jcr, dev, block)) { Jmsg(jcr, M_INFO, 0, "End of all volumes.\n"); - Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), - block->BlockNumber, rec->remainder); ok = FALSE; /* * Create EOT Label so that Media record may @@ -79,13 +78,10 @@ int read_records(JCR *jcr, DEVICE *dev, */ trec->FileIndex = EOT_LABEL; trec->File = dev->file; - trec->Block = rec->Block; /* return block last read */ ok = record_cb(jcr, dev, block, trec); free_record(trec); break; } - Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), - block->BlockNumber, rec->remainder); /* * We just have a new tape up, now read the label (first record) * and pass it off to the callback routine, then continue @@ -96,33 +92,17 @@ int read_records(JCR *jcr, DEVICE *dev, handle_session_record(dev, trec, &sessrec); ok = record_cb(jcr, dev, block, trec); free_record(trec); - /* - * Now find and position to first file and block - * on this tape. - */ - if (jcr->bsr) { - BSR *bsr; - - jcr->bsr->reposition = true; - bsr = find_next_bsr(jcr->bsr, dev); - if (bsr) { - Jmsg(jcr, M_INFO, 0, _("Forward spacing to file:block %u:%u.\n"), - bsr->volfile->sfile, bsr->volblock->sblock); - Dmsg4(100, "Reposition new from (file:block) %d:%d to %d:%d\n", - dev->file, dev->block_num, bsr->volfile->sfile, - bsr->volblock->sblock); - reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock); - Dmsg2(100, "Now at (file:block) %d:%d\n", - dev->file, dev->block_num); - } - } + position_to_first_file(jcr, dev); /* After reading label, we must read first data block */ continue; } 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", dev->file, dev_name(dev), jcr->VolumeName); - Dmsg0(20, "read_record got eof. try again\n"); + } + Dmsg3(100, "Got EOF at file %u on device %s, Volume \"%s\"\n", + dev->file, dev_name(dev), jcr->VolumeName); continue; } else if (dev_state(dev, ST_SHORT)) { Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); @@ -134,16 +114,17 @@ int read_records(JCR *jcr, DEVICE *dev, break; } } - Dmsg5(100, "Read block: dev=%d blk=%d VI=%u VT=%u blen=%d\n", dev->block_num, block->BlockNumber, - block->VolSessionId, block->VolSessionTime, block->block_len); + Dmsg2(100, "New block at position=(file:block) %d:%d\n", dev->file, dev->block_num); +#define FAST_BLOCK_REJECTION +#ifdef FAST_BLOCK_REJECTION + /* this does not stop when file/block are too big */ if (!match_bsr_block(jcr->bsr, block)) { - Dmsg5(100, "reject Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n", - block->BlockNumber, block->block_len, block->BlockVer, - block->VolSessionId, block->VolSessionTime); - continue; + if (try_repositioning(jcr, rec, dev)) { + break; /* get next volume */ + } + continue; /* skip this record */ } - Dmsg4(100, "Block: %d VI=%u VT=%u blen=%d\n", block->BlockNumber, - block->VolSessionId, block->VolSessionTime, block->block_len); +#endif /* * Get a new record for each Job as defined by @@ -163,21 +144,25 @@ int read_records(JCR *jcr, DEVICE *dev, Dmsg2(100, "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(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); record = 0; + rec->state = 0; + Dmsg1(100, "Block empty %d\n", is_block_empty(rec)); for (rec->state=0; !is_block_empty(rec); ) { if (!read_record_from_block(block, rec)) { - Dmsg3(10, "!read-break. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec), + Dmsg3(100, "!read-break. state=%s blk=%d rem=%d\n", rec_state_to_str(rec), block->BlockNumber, rec->remainder); break; } - Dmsg5(100, "read-OK. stat=%s blk=%d rem=%d file:block=%d:%d\n", + Dmsg5(100, "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); /* @@ -190,10 +175,6 @@ int read_records(JCR *jcr, DEVICE *dev, Dmsg6(100, "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); - Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId, - FI_to_ascii(rec->FileIndex), - stream_to_ascii(rec->Stream, rec->FileIndex), - rec->data_len); if (rec->FileIndex == EOM_LABEL) { /* end of tape? */ Dmsg0(40, "Get EOM LABEL\n"); @@ -220,43 +201,40 @@ int read_records(JCR *jcr, DEVICE *dev, int stat = match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec); if (stat == -1) { /* no more possible matches */ done = true; /* all items found, stop */ + Dmsg2(100, "All done=(file:block) %d:%d\n", dev->file, dev->block_num); break; } else if (stat == 0) { /* no match */ - BSR *bsr; - bsr = find_next_bsr(jcr->bsr, dev); - if (bsr == NULL && jcr->bsr->mount_next_volume) { - Dmsg0(100, "Would mount next volume here\n"); - Dmsg2(100, "Current postion (file:block) %d:%d\n", - dev->file, dev->block_num); - jcr->bsr->mount_next_volume = false; - dev->state |= ST_EOT; - rec->Block = 0; + Dmsg4(100, "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; } - if (bsr) { - Dmsg4(100, "Reposition from (file:block) %d:%d to %d:%d\n", - dev->file, dev->block_num, bsr->volfile->sfile, - bsr->volblock->sblock); - reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock); - rec->Block = 0; - Dmsg2(100, "Now at (file:block) %d:%d\n", - dev->file, dev->block_num); - } - Dmsg5(100, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n", - record, block->BlockNumber, rec->VolSessionId, rec->VolSessionTime, - rec->FileIndex); continue; /* we don't want record, read next one */ } } if (is_partial_record(rec)) { - Dmsg6(10, "Partial, break. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record, + Dmsg6(100, "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(jcr, dev, block, rec); + if (rec->Stream == STREAM_MD5_SIGNATURE || rec->Stream == STREAM_SHA1_SIGNATURE) { + Dmsg3(100, "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(100, "Break after match_set_eof pos %d:%d\n", + dev->file, dev->block_num); + break; + } + Dmsg2(100, "After set_eof pos %d:%d\n", dev->file, dev->block_num); + } } /* end for loop over records */ + Dmsg2(100, "After end records position=(file:block) %d:%d\n", dev->file, dev->block_num); } /* end for loop over blocks */ +// Dmsg2(100, "Position=(file:block) %d:%d\n", dev->file, dev->block_num); /* Walk down list and free all remaining allocated recs */ for (rec=(DEV_RECORD *)recs->first(); rec; ) { @@ -266,11 +244,68 @@ int read_records(JCR *jcr, DEVICE *dev, rec = nrec; } delete recs; - print_block_errors(jcr, block); + print_block_read_errors(jcr, block); free_block(block); return ok; } +/* + * See if we can reposition. + * Returns: 1 if at end of volume + * 0 otherwise + */ +static int try_repositioning(JCR *jcr, DEV_RECORD *rec, DEVICE *dev) +{ + BSR *bsr; + bsr = find_next_bsr(jcr->bsr, dev); + if (bsr == NULL && jcr->bsr->mount_next_volume) { + Dmsg0(100, "Would mount next volume here\n"); + Dmsg2(100, "Current postion (file:block) %d:%d\n", + dev->file, dev->block_num); + jcr->bsr->mount_next_volume = false; + dev->state |= ST_EOT; + rec->Block = 0; + return 1; + } + if (bsr) { + if (verbose > 1) { + 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); + } + Dmsg4(100, "Try_Reposition from (file:block) %d:%d to %d:%d\n", + dev->file, dev->block_num, bsr->volfile->sfile, + bsr->volblock->sblock); + reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock); + rec->Block = 0; + } + return 0; +} + +/* + * Position to the first file on this volume + */ +static BSR *position_to_first_file(JCR *jcr, DEVICE *dev) +{ + BSR *bsr = NULL; + /* + * Now find and position to first file and block + * on this tape. + */ + if (jcr->bsr) { + 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"), + bsr->volfile->sfile, bsr->volblock->sblock); + Dmsg2(100, "Forward spacing to file:block %u:%u.\n", + bsr->volfile->sfile, bsr->volblock->sblock); + reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock); + } + } + return bsr; +} + static void handle_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) { diff --git a/bacula/src/stored/record.h b/bacula/src/stored/record.h index f00207547e..dd3047d478 100644 --- a/bacula/src/stored/record.h +++ b/bacula/src/stored/record.h @@ -77,6 +77,7 @@ * * This is the memory structure for the record header. */ +struct BSR; /* satisfy forward reference */ struct DEV_RECORD { dlink link; /* link for chaining in read_record.c */ /* File and Block are always returned during reading @@ -91,6 +92,7 @@ struct DEV_RECORD { uint32_t data_len; /* current record length */ uint32_t remainder; /* remaining bytes to read/write */ uint32_t state; /* state bits */ + BSR *bsr; /* pointer to bsr that matched */ uint8_t ser_buf[WRITE_RECHDR_LENGTH]; /* serialized record header goes here */ POOLMEM *data; /* Record data. This MUST be a memory pool item */ }; diff --git a/bacula/src/tools/testls.c b/bacula/src/tools/testls.c index 51d178023c..236d3b7d8f 100755 --- a/bacula/src/tools/testls.c +++ b/bacula/src/tools/testls.c @@ -71,28 +71,28 @@ main (int argc, char *const *argv) while ((ch = getopt(argc, argv, "ad:e:i:?")) != -1) { switch (ch) { - case 'a': /* print extended attributes *debug* */ - attrs = 1; - break; - - case 'd': /* set debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) { - debug_level = 1; - } - break; + case 'a': /* print extended attributes *debug* */ + attrs = 1; + break; + + case 'd': /* set debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } + break; - case 'e': /* exclude patterns */ - exc = optarg; - break; + case 'e': /* exclude patterns */ + exc = optarg; + break; - case 'i': /* include patterns */ - inc = optarg; - break; + case 'i': /* include patterns */ + inc = optarg; + break; - case '?': - default: - usage(); + case '?': + default: + usage(); } } @@ -200,6 +200,10 @@ static void print_ls_output(char *fname, char *link, int type, struct stat *stat char *p, *f; int n; + if (type == FT_LNK) { + statp->st_mtime = 0; + statp->st_mode |= 0777; + } p = encode_mode(statp->st_mode, buf); n = sprintf(p, " %2d ", (uint32_t)statp->st_nlink); p += n; @@ -213,11 +217,7 @@ static void print_ls_output(char *fname, char *link, int type, struct stat *stat n = sprintf(p, " "); } p += n; - if (type != FT_LNK) { - p = encode_time(statp->st_mtime, p); - } else { - p = encode_time(0, p); - } + p = encode_time(statp->st_mtime, p); *p++ = ' '; /* Copy file name */ for (f=fname; *f && (p-buf) < (int)sizeof(buf); ) diff --git a/bacula/src/version.h b/bacula/src/version.h index 47e2bf31fa..587af5a2a4 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,9 +1,9 @@ /* */ #undef VERSION -#define VERSION "1.32" +#define VERSION "1.32d" #define VSTRING "1" -#define BDATE "26 Sep 2003" -#define LSMDATE "26Sep03" +#define BDATE "02 Nov 2003" +#define LSMDATE "02Nov03" /* Debug flags */ #undef DEBUG diff --git a/regress/.cvsignore b/regress/.cvsignore deleted file mode 100644 index 120006c649..0000000000 --- a/regress/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -build -bin -test.out -weird-files -diff -tmp -working diff --git a/regress/README b/regress/README deleted file mode 100644 index ad5056c4e2..0000000000 --- a/regress/README +++ /dev/null @@ -1,85 +0,0 @@ - Bacula Regression - Kern Sibbald - April 2003 - -This is Bacula's regression script directory. At this time -(May 2003), it is still in development, so all the tests are -not complete. - -To set it up, first edit Makefile and set BACULA-SOURCE to point -to your source. - -!!!!!!!!!! IMPORTANT !!!!!!!! -Second, edit the EMAIL address in the Makefile to be your -email address and not mine or I will get LOTS of unwanted -email! - -Third, edit the DEPKGS path in the Makefile to point to the -depkgs directory. - -Fourth, make sure that depkgs is pre-built if it isn't -already: (cd your-depkgs; make sqlite). - -Then do: - - make setup - -You run the above one time. This will copy the Bacula -source, configure, build it, and configure all the scripts -and conf files. If you change your source, you will need -to redo this command. - -Then you can run any of the tests in the tests subdirectory. -Each test whose name ends in -root requires you to be root for -a resonable run. Each test is totally independent of any other -test. Aside from the required "make setup", each test is totally -self-initalizing and should clean up after itself. - -Not all the tests yet report OK. This is simply because there are -some spurious differences that I haven't yet taken the time to -eliminate. The working scrips as of 24 Apr 03 are: - -backup-bacula-test -sparse-test -compressed-test -sparse-compressed-test -two-jobs-test -wierd-files-test -verify-vol-test - -The tests expect you to execute them from the main regress -directory! - -You can run them individually as: - - tests/two-jobs-test - -or all non-root tests (my normal testing under my account) - - ./all-non-root-tests - -or all tests (I only run these before a production release): - - su - ./all-tests - - -after running the root tests, while still root, it is a good idea -to do: - - make reset - -this cleans up any files that may be created with root permissions. - -If you want to add more tests, do so by putting the shell script -in the tests subdirectory. Be careful when adding (or better not) -new clients, pools, and such to the test-bacula-dir.conf.in file -as it may invalidate a good number of tests, which respond to -questions by answering with a number (i.e. the order of the selection -list is known). It might be better to add your own testb-bacula... -configuration file. - -To avoid re-doing a make setup if you have made a change to the -conf files, and you do not need a new copy of the source, you can simply do: - - scripts/do-sed diff --git a/regress/all-non-root-tape-tests b/regress/all-non-root-tape-tests deleted file mode 100755 index 13fffb0056..0000000000 --- a/regress/all-non-root-tape-tests +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# Run all tape tests -# -tests/test0 -tests/backup-bacula-tape -tests/small-file-size-tape -tests/two-volume-tape -echo " " -echo " " -echo "Test results" -cat test.out -scripts/cleanup diff --git a/regress/all-non-root-tests b/regress/all-non-root-tests deleted file mode 100755 index 2b2c48d34e..0000000000 --- a/regress/all-non-root-tests +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# -# Run all tests -# -tests/test0 -tests/backup-bacula-test -tests/verify-vol-test -tests/sparse-test -tests/compressed-test -tests/sparse-compressed-test -tests/weird-files-test -tests/two-jobs-test -tests/two-vol-test -tests/six-vol-test -tests/bscan-test -tests/weird-files2-test -tests/concurrent-jobs-test -tests/four-concurrent-jobs-test -tests/bsr-opt-test -tests/bextract-test -tests/recycle-test -tests/span-vol-test -tests/restore-by-file-test -echo " " -echo " " -echo "Test results" -cat test.out -scripts/cleanup diff --git a/regress/all-root-tests b/regress/all-root-tests deleted file mode 100755 index 9eb8995c9f..0000000000 --- a/regress/all-root-tests +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# -# Run all root tests -# -tests/dev-test-root -tests/etc-test-root -tests/lib-test-root -cat test.out -scripts/cleanup diff --git a/regress/all-tape-and-file-tests b/regress/all-tape-and-file-tests deleted file mode 100755 index 857934410a..0000000000 --- a/regress/all-tape-and-file-tests +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# -# Run all tests -# -tests/test0 -tests/backup-bacula-test -tests/verify-vol-test -tests/sparse-test -tests/compressed-test -tests/sparse-compressed-test -tests/weird-files-test -tests/two-jobs-test -tests/two-vol-test -tests/six-vol-test -tests/bscan-test -tests/weird-files2-test -tests/concurrent-jobs-test -tests/four-concurrent-jobs-test -tests/bsr-opt-test -tests/bextract-test -tests/recycle-test -tests/span-vol-test -tests/backup-bacula-tape -tests/small-file-size-tape -tests/two-volume-tape -echo " " -echo " " -echo "Test results" -cat test.out -scripts/cleanup diff --git a/regress/all-tests b/regress/all-tests deleted file mode 100755 index b1b2b35e86..0000000000 --- a/regress/all-tests +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# Run all tests -# -./all-non-root-tests -./all-root-tests -cat test.out -scripts/cleanup diff --git a/regress/scripts/.cvsignore b/regress/scripts/.cvsignore deleted file mode 100644 index 0253541d2a..0000000000 --- a/regress/scripts/.cvsignore +++ /dev/null @@ -1,12 +0,0 @@ -bacula-dir.conf -bacula-fd.conf -bacula-sd.conf -console.conf -test-bacula-dir.conf -test-bacula-fd.conf -test-bacula-sd.conf -test-console.conf -testa-bacula-dir.conf -bacula-dir-tape.conf -bacula-sd-tape.conf -cleanup-tape diff --git a/regress/scripts/bacula-dir-tape.conf.in b/regress/scripts/bacula-dir-tape.conf.in deleted file mode 100644 index da9ac34c19..0000000000 --- a/regress/scripts/bacula-dir-tape.conf.in +++ /dev/null @@ -1,132 +0,0 @@ -# -# Default Bacula Director Configuration file -# -# The only thing that MUST be changed is to add one or more -# file or directory names in the Include directive of the -# FileSet resource. -# -# For Bacula release 1.30 (12 April 2003) -- redhat 7.3 -# -# You might also want to change the default email address -# from root to your address. See the "mail" and "operator" -# directives in the Messages resource. -# - -Director { # define myself - Name = @hostname@-dir - DIRport = 8101 # where we listen for UA connections - QueryFile = "@scriptdir@/query.sql" - WorkingDirectory = "@working_dir@" - PidDirectory = "@piddir@" - Maximum Concurrent Jobs = 4 - Password = "pNvX1WiXnwv2C/F7E52LGvw6rKjbbPvu2kyuPa9pVaL3" - Messages = Standard -} - -# -# Define the main nightly save backup job -# By default, this job will back up to disk in /tmp -Job { - Name = "NightlySave" - Type = Backup - Client=@hostname@-fd - FileSet="Full Set" - Storage = DDS-4 - Messages = Standard - Pool = Default - Write Bootstrap = "@working_dir@/NightlySave.bsr" - Maximum Concurrent Jobs = 4 -} - - -# Standard Restore template, to be changed by Console program -Job { - Name = "RestoreFiles" - Type = Restore - Client=@hostname@-fd - FileSet="Full Set" - Storage = DDS-4 - Messages = Standard - Pool = Default - Where = /tmp/bacula-restores -} - - -# List of files to be backed up -FileSet { - Name = "Full Set" - Include = signature=MD5 { - ${out} -echo "s%@scriptdir@%${cwd}/bin%g" >>${out} -echo "s%@working_dir@%${cwd}/working%g" >>${out} -echo "s%@piddir@%${cwd}/working%g" >>${out} -echo "s%@subsysdir@%${cwd}/working%g" >>${out} -echo "s%@job_email@%${1}%g" >>${out} -echo "s%@tape_drive@%${2}%g" >>${out} -echo "s%@autochanger@%${3}%g" >>${out} -echo "s%@tmpdir@%${cwd}/tmp%g" >>${out} -echo "s%@hostname@%${host}%g" >>${out} - -# process .in files with sed script -sed -f ${out} ${cwd}/scripts/test-bacula-dir.conf.in >${cwd}/scripts/test-bacula-dir.conf -sed -f ${out} ${cwd}/scripts/testa-bacula-dir.conf.in >${cwd}/scripts/testa-bacula-dir.conf -sed -f ${out} ${cwd}/scripts/test-bacula-fd.conf.in >${cwd}/scripts/test-bacula-fd.conf -sed -f ${out} ${cwd}/scripts/test-bacula-sd.conf.in >${cwd}/scripts/test-bacula-sd.conf -sed -f ${out} ${cwd}/scripts/test-console.conf.in >${cwd}/scripts/test-console.conf -sed -f ${out} ${cwd}/scripts/bacula-dir-tape.conf.in >${cwd}/scripts/bacula-dir-tape.conf -sed -f ${out} ${cwd}/scripts/bacula-sd-tape.conf.in >${cwd}/scripts/bacula-sd-tape.conf -sed -f ${out} ${cwd}/scripts/cleanup-tape.in >${cwd}/scripts/cleanup-tape -cp ${cwd}/bin/bacula-sd.conf /tmp/bac$$ -sed s%/tmp%${cwd}/tmp%g /tmp/bac$$ >${cwd}/bin/bacula-sd.conf -chmod 777 ${cwd}/scripts/cleanup-tape - -rm -f ${out} -rm -f /tmp/bac$$ diff --git a/regress/scripts/exclude-dev-test b/regress/scripts/exclude-dev-test deleted file mode 100644 index 4165ea1ae7..0000000000 --- a/regress/scripts/exclude-dev-test +++ /dev/null @@ -1,5 +0,0 @@ -dev/ptmx -dev/pts -dev/rd/c5d2 -dev/rd -dev/shm diff --git a/regress/scripts/exclude-etc-test b/regress/scripts/exclude-etc-test deleted file mode 100644 index f59ca8df2a..0000000000 --- a/regress/scripts/exclude-etc-test +++ /dev/null @@ -1 +0,0 @@ -etc/mail/statistics diff --git a/regress/scripts/exclude-lib-test b/regress/scripts/exclude-lib-test deleted file mode 100644 index 5be32f443b..0000000000 --- a/regress/scripts/exclude-lib-test +++ /dev/null @@ -1,5 +0,0 @@ -lib/ld-2.2.5.so -lib/libtermcap.so.2.0.8 -lib/libc-2.2.5.so -lib/libnsl-2.2.5.so -lib/libnss_files-2.2.5.so diff --git a/regress/scripts/regress-config b/regress/scripts/regress-config deleted file mode 100755 index e03e84bc27..0000000000 --- a/regress/scripts/regress-config +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -# -# This is the configuration script for regression testing -# - -CFLAGS="-g -O2 -Wall" \ - ./configure \ - --sbindir=$1/bin \ - --sysconfdir=$1/bin \ - --with-pid-dir=$1/working \ - --with-subsys-dir=$1/working \ - --enable-smartalloc \ - --disable-readline \ - --with-sqlite=$2 \ - --with-working-dir=$1/working \ - --with-dump-email=$3 \ - --with-job-email=$3 \ - --with-baseport=8101 - -exit 0 diff --git a/regress/scripts/setup b/regress/scripts/setup deleted file mode 100755 index 48d71231d3..0000000000 --- a/regress/scripts/setup +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# -# Script to setup running Bacula regression tests -# -cwd=`pwd` -if [ $# != 3 ] ; then - echo "Incorrect number of arguments. Need:" - echo "setup bacula-src depkgs email-address" - echo " " - exit 1 -fi -if [ ! -d $1 ] ; then - echo "Arg 1 must be a Bacula release directory." - echo " " - exit 1 -fi -if [ ! -d $2 ] ; then - cd .. - cwd=`pwd` - echo "The regression scripts require DEPKGS as arg 2 but not found!" - echo " " - exit 1 -fi -rm -rf build bin -# Copy new source -cp -rp $1 build -cp scripts/regress-config build -cd build -rm -f Makefile config.cache -# Run Bacula configuration, make, install -./regress-config ${cwd} $2 $3 -make -make install -cp src/tools/testls ../bin - -cd .. -bin/bacula stop -bin/create_sqlite_database -bin/drop_sqlite_tables -bin/make_sqlite_tables -# Start and stop Bacula to ensure conf files are OK -bin/bacula start -bin/bacula stop -# -# Save Bacula default conf files for later use -# -cp -f bin/*.conf scripts diff --git a/regress/scripts/test-bacula-dir.conf.in b/regress/scripts/test-bacula-dir.conf.in deleted file mode 100644 index e584b9f5d3..0000000000 --- a/regress/scripts/test-bacula-dir.conf.in +++ /dev/null @@ -1,298 +0,0 @@ -# -# Default Bacula Director Configuration file -# -# The only thing that MUST be changed is to add one or more -# file or directory names in the Include directive of the -# FileSet resource. -# -# For Bacula release 1.30 (12 April 2003) -- redhat 7.3 -# -# You might also want to change the default email address -# from root to your address. See the "mail" and "operator" -# directives in the Messages resource. -# - -Director { # define myself - Name = @hostname@-dir - DIRport = 8101 # where we listen for UA connections - QueryFile = "@scriptdir@/query.sql" - WorkingDirectory = "@working_dir@" - PidDirectory = "@piddir@" - SubSysDirectory = "@subsysdir@" - Maximum Concurrent Jobs = 4 - Password = "pNvX1WiXnwv2C/F7E52LGvw6rKjbbPvu2kyuPa9pVaL3" # Console password - Messages = Standard -} - -# -# Define the main nightly save backup job -# By default, this job will back up to disk in /tmp -Job { - Name = "NightlySave" - Type = Backup - Client=@hostname@-fd - FileSet="Full Set" - Storage = File - Messages = Standard - Pool = Default - Write Bootstrap = "@working_dir@/NightlySave.bsr" - Maximum Concurrent Jobs = 4 -} - -Job { - Name = "MonsterSave" - Type = Backup - Client=@hostname@-fd - FileSet="Full Set" - Storage = File1 - Messages = Standard - Pool = Default - Write Bootstrap = "@working_dir@/NightlySave.bsr" -} - - -Job { - Name = "VerifyVolume" - Type = Verify - Level = VolumeToCatalog - Client=@hostname@-fd - FileSet="Full Set" - Storage = File - Messages = Standard - Pool = Default - Write Bootstrap = "@working_dir@/NightlySave.bsr" -} - - -Job { - Name = "SparseTest" - Type = Backup - Client=@hostname@-fd - FileSet="SparseSet" - Storage = File - Messages = Standard - Pool = Default - Write Bootstrap = "@working_dir@/NightlySave.bsr" -} - -Job { - Name = "CompressedTest" - Type = Backup - Client=@hostname@-fd - FileSet="CompressedSet" - Storage = File - Messages = Standard - Pool = Default - Maximum Concurrent Jobs = 4 - Write Bootstrap = "@working_dir@/NightlySave.bsr" -} - -Job { - Name = "SparseCompressedTest" - Type = Backup - Client=@hostname@-fd - FileSet="SparseCompressedSet" - Storage = File - Messages = Standard - Pool = Default - Write Bootstrap = "@working_dir@/NightlySave.bsr" -} - - -# Backup the catalog database (after the nightly save) -Job { - Name = "BackupCatalog" - Type = Backup - Client=@hostname@-fd - FileSet="Catalog" -# Schedule = "WeeklyCycleAfterBackup" - Storage = File - Messages = Standard - Pool = Default - # This creates an ASCII copy of the catalog - RunBeforeJob = "@sbindir@/make_catalog_backup -u bacula" - # This deletes the copy of the catalog - RunAfterJob = "@sbindir@/delete_catalog_backup" - Write Bootstrap = "@working_dir@/BackupCatalog.bsr" -} - -# Standard Restore template, to be changed by Console program -Job { - Name = "RestoreFiles" - Type = Restore - Client=@hostname@-fd - FileSet="Full Set" - Storage = File - Messages = Standard - Pool = Default - Where = /tmp/bacula-restores -} - - -# List of files to be backed up -FileSet { - Name = "Full Set" - Include = signature=MD5 { - &1 >/dev/null -scripts/copy-tape-confs -scripts/cleanup-tape -echo "${cwd}/build" >/tmp/file-list -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting Bacula tape test ===" -echo " === Starting Bacula tape test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Bacula tape test Bacula source failed!!! !!!!! " - echo " !!!!! Bacula tape test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Bacula tape test Bacula source OK ===== " - echo " ===== Bacula tape test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/backup-bacula-test b/regress/tests/backup-bacula-test deleted file mode 100755 index dfda3bcccd..0000000000 --- a/regress/tests/backup-bacula-test +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then restore it. -# -cwd=`pwd` -scripts/copy-confs -scripts/cleanup -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting Backup Bacula Test ===" -echo " === Starting Backup Bacula Test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Backup Bacula Test failed!!! !!!!! " - echo " !!!!! Backup Bacula Test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Backup Bacula Test OK ===== " - echo " ===== Backup Bacula Test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/bextract-test b/regress/tests/bextract-test deleted file mode 100755 index fc1310b6a4..0000000000 --- a/regress/tests/bextract-test +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory but -# split the archive into two volumes, then build a BSR with -# the restore command and use bextract to restore the files. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting bextract-test ===" -echo " === Starting bextract-test ===" >working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -mkdir -p ${cwd}/tmp/bacula-restores -bin/bextract -b working/restore.bsr -c bin/bacula-sd.conf ${cwd}/tmp ${cwd}/tmp/bacula-restores 2>&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! bextract-test Bacula source failed!!! !!!!! " - echo " !!!!! bextract-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== bextract-test Bacula source OK ===== " - echo " ===== bextract-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/bscan-test b/regress/tests/bscan-test deleted file mode 100755 index aca7d1a773..0000000000 --- a/regress/tests/bscan-test +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory but -# split the archive into two volumes then bscan it -# into the catalog after the backup. It also to a limited -# extent tests the purge volume and delete volume commands. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting bscan-test ===" -echo " === Starting bscan-test ===" >working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -echo "volume=TestVolume001|TestVolume002" >tmp/bscan.bsr -bin/bscan -w working -m -s -v -b tmp/bscan.bsr -c bin/bacula-sd.conf ${cwd}/tmp 2>&1 >/dev/null -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! bscan-test Bacula source failed!!! !!!!! " - echo " !!!!! bscan-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== bscan-test Bacula source OK ===== " - echo " ===== bscan-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/bsr-opt-test b/regress/tests/bsr-opt-test deleted file mode 100755 index 381166ff93..0000000000 --- a/regress/tests/bsr-opt-test +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory but -# split the archive into two volumes, then restore -# files on only one of the volumes and ensure that -# the other volume is not used. I.e. bsr optimization -# works. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting bsr-opt-test ===" -echo " === Starting bsr-opt-test ===" >working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep TestVolume001 working/restore.bsr -bsrstat=$? -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build/src/cats tmp/bacula-restores${cwd}/build/src/cats 2>&1 >/dev/null -if [ $? != 0 -o $bsrstat != 1 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! bsr-opt-test Bacula source failed!!! !!!!! " - echo " !!!!! bsr-opt-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== bsr-opt-test Bacula source OK ===== " - echo " ===== bsr-opt-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/compressed-test b/regress/tests/compressed-test deleted file mode 100755 index ac886b06e4..0000000000 --- a/regress/tests/compressed-test +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory using the compressed option -# then restore it. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting compressed-test ===" -echo " === Starting compressed-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! compressed-test Bacula source failed!!! !!!!! " - echo " !!!!! compressed-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== compressed-test Bacula source OK ===== " - echo " ===== compressed-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/concurrent-jobs-test b/regress/tests/concurrent-jobs-test deleted file mode 100755 index e02470e004..0000000000 --- a/regress/tests/concurrent-jobs-test +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh -# -# Run two jobs at the same time -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/tmp/largefile" >/tmp/file-list -if test -c /dev/urandom ; then -# Create 56MB file with random data - echo "Creating a 56MB file with random data ..." - dd if=/dev/urandom of=${cwd}/tmp/largefile bs=1024 count=55000 -else - echo "Creating a 56MB file with bacula-dir data ..." - dd if=bin/bacula-dir of=${cwd}/tmp/1 bs=1024 count=1000 - cat ${cwd}/tmp/1 ${cwd}/tmp/1 ${cwd}/tmp/1 ${cwd}/tmp/1 ${cwd}/tmp/1 >${cwd}/tmp/2 - rm -f ${cwd}/tmp/1 - cat ${cwd}/tmp/2 ${cwd}/tmp/2 ${cwd}/tmp/2 ${cwd}/tmp/2 ${cwd}/tmp/2 >>${cwd}/tmp/3 - rm -f ${cwd}/tmp/2 - cat ${cwd}/tmp/3 ${cwd}/tmp/3 ${cwd}/tmp/3 ${cwd}/tmp/3 ${cwd}/tmp/3 >${cwd}/tmp/largefile - rm -f ${cwd}/tmp/3 -fi - -echo "largefile created" -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting concurrent-jobs-test ===" -echo " === Starting concurrent-jobs-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff tmp/largefile tmp/bacula-restores${cwd}/tmp/largefile 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! concurrent-jobs-test Bacula source failed!!! !!!!! " - echo " !!!!! concurrent-jobs-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== concurrent-jobs-test Bacula source OK ===== " - echo " ===== concurrent-jobs-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/dev-test-root b/regress/tests/dev-test-root deleted file mode 100755 index 8f21e22db5..0000000000 --- a/regress/tests/dev-test-root +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then restore it. -# -echo " " -echo " " -echo " === /dev save/restore test ===" -echo " " -echo " " -UID=`/usr/bin/id -u` -if [ $UID != 0 ] ; then - echo " " - echo "You must be root to run this test." - echo " ===== dev test failed!!! ===== " - echo " ===== dev test failed!!! ===== " >>test.out - echo " " - exit 1 -fi -cwd=`pwd` -scripts/copy-test-confs -echo "/dev" >/tmp/file-list -rm -rf /tmp/TestVolume001 /tmp/bacula-restores -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -cd / -${cwd}/bin/testls -e ${cwd}/scripts/exclude-etc-test dev >${cwd}/tmp/original -cd /tmp/bacula-restores -${cwd}/bin/testls -e ${cwd}/scripts/exclude-etc-test dev >${cwd}/tmp/restored -diff ${cwd}/tmp/original ${cwd}/tmp/restored 2>&1 >/dev/null -if [ $? != 0 ] ; then - echo " " - echo " " - echo " ===== dev test failed!!! ===== " - echo " ===== dev test failed!!! ===== " >>test.out - echo " " -else - echo " ===== dev test OK ===== " - echo " ===== dev test OK ===== " >>test.out - cd ${cwd} - scripts/cleanup -fi diff --git a/regress/tests/etc-test-root b/regress/tests/etc-test-root deleted file mode 100755 index 6459026b12..0000000000 --- a/regress/tests/etc-test-root +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then restore it. -# -echo " " -echo " " -echo " === /etc save/restore test ===" -echo " " -echo " " -UID=`/usr/bin/id -u` -if [ $UID != 0 ] ; then - echo " " - echo "You must be root to run this test." - echo " ===== Test4 failed!!! ===== " - echo " ===== Test4 failed!!! ===== " >>test.out - echo " " - exit 1 -fi -cwd=`pwd` -scripts/copy-test-confs -echo "/etc" >/tmp/file-list -rm -rf /tmp/TestVolume001 /tmp/bacula-restores -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -cd / -${cwd}/bin/testls -e ${cwd}/scripts/exclude-etc-test etc >${cwd}/tmp/original -cd /tmp/bacula-restores -${cwd}/bin/testls -e ${cwd}/scripts/exclude-etc-test etc >${cwd}/tmp/restored -diff ${cwd}/tmp/original ${cwd}/tmp/restored 2>&1 >/dev/null -if [ $? != 0 ] ; then - echo " " - echo " " - echo " ===== Test4 /etc failed!!! ===== " - echo " ===== Test4 failed!!! ===== " >>test.out - echo " " -else - echo " ===== Test4 /etc OK ===== " - echo " ===== Test4 OK ===== " >>test.out - cd ${cwd} - scripts/cleanup -fi diff --git a/regress/tests/four-concurrent-jobs-test b/regress/tests/four-concurrent-jobs-test deleted file mode 100755 index 0782fbd63c..0000000000 --- a/regress/tests/four-concurrent-jobs-test +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh -# -# Run two jobs at the same time -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting four-concurrent-jobs-test ===" -echo " === Starting four-concurrent-jobs-test ===" >>working/log -echo " " - -#bin/bacula start 2>&1 >/dev/null -bin/bacula start -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! four-concurrent-jobs-test Bacula source failed!!! !!!!! " - echo " !!!!! four-concurrent-jobs-test failed!!! !!!!! " >>test.out - echo " " - exit 1 -else - echo " ===== four-concurrent-jobs-test Bacula source OK ===== " - echo " ===== four-concurrent-jobs-test OK ===== " >>test.out - scripts/cleanup - exit 0 -fi diff --git a/regress/tests/lib-test-root b/regress/tests/lib-test-root deleted file mode 100755 index 60320fb39b..0000000000 --- a/regress/tests/lib-test-root +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then restore it. -# -echo " " -echo " " -echo " === /lib save/restore test ===" -echo " " -echo " " -UID=`/usr/bin/id -u` -if [ $UID != 0 ] ; then - echo " " - echo "You must be root to run this test." - echo " ===== Test5 failed!!! ===== " - echo " ===== Test5 failed!!! ===== " >>test.out - echo " " - exit 1 -fi -cwd=`pwd` -scripts/copy-test-confs -echo "/lib" >/tmp/file-list -rm -rf /tmp/TestVolume001 /tmp/bacula-restores -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -cd / -${cwd}/bin/testls -e ${cwd}/scripts/exclude-lib-test lib >${cwd}/tmp/original -cd /tmp/bacula-restores -${cwd}/bin/testls -e ${cwd}/scripts/exclude-lib-test lib >${cwd}/tmp/restored -diff ${cwd}/tmp/original ${cwd}/tmp/restored 2>&1 >/dev/null -if [ $? != 0 ] ; then - echo " " - echo " " - echo " ===== Test5 /lib failed!!! ===== " - echo " ===== Test5 failed!!! ===== " >>test.out - echo " " -else - echo " ===== Test5 /lib OK ===== " - echo " ===== Test5 OK ===== " >>test.out - cd ${cwd} - scripts/cleanup -fi diff --git a/regress/tests/recycle-test b/regress/tests/recycle-test deleted file mode 100755 index 0745b88e23..0000000000 --- a/regress/tests/recycle-test +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory but -# create three volumes and do six backups causing the -# volumes to be recycled, and cycling through the volumes -# twice. Tests maxvoljobs and volretention. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting recycle-test ===" -echo " === Starting recycle-test ===" >working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! recycle-test Bacula source failed!!! !!!!! " - echo " !!!!! recycle-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== recycle-test Bacula source OK ===== " - echo " ===== recycle-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/restore-by-file-test b/regress/tests/restore-by-file-test deleted file mode 100755 index 22d4cc759b..0000000000 --- a/regress/tests/restore-by-file-test +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory using the compressed option -# then restore it. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/tmp/build" >/tmp/file-list -mkdir ${cwd}/tmp/build -cp -p ${cwd}/build/src/dird/*.c ${cwd}/tmp/build -cd ${cwd}/tmp/build -ls >../1 -cd .. -sed s%\^%${cwd}/tmp/build/% 1 >restore-list -rm -f 1 -cd ${cwd} -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting restore-by-file-test ===" -echo " === Starting restore-by-file-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r tmp/build tmp/bacula-restores${cwd}/tmp/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! restore-by-file-test Bacula source failed!!! !!!!! " - echo " !!!!! restore-by-file-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== restore-by-file-test Bacula source OK ===== " - echo " ===== restore-by-file-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/six-vol-test b/regress/tests/six-vol-test deleted file mode 100755 index 73ce4e920d..0000000000 --- a/regress/tests/six-vol-test +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# -# Create a 60MB file with random bytes. Back it up to 6 Volumes -# each constrained to 10MB using the automatic labeling feature. -# - -if test ! -c /dev/urandom ; then - echo "No random device. Test skipped.\n" - exit 0 -fi -cwd=`pwd` -scripts/copy-testa-confs -scripts/cleanup -echo "${cwd}/tmp/largefile" >/tmp/file-list -# Create 56MB file with random data -echo "Creating a 56MB file with random data ..." -dd if=/dev/urandom of=${cwd}/tmp/largefile bs=1024 count=55000 -echo "largefile created" -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting six-vol-test ===" -echo " === Starting six-vol-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff tmp/largefile tmp/bacula-restores${cwd}/tmp/largefile 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! six-vol-test Bacula source failed!!! !!!!! " - echo " !!!!! six-vol-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== six-vol-test Bacula source OK ===== " - echo " ===== six-vol-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/small-file-size-tape b/regress/tests/small-file-size-tape deleted file mode 100755 index 743cc17ff8..0000000000 --- a/regress/tests/small-file-size-tape +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# to a tape where the maximum tape file size is set to 1M -# -cwd=`pwd` -bin/bacula stop 2>&1 >/dev/null -scripts/copy-tape-confs -scripts/cleanup-tape -echo "${cwd}/build" >/tmp/file-list -bin/drop_sqlite_tables -bin/make_sqlite_tables -out="tmp/sed_tmp" -echo "s%# Maximum File Size% Maximum File Size%g" >${out} -cp ${cwd}/bin/bacula-sd.conf ${cwd}/tmp/1 -sed -f ${out} ${cwd}/tmp/1 >${cwd}/bin/bacula-sd.conf - -echo " " -echo " " -echo " === Starting Small File Size test ===" -echo " === Starting Small File Size test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Small File Size test Bacula source failed!!! !!!!! " - echo " !!!!! Small File Size test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Small File Size test Bacula source OK ===== " - echo " ===== Small File Size test OK ===== " >>test.out -# scripts/cleanup -fi diff --git a/regress/tests/span-vol-test b/regress/tests/span-vol-test deleted file mode 100755 index a73dbfba0d..0000000000 --- a/regress/tests/span-vol-test +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory but -# split the archive into four volumes, two of which are -# totally full. I.e. make sure that bsr selects all tapes -# including those fully spanned. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting span-vol-test ===" -echo " === Starting span-vol-test ===" >working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! span-vol-test Bacula source failed!!! !!!!! " - echo " !!!!! span-vol-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== span-vol-test Bacula source OK ===== " - echo " ===== span-vol-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/sparse-compressed-test b/regress/tests/sparse-compressed-test deleted file mode 100755 index 3f2fcb9341..0000000000 --- a/regress/tests/sparse-compressed-test +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory using the Sparse option -# then restore it. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting sparse-compressed-test ===" -echo " === Starting sparse-compressed-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! sparse-compressed-test Bacula source failed!!! !!!!! " - echo " !!!!! sparse-compressed-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== sparse-compressed-test Bacula source OK ===== " - echo " ===== sparse-compressed-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/sparse-test b/regress/tests/sparse-test deleted file mode 100755 index aaecc63342..0000000000 --- a/regress/tests/sparse-test +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory using the Sparse option -# then restore it. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting sparse-test ===" -echo " === Starting sparse-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! sparse-test Bacula source failed!!! !!!!! " - echo " !!!!! sparse-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== sparse-test Bacula source OK ===== " - echo " ===== sparse-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/test0 b/regress/tests/test0 deleted file mode 100755 index 0d0edd0b85..0000000000 --- a/regress/tests/test0 +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -echo " " >test.out -rm -f bin/working/* diff --git a/regress/tests/two-jobs-test b/regress/tests/two-jobs-test deleted file mode 100755 index d848ce423f..0000000000 --- a/regress/tests/two-jobs-test +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory using the compressed option -# then backup a second time and finally restore it -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting two-jobs-test ===" -echo " === Starting two-jobs-test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! two-jobs-test Bacula source failed!!! !!!!! " - echo " !!!!! two-jobs-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== two-jobs-test Bacula source OK ===== " - echo " ===== two-jobs-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/two-vol-test b/regress/tests/two-vol-test deleted file mode 100755 index 53ca3cf8f8..0000000000 --- a/regress/tests/two-vol-test +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory but -# split the archive into two volumes -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting two-vol-test ===" -echo " === Starting two-vol-test ===" >working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! two-vol-test Bacula source failed!!! !!!!! " - echo " !!!!! two-vol-test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== two-vol-test Bacula source OK ===== " - echo " ===== two-vol-test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/two-volume-tape b/regress/tests/two-volume-tape deleted file mode 100755 index 31c7d795ea..0000000000 --- a/regress/tests/two-volume-tape +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# to two tapes where the maximum tape file size is set to 1M -# -cwd=`pwd` -bin/bacula stop 2>&1 >/dev/null -scripts/copy-tape-confs -mtx -f /dev/sg0 unload -mtx -f /dev/sg0 load 1 -mt -f /dev/nst0 rewind -mt -f /dev/nst0 weof -mtx -f /dev/sg0 unload -mtx -f /dev/sg0 load 2 -mt -f /dev/nst0 rewind -mt -f /dev/nst0 weof -mtx -f /dev/sg0 unload -echo "${cwd}/build" >/tmp/file-list -bin/drop_sqlite_tables -bin/make_sqlite_tables -out="tmp/sed_tmp" -echo "s%# Maximum File Size% Maximum File Size%g" >${out} -cp ${cwd}/bin/bacula-sd.conf ${cwd}/tmp/1 -sed -f ${out} ${cwd}/tmp/1 >${cwd}/bin/bacula-sd.conf - -echo " " -echo " " -echo " === Starting Two Volume Tape test ===" -echo " === Starting Two Volume Tape test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff -r build tmp/bacula-restores${cwd}/build 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Two Volume Tape test Bacula source failed!!! !!!!! " - echo " !!!!! Two Volume Tape test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Two Volume Tape test Bacula source OK ===== " - echo " ===== Two Volume Tape test OK ===== " >>test.out -# scripts/cleanup -fi diff --git a/regress/tests/verify-vol-test b/regress/tests/verify-vol-test deleted file mode 100755 index 1e841c2c84..0000000000 --- a/regress/tests/verify-vol-test +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then verify the catalog. -# -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/build" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting verify Volume Test ===" -echo " === Starting verify Volume Test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Verify OK" ${cwd}/tmp/original 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Verify Volume failed!!! !!!!! " - echo " !!!!! Verify Volume failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Verify Volume Test OK ===== " - echo " ===== Verify Volume Test OK ===== " >>test.out - scripts/cleanup -fi diff --git a/regress/tests/weird-files-test b/regress/tests/weird-files-test deleted file mode 100755 index 7237d40c3f..0000000000 --- a/regress/tests/weird-files-test +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then restore it. -# -if test ! -d weird-files ; then - echo " " - echo "Weird files not configured. Test not run." - exit 0 -fi -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -echo "${cwd}/weird-files" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting weird filenames test ===" -echo " === Starting weird filenames test ===" >>working/log -echo " " - -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -${cwd}/bin/testls weird-files >${cwd}/tmp/original -cd tmp/bacula-restores${cwd} -${cwd}/bin/testls weird-files >${cwd}/tmp/restored -cd ${cwd} -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff ${cwd}/tmp/original ${cwd}/tmp/restored 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Weird files test failed!!! !!!!! " - echo " !!!!! Weird files test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Weird files test OK ===== " - echo " ===== Weird files test OK ===== " >>test.out - cd ${cwd} - scripts/cleanup -fi diff --git a/regress/tests/weird-files2-test b/regress/tests/weird-files2-test deleted file mode 100755 index a618c4e4c0..0000000000 --- a/regress/tests/weird-files2-test +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/sh -# -# Run a simple backup of the Bacula build directory -# then restore it. -# -if test ! -d weird-files ; then - echo " " - echo "weird files not configured. Test not run." - exit 0 -fi -cwd=`pwd` -scripts/copy-test-confs -scripts/cleanup -rm -rf weird-files2 -cp -a weird-files weird-files2 -echo "${cwd}/weird-files2" >/tmp/file-list -bin/bacula stop 2>&1 >/dev/null -bin/drop_sqlite_tables -bin/make_sqlite_tables - -echo " " -echo " " -echo " === Starting weird filenames2 test ===" -echo " === Starting weird filenames2 test ===" >>working/log -echo " " - -bin/testls weird-files2 >${cwd}/tmp/original -bin/bacula start 2>&1 >/dev/null -bin/console -c bin/console.conf <&1 >/dev/null -bin/testls weird-files2 >${cwd}/tmp/restored -grep "^Termination: *Backup OK" tmp/log1.out 2>&1 >/dev/null -bstat=$? -grep "^Termination: *Restore OK" tmp/log2.out 2>&1 >/dev/null -rstat=$? -diff ${cwd}/tmp/original ${cwd}/tmp/restored 2>&1 >/dev/null -if [ $? != 0 -o $bstat != 0 -o $rstat != 0 ] ; then - echo " " - echo " " - echo " !!!!! Weird files2 test failed!!! !!!!! " - echo " !!!!! Weird files2 test failed!!! !!!!! " >>test.out - echo " " -else - echo " ===== Weird files2 test OK ===== " - echo " ===== Weird files2 test OK ===== " >>test.out - cd ${cwd} - scripts/cleanup - rm -rf weird-files2 -fi diff --git a/regress/weird-files.tar.gz b/regress/weird-files.tar.gz deleted file mode 100644 index 0ecbe3fc7215241cdfc3dfc18801eaaf23de9be2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1510 zcmV3jpzGcg;*U?PM}tbUIyh14)p` zu|%dM6p#PD0AxwfBca%kupQmAk!*?r%)@hVfqMx*n4+HJMX@r?WHb;6;Y2CnUI|f> zAH6dBXb<|C~AgMV4_Xl)o3Kl0=RW>GKc$5^kLTKU+Az8$Wjs z0Yf6ze_7RQz4Gt-ZNuyTYyMB2*$4egMydZj<%DOT{}iyMv8Y-gjkfFuFL;Nh8;c5y zW>sl*Q8q|hv@*J}W9EFKo}*P!-Z#ir?nB@ZuNkra^|Yy08*6Y=Ev#p_r#5^%r<7`m z|5PS@oG9doFu|D^AvVdYwV8P3O{RLbS?Nh_mbGb`$+pA0ewuGEtQ*&V%)eK*zns`s zxX-bmHU4Aj5dU!>|4HT!ga0SMMgIp&zZt~(Z#L6;QTM+LaNYcW8~&Fs6fpl! zfeZZW7cl;3e*LF){O@Cs0{&0=-?86Y7|@-6_j&2~zq=c3PPzy1f3E*sAlOqIZS()w z|HJ&BQLdc+X^O=O;D3LKr^OQgJwO&9jQ^hFHvYL(RE70_mBIL*1Tp_}T`ryMm$*mm zdvx=E=Mz*2>iu8i0ge9&!2iMjZ85ul#M8p|+eWMZGrrTmRDy=}U!q|Cp8`Mr;B3E~ zH2K)f@(R7li#IU&zabpy-`Gtt@85H~=-Fw|MxXtN)q8F3f$*{T>K{(_i)x5Ae1-QF{8OSbp_E_$W0Je^Uk=fkQvm-_{qOAU+$?%;<4XN| z{$*GTrkRTXLH{Wb^Z!R(Eo;4AzwNn=EBW`qAEP1vn+b^j(jex4sOxTJyz<&~i z{D0vy|NcqPJ9PNj-w2^HU~DTiHHXRoGl!~x?*^wOR?n?}Cj9)5a|!W(5?rtU{k|Wd z|L+KA`uA^pUI@4{{yXU3h5vs1Kdb*7!klhg|7Y>vApCcH{+CJ~p8pyuAdLb1pXv0Ay2e;kke=wqn8Up@Nm z!Q6ReW#hDKdTtu<3rj8DbbvZ{(UTs!$A6{(A?Khx@+?1$x z!AMm@q%k-y`hRl$i@pA37V^JRLH;iZ&h;P7^S7HpImx>t<#K!w>(k-zhyc1Q`SGdV z-=T-?iSC?t$cx_}dlLHYyKA$qKAUi4-w*JB0dY6EoBZ;jDwiMneda&LKE}KJN@}1NG+!JN?&H_0=-Rw&Sl9vHyE7z`r&4J^stokJ#T8_}8K~GpEo;{86t8 zrh8zv2hR4u`~WNt!14gB4!}R{fq&iuA8v-hHYEoHB;dcx{_ot)75)BSR4Um2B?VrB z|8q&s{a=9pr@)K%|MyQ1rN4~cJU3mvh&kpwTn|HGayC;qR%|C0dx zzgutcXMbr{zBB%!mCw?R*TsK({?Et!C;kunzo)_PoAMsbwbii51^@s6000000DSlO M57A4ZDFAo?0H&KcCjbBd -- 2.39.2