From: Kern Sibbald Date: Tue, 18 Nov 2003 21:05:27 +0000 (+0000) Subject: Update to cygwin 1.5.5+add slots=1,3... code X-Git-Tag: Release-7.0.0~9913 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a002d989df13b7bbd4199d1844a8536bc99586ec;p=bacula%2Fbacula Update to cygwin 1.5.5+add slots=1,3... code git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@808 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 16c0ee65f6..6f2a411641 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,84 @@ +2003-11-xx Version 1.33 xxNov03 +18Nov03 +- Start daemons at level 90 rather than 20 so that MySQL will already + be started. +- Write alter_mysql_tables.in and alter_sqlite_tables.in +- Add Drive and InChanger to Media record. +- Update database level to 7. +- Add db_make_inchanger_unique() and call it when creating and updating + the Media record. +- Add Drive and InChanger to database code for Media record. +- Allow changing InChanger flag in update command. +- First cut at allowing the user to specify slots for updating autochanger. +- Add scan to "update slots scan". +- Add command in SD to readlabel. +15Nov03 +- In the bacula start/stop script, ordered the stop: FD SD Dir to + give the SD the best chances of updating the catalog before dying. +- Add Drive and InChanger to MEDIA_DBR record and to Volume update + from the SD. +- Reorganize the Volume info update from SD so that the Dir sends back the + current information in case the Volume status has changed by expiring. + The DIR-SD protocol is not backward compatible (must update). +- Fixed the signal handler to pass the signal to the exit_handler() + previously it passed 1. +- Modified SD so that on normal shutdown, it walks through all jcrs and + cancels them so that the Volume status will be updated in the catalog. +- Found and fixed a bug where ST_LABEL was not set in append mode + (when a different tape was accepted other than the original one + proposed by the DIR. +- Update the catalog Volume info after dev->file is incremented rather + than waiting for end of job. +12Nov03 +- Change getdomainname() prototype for Darwin. +- Add gethost_strerror() to create correct error message for + gethostbyname(). +- After doing a kill() of a stalled connection in watchdog, turn off + the timer to prevent an infinite loop. +- Allow Bacula to rewrite the label on a disk volume. +- Correct usage report printed by bsmtp. +11Nov03 +- Complete changing references to bsmtp from smtp. +- Add L_NONE for Admin and Restore jobs and update level_to_str() +- Fix segfault from double free of RestoreBootstrap in job.c +10Nov03 +- Change console to bconsole +- Change console.conf to bconsole.conf +- Change smtp to bsmtp +- Implement .bconsolerc +- Check if volume has expired when doing an update media for the SD +09Nov03 +- Implement new code that assures that a non-zero Slot is unique within + a given Pool. When setting a non-zero Slot, the Slot of all other + Volumes with the same Slot is set to zero. +07Nov03 +- Fix bug reported by Lars where an incorrect Volume name was printed + by the "status dir" command. +06Nov03 +- Pretty up a few error messages printed by smtp. +- Make btime_t int64_t so that one can do arithmetic. +- Implement since as utime (64 bit UTC). +- Compute clock diff between Dir and FD, and adjust since time. +- Apply SQL fix from Nic Bellamy (thanks). +- Apply John's zlib #ifdefing fix. +05Nov03 +- Add Dan's with-sd-user, ... to configure.in. +- Add Dan's userid and group modifications to bacula.in +- Lots of documentation updates. +- Make console print "Enter a period to cancel a command" when starting. +- Fix the "list nextvol" command so that it doesn't try to close the + database twice, giving a segfault. +- Fix (hopefully) to dircmd.c so that a mount request does a pthread_cond_signal. + There was one path were the signal was not sent. This should fix the bug + that requires you to do two "mount" commands to free a job waiting on a mount. +- Make dir_ask_sysop_to_mount_next_volume() return immediately if a slot is + specified. +- Correct some of the messages in testfind.c (pointed out by Dan -- thanks). +- Alias fd to client, sd to storage. +- Changed order of Console commands so that short commands such as q (quit) + are more logical. + 2003-11-03 Version 1.32d 02Nov03 Release 02Nov03 - Mainly a bug fix release. diff --git a/bacula/Makefile.in b/bacula/Makefile.in index 0fb34b60f1..fedea8aa3f 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -120,9 +120,10 @@ Makefiles: chmod 755 src/cats/make_test_tables src/cats/drop_test_tables chmod 755 src/cats/create_mysql_database chmod 755 src/cats/make_catalog_backup src/cats/delete_catalog_backup - chmod 755 src/cats/alter_mysql_tables + chmod 755 src/cats/update_mysql_tables chmod 755 src/cats/create_sqlite_database - chmod 755 src/cats/alter_sqlite_tables + chmod 755 src/cats/update_sqlite_tables + chomd 755 src/cats/update_bacula_tables chmod 755 src/cats/create_bdb_database chmod 755 src/cats/grant_mysql_privileges diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index a53eb61ac3..4e851806ce 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -1,117 +1,22 @@ - Release Notes for Bacula 1.32d + Release Notes for Bacula 1.33 Bacula code: Total files = 259 Total lines = 78,087 (*.h *.c *.in) -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.32d +- Implement "update slots scan" that reads the volume label. -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. -- There is a new option to restore that allows you - to restore files based on their Filename. You can - also specify a file to read which contains the list. -- Added ClientRunBeforeJob and ClientRunAfterJob. -- Implemented Include | and < in File daemon. -- Automatic labeling of tape Volumes should work now. -- Recycling has been completely restructured and should work. -- Implemented full length time interval qualifiers (e.g - "5n is now "5 min" or "5 minutes". A modifier is now required! -- Fixed gnome-console to compile with RH9 (Gnome 2.0) -- Implemented "list nextvol job=xxx", which displays the - next volume to be used by job xxx. The Volume name to - 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 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. -- Implemented a single routine to read_records. It also returns - a different record packet for each session. This means - that multiple simultaneous jobs should work. -- Added SDConnectTimeout to FD. -- Lots of doc enhancements -- Fixed a PurgeOldestVolume bug (VolStatus not returned) -- Don't crash if DB address record not specified. -- Return VolStatus on find_next_volume. -- Use alist for incexe name_list. -- Use bget_dirmsg() everywhere possible when talking to FD. -- Delete old semaphore job and workq job scheduling code. -- edit_run_codes in one place (/lib) Add Job name -- Update query.sql to find current backups correctly. -- Correct ambiguous SQL statement for pruning. -- Set heartbeat interval to zero by default. -- Fix a possible race condition in stopping the - heartbeat thread. -- Eliminate gnome2-console directory. Everything is in gnome-console -- Enhanced "packet too big" message to indicate who sent it. -- Corrected console prompt problem in non-readline versions. -- Correct a number of variable expansion problems. -- Added a number of new regression tests. -- In an attempt to make configuration a bit less confusing, I've changed - the name of a number of variables. The old ones still work, but will - be phased out over time. FDAddress, FDPassword, SDAddress SDPassword, - SDDeviceName, and DBPassword. -- A possible fix to the very intermittent SD crashes that Alex gets. - Items to note: !!!!! -- Modifiers (sec, min, hour, day, ...) are now required on conf file - time interval specifications. -- Duplicate names within the same conf resource are prohibited. -- If you have used a prior BETA version of 1.32, please do - the following to cleanup any zero length spool files: +- The daemon protocol has changed, you must update everything at once. +- The database level has been updated. You must either re-initialize + your databases with: + + ./drop_bacula_tables + ./make_bacula_tables - cd - rm -f *.spool.* + which will delete ALL prior catalog information, or you can + update your database with: - Please be sure there are no spaces between the asterisks - and the periods. + ./alter_bacula_tables diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index 664b8f0a34..91207688a1 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -1518,14 +1518,14 @@ AC_OUTPUT([autoconf/Make.common \ 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/update_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/update_sqlite_tables \ src/cats/create_sqlite_database \ src/cats/sqlite \ src/cats/mysql \ @@ -1534,6 +1534,7 @@ AC_OUTPUT([autoconf/Make.common \ src/cats/drop_bdb_tables \ src/cats/make_bacula_tables \ src/cats/drop_bacula_tables \ + src/cats/update_bacula_tables \ src/findlib/Makefile \ src/tools/Makefile \ $PFILES ], @@ -1548,12 +1549,12 @@ chmod 755 src/cats/make_mysql_tables src/cats/drop_mysql_tables chmod 755 src/cats/make_test_tables src/cats/drop_test_tables chmod 755 src/cats/create_mysql_database chmod 755 src/cats/make_catalog_backup src/cats/delete_catalog_backup -chmod 755 src/cats/alter_mysql_tables chmod 755 src/cats/grant_mysql_privileges chmod 755 src/cats/make_sqlite_tables src/cats/drop_sqlite_tables chmod 755 src/cats/make_bacula_tables src/cats/drop_bacula_tables +chmod 755 src/cats/update_bacula_tables src/cats/update_mysql_tables +chmod 755 src/cats/update/mysql_tables chmod 755 src/cats/create_sqlite_database -chmod 755 src/cats/alter_sqlite_tables chmod 755 src/cats/sqlite chmod 755 src/cats/make_bdb_tables src/cats/drop_bdb_tables chmod 755 src/cats/create_bdb_database diff --git a/bacula/configure b/bacula/configure index 5e93cb11a1..258c1663fa 100755 --- a/bacula/configure +++ b/bacula/configure @@ -17576,7 +17576,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/bconsole 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/bconsole.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_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/bconsole 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/bconsole.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/make_mysql_tables src/cats/drop_mysql_tables src/cats/update_mysql_tables src/cats/create_mysql_database src/cats/grant_mysql_privileges src/cats/make_sqlite_tables src/cats/drop_sqlite_tables src/cats/update_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/cats/update_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 @@ -18146,14 +18146,14 @@ do "src/cats/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/cats/Makefile" ;; "src/cats/make_catalog_backup" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_catalog_backup" ;; "src/cats/delete_catalog_backup" ) CONFIG_FILES="$CONFIG_FILES src/cats/delete_catalog_backup" ;; - "src/cats/alter_mysql_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/alter_mysql_tables" ;; "src/cats/make_mysql_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_mysql_tables" ;; "src/cats/drop_mysql_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_mysql_tables" ;; + "src/cats/update_mysql_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/update_mysql_tables" ;; "src/cats/create_mysql_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_mysql_database" ;; "src/cats/grant_mysql_privileges" ) CONFIG_FILES="$CONFIG_FILES src/cats/grant_mysql_privileges" ;; - "src/cats/alter_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/alter_sqlite_tables" ;; "src/cats/make_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_sqlite_tables" ;; "src/cats/drop_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_sqlite_tables" ;; + "src/cats/update_sqlite_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/update_sqlite_tables" ;; "src/cats/create_sqlite_database" ) CONFIG_FILES="$CONFIG_FILES src/cats/create_sqlite_database" ;; "src/cats/sqlite" ) CONFIG_FILES="$CONFIG_FILES src/cats/sqlite" ;; "src/cats/mysql" ) CONFIG_FILES="$CONFIG_FILES src/cats/mysql" ;; @@ -18162,6 +18162,7 @@ do "src/cats/drop_bdb_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_bdb_tables" ;; "src/cats/make_bacula_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/make_bacula_tables" ;; "src/cats/drop_bacula_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/drop_bacula_tables" ;; + "src/cats/update_bacula_tables" ) CONFIG_FILES="$CONFIG_FILES src/cats/update_bacula_tables" ;; "src/findlib/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/findlib/Makefile" ;; "src/tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/tools/Makefile" ;; "$PFILES" ) CONFIG_FILES="$CONFIG_FILES $PFILES" ;; @@ -18937,12 +18938,12 @@ chmod 755 src/cats/make_mysql_tables src/cats/drop_mysql_tables chmod 755 src/cats/make_test_tables src/cats/drop_test_tables chmod 755 src/cats/create_mysql_database chmod 755 src/cats/make_catalog_backup src/cats/delete_catalog_backup -chmod 755 src/cats/alter_mysql_tables chmod 755 src/cats/grant_mysql_privileges chmod 755 src/cats/make_sqlite_tables src/cats/drop_sqlite_tables chmod 755 src/cats/make_bacula_tables src/cats/drop_bacula_tables +chmod 755 src/cats/update_bacula_tables src/cats/update_mysql_tables +chmod 755 src/cats/update/mysql_tables chmod 755 src/cats/create_sqlite_database -chmod 755 src/cats/alter_sqlite_tables chmod 755 src/cats/sqlite chmod 755 src/cats/make_bdb_tables src/cats/drop_bdb_tables chmod 755 src/cats/create_bdb_database diff --git a/bacula/kernstodo b/bacula/kernstodo index 2dd8c85eb8..ad5eecdb11 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -47,6 +47,31 @@ For 1.33 Testing/Documentation: For 1.33 +- Optimize fsf not to read. +- 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. +- Implement autochanger testing in btape "test" command. +- Make sure that Volumes are recycled based on "Least recently used" + rather than lowest MediaId. +- 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. +- Enhance "update slots" to include a "scan" feature + scan 1; scan 1-5; scan 1,2,4 ... to update the catalog +- Allow a slot or range of slots on the label barcodes command. +- Finish implementation of Verify=DiskToCatalog +- Possibly up network buffers to 65K. +- Keep last 5 or 10 completed jobs and show them in a similar list. +- Make a Running Jobs: output similar to current Scheduled Jobs: +- Optimize fsf not to read. +- 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. +- Implement autochanger testing in btape "test" command. + +After 1.33: +- Print warning message if FileId > 4 billion - do a "messages" before the first prompt in Console - Add a date and time stamp at the beginning of every line in the Job report (Volker Sauer). @@ -117,29 +142,6 @@ For 1.33 to start a job or pass its DHCP obtained IP number. - Implement multiple Consoles. - Implement a query tape prompt/replace feature for a console -- Make sure that Volumes are recycled based on "Least recently used" - rather than lowest MediaId. -- 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. -- Enhance "update slots" to include a "scan" feature - scan 1; scan 1-5; scan 1,2,4 ... to update the catalog -- Allow a slot or range of slots on the label barcodes command. -- 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. -- Keep last 5 or 10 completed jobs and show them in a similar list. -- Make a Running Jobs: output similar to current Scheduled Jobs: -- Fix TimeZone problem! -- Optimize fsf not to read. -- 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. -- Implement autochange testing in btape. - From Johan? Two jobs ready to go, first one blocked waiting for media Cancel 2nd job ("waiting execution" one) @@ -184,19 +186,9 @@ For 1.33 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. -- 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 - 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. @@ -648,11 +640,16 @@ Migration triggered by: It is somewhat like a Full save becomes an incremental since the Base job (or jobs) plus other non-base files. Need: -- New BaseFile table that contains: - JobId, BaseJobId, FileId (from Base). +- A Base backup is same as Full backup, just different type. +- New BaseFiles table that contains: + BaseId - index + BaseJobId - Base JobId referenced for this FileId (needed ???) + JobId - JobId currently running + FileId - File not backed up, exists in Base Job + FileIndex - FileIndex from Base Job. i.e. for each base file that exists but is not saved because it has not changed, the File daemon sends the JobId, BaseId, - and FileId back to the Director who creates the DB entry. + FileId, FileIndex back to the Director who creates the DB entry. - To initiate a Base save, the Director sends the FD the FileId, and full filename for each file in the Base. - When the FD finds a Base file, he requests the Director to @@ -890,3 +887,18 @@ Done: (see kernsdone for more) - Implement ClientRunBeforeJob and ClientRunAfterJob. - Implement forward spacing block/file: position_device(bsr) -- just before read_block_from_device(); +- Change console to bconsole. +- Change smtp to bsmtp. +- Fix time difference problem between Bacula and Client + so that everything is in GMT. +- Fix TimeZone problem! +- 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 +- Upgrade to cygwin 1.5 diff --git a/bacula/platforms/redhat/bacula-dir.in b/bacula/platforms/redhat/bacula-dir.in index d568cdb999..05fec1b712 100755 --- a/bacula/platforms/redhat/bacula-dir.in +++ b/bacula/platforms/redhat/bacula-dir.in @@ -3,7 +3,7 @@ # bacula This shell script takes care of starting and stopping # the bacula Director daemon # -# chkconfig: 2345 20 99 +# chkconfig: 2345 90 99 # description: It comes by night and sucks the vital essence from your computers. # # For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@ diff --git a/bacula/platforms/redhat/bacula-fd.in b/bacula/platforms/redhat/bacula-fd.in index 19f04f028b..8b725bc722 100755 --- a/bacula/platforms/redhat/bacula-fd.in +++ b/bacula/platforms/redhat/bacula-fd.in @@ -3,7 +3,7 @@ # bacula This shell script takes care of starting and stopping # the bacula File daemon. # -# chkconfig: 2345 20 99 +# chkconfig: 2345 90 99 # description: It comes by night and sucks the vital essence from your computers. # # For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@ diff --git a/bacula/platforms/redhat/bacula-sd.in b/bacula/platforms/redhat/bacula-sd.in index a4bfdd4f5a..e58287625d 100755 --- a/bacula/platforms/redhat/bacula-sd.in +++ b/bacula/platforms/redhat/bacula-sd.in @@ -3,7 +3,7 @@ # bacula This shell script takes care of starting and stopping # the bacula Storage daemon. # -# chkconfig: 2345 20 99 +# chkconfig: 2345 90 99 # description: It comes by night and sucks the vital essence from your computers. # # For Bacula release @VERSION@ (@DATE@) -- @DISTNAME@ diff --git a/bacula/src/cats/.cvsignore b/bacula/src/cats/.cvsignore index c2353f3f7f..e7a8344a05 100644 --- a/bacula/src/cats/.cvsignore +++ b/bacula/src/cats/.cvsignore @@ -2,8 +2,6 @@ Makefile make_catalog_backup delete_catalog_backup -alter_mysql_tables -alter_sqlite_tables create_bdb_database create_mysql_database create_sqlite_database @@ -20,3 +18,8 @@ mysql sqlite make_bacula_tables drop_bacula_tables +update.sql +update2_sqlite_tables +update_bacula_tables +update_mysql_tables +update_sqlite_tables diff --git a/bacula/src/cats/Makefile.in b/bacula/src/cats/Makefile.in index e4ee4d48af..ad9ad1dafe 100644 --- a/bacula/src/cats/Makefile.in +++ b/bacula/src/cats/Makefile.in @@ -64,8 +64,9 @@ realclean: clean $(RMF) create_mysql_database make_sqlite_tables sqlite $(RMF) create_bdb_database drop_bdb_tables make_dbd_tables $(RMF) make_catalog_backup delete_catalog_backup - $(RMF) alter_mysql_tables alter_sqlite_tables create_sqlite_database + $(RMF) update_mysql_tables update_sqlite_tables create_sqlite_database $(RMF) drop_bacula_tables drop_sqlite_tables make_bacula_tables + $(RMF) update_bacula_tables $(RMF) drop_bdb_tables make_bdb_tables mysql distclean: realclean @@ -76,8 +77,10 @@ install: $(INSTALL_SCRIPT) create_@DB_NAME@_database $(DESTDIR)$(scriptdir)/create_@DB_NAME@_database $(INSTALL_SCRIPT) drop_@DB_NAME@_tables $(DESTDIR)$(scriptdir)/drop_@DB_NAME@_tables $(INSTALL_SCRIPT) make_@DB_NAME@_tables $(DESTDIR)$(scriptdir)/make_@DB_NAME@_tables + $(INSTALL_SCRIPT) update_@DB_NAME@_tables $(DESTDIR)$(scriptdir)/update_@DB_NAME@_tables $(INSTALL_SCRIPT) drop_bacula_tables $(DESTDIR)$(scriptdir)/drop_bacula_tables $(INSTALL_SCRIPT) make_bacula_tables $(DESTDIR)$(scriptdir)/make_bacula_tables + $(INSTALL_SCRIPT) update_bacula_tables $(DESTDIR)$(scriptdir)/update_bacula_tables $(INSTALL_SCRIPT) make_catalog_backup $(DESTDIR)$(scriptdir)/make_catalog_backup $(INSTALL_SCRIPT) delete_catalog_backup $(DESTDIR)$(scriptdir)/delete_catalog_backup $(INSTALL_SCRIPT) grant_mysql_privileges $(DESTDIR)$(scriptdir)/grant_mysql_privileges @@ -86,8 +89,10 @@ uninstall: (cd $(DESTDIR)$(scriptdir); $(RMF) create_@DB_NAME@_database) (cd $(DESTDIR)$(scriptdir); $(RMF) drop_@DB_NAME@_tables) (cd $(DESTDIR)$(scriptdir); $(RMF) make_@DB_NAME@_tables) + (cd $(DESTDIR)$(scriptdir); $(RMF) update_@DB_NAME@_tables) (cd $(DESTDIR)$(scriptdir); $(RMF) drop_bacula_tables) (cd $(DESTDIR)$(scriptdir); $(RMF) make_bacula_tables) + (cd $(DESTDIR)$(scriptdir); $(RMF) update_bacula_tables) (cd $(DESTDIR)$(scriptdir); $(RMF) make_catalog_backup) (cd $(DESTDIR)$(scriptdir); $(RMF) delete_catalog_backup) (cd $(DESTDIR)$(scriptdir); $(RMF) grant_mysql_privileges) diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 62eedfc3a1..f17fecad42 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -48,7 +48,7 @@ typedef int (DB_RESULT_HANDLER)(void *, int, char **); #ifdef HAVE_SQLITE -#define BDB_VERSION 6 +#define BDB_VERSION 7 #include @@ -142,7 +142,7 @@ extern void my_sqlite_free_table(B_DB *mdb); #ifdef HAVE_MYSQL -#define BDB_VERSION 6 +#define BDB_VERSION 7 #include diff --git a/bacula/src/cats/make_mysql_tables.in b/bacula/src/cats/make_mysql_tables.in index d84dad313f..2f49e34821 100644 --- a/bacula/src/cats/make_mysql_tables.in +++ b/bacula/src/cats/make_mysql_tables.in @@ -24,7 +24,7 @@ CREATE TABLE Path ( # ****FIXME**** make FileId BIGINT someday when MySQL works ***** CREATE TABLE File ( FileId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - FileIndex INTEGER UNSIGNED NOT NULL, + FileIndex INTEGER UNSIGNED NOT NULL DEFAULT 0, JobId INTEGER UNSIGNED NOT NULL REFERENCES Job, PathId INTEGER UNSIGNED NOT NULL REFERENCES Path, FilenameId INTEGER UNSIGNED NOT NULL REFERENCES Filename, @@ -50,12 +50,12 @@ CREATE TABLE Job ( StartTime DATETIME NOT NULL, EndTime DATETIME NOT NULL, JobTDate BIGINT UNSIGNED NOT NULL, - VolSessionId INTEGER UNSIGNED NOT NULL, - VolSessionTime INTEGER UNSIGNED NOT NULL, - JobFiles INTEGER UNSIGNED NOT NULL, + VolSessionId INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolSessionTime INTEGER UNSIGNED NOT NULL DEFAULT 0, + JobFiles INTEGER UNSIGNED NOT NULL DEFAULT 0, JobBytes BIGINT UNSIGNED NOT NULL, - JobErrors INTEGER UNSIGNED NOT NULL, - JobMissingFiles INTEGER UNSIGNED NOT NULL, + JobErrors INTEGER UNSIGNED NOT NULL DEFAULT 0, + JobMissingFiles INTEGER UNSIGNED NOT NULL DEFAULT 0, PoolId INTEGER UNSIGNED NOT NULL REFERENCES Pool, FileSetId INTEGER UNSIGNED NOT NULL REFERENCES FileSet, PurgedFiles TINYINT NOT NULL DEFAULT 0, @@ -77,13 +77,13 @@ CREATE TABLE JobMedia ( JobMediaId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, JobId INTEGER UNSIGNED NOT NULL REFERENCES Job, MediaId INTEGER UNSIGNED NOT NULL REFERENCES Media, - FirstIndex INTEGER UNSIGNED NOT NULL, - LastIndex INTEGER UNSIGNED NOT NULL, - StartFile INTEGER UNSIGNED NOT NULL, - EndFile INTEGER UNSIGNED NOT NULL, - StartBlock INTEGER UNSIGNED NOT NULL, - EndBlock INTEGER UNSIGNED NOT NULL, - VolIndex INTEGER UNSIGNED NOT NULL, + FirstIndex INTEGER UNSIGNED NOT NULL DEFAULT 0, + LastIndex INTEGER UNSIGNED NOT NULL DEFAULT 0, + StartFile INTEGER UNSIGNED NOT NULL DEFAULT 0, + EndFile INTEGER UNSIGNED NOT NULL DEFAULT 0, + StartBlock INTEGER UNSIGNED NOT NULL DEFAULT 0, + EndBlock INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolIndex INTEGER UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY(JobMediaId), INDEX (JobId, MediaId) ); @@ -98,22 +98,24 @@ CREATE TABLE Media ( FirstWritten DATETIME NOT NULL, LastWritten DATETIME NOT NULL, LabelDate DATETIME NOT NULL, - VolJobs INTEGER UNSIGNED NOT NULL, - VolFiles INTEGER UNSIGNED NOT NULL, - VolBlocks INTEGER UNSIGNED NOT NULL, - VolMounts INTEGER UNSIGNED NOT NULL, - VolBytes BIGINT UNSIGNED NOT NULL, - VolErrors INTEGER UNSIGNED NOT NULL, - VolWrites INTEGER UNSIGNED NOT NULL, + VolJobs INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolFiles INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolBlocks INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolMounts INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolBytes BIGINT UNSIGNED NOT NULL DEFAULT 0, + VolErrors INTEGER UNSIGNED NOT NULL DEFAULT 0, + VolWrites INTEGER UNSIGNED NOT NULL DEFAULT 0, VolCapacityBytes BIGINT UNSIGNED NOT NULL, VolStatus ENUM('Full', 'Archive', 'Append', 'Recycle', 'Purged', 'Read-Only', 'Disabled', 'Error', 'Busy', 'Used', 'Cleaning') NOT NULL, - Recycle TINYINT NOT NULL, - VolRetention BIGINT UNSIGNED NOT NULL, - VolUseDuration BIGINT UNSIGNED NOT NULL, - MaxVolJobs INTEGER UNSIGNED NOT NULL, - MaxVolFiles INTEGER UNSIGNED NOT NULL, - MaxVolBytes BIGINT UNSIGNED NOT NULL, + Recycle TINYINT NOT NULL DEFAULT 0, + VolRetention BIGINT UNSIGNED NOT NULL DEFAULT 0, + VolUseDuration BIGINT UNSIGNED NOT NULL DEFAULT 0, + MaxVolJobs INTEGER UNSIGNED NOT NULL DEFAULT 0, + MaxVolFiles INTEGER UNSIGNED NOT NULL DEFAULT 0, + MaxVolBytes BIGINT UNSIGNED NOT NULL DEFAULT 0, + Drive INTEGER NOT NULL DEFAULT 0, + InChanger TINYINT NOT NULL DEFAULT 0, PRIMARY KEY(MediaId), INDEX (PoolId) ); @@ -121,15 +123,15 @@ CREATE TABLE Media ( CREATE TABLE Pool ( PoolId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, Name TINYBLOB NOT NULL, - NumVols INTEGER UNSIGNED NOT NULL, - MaxVols INTEGER UNSIGNED NOT NULL, + NumVols INTEGER UNSIGNED NOT NULL DEFAULT 0, + MaxVols INTEGER UNSIGNED NOT NULL DEFAULT 0, UseOnce TINYINT NOT NULL, UseCatalog TINYINT NOT NULL, AcceptAnyVolume TINYINT DEFAULT 0, VolRetention BIGINT UNSIGNED NOT NULL, VolUseDuration BIGINT UNSIGNED NOT NULL, - MaxVolJobs INTEGER UNSIGNED NOT NULL, - MaxVolFiles INTEGER UNSIGNED NOT NULL, + MaxVolJobs INTEGER UNSIGNED NOT NULL DEFAULT 0, + MaxVolFiles INTEGER UNSIGNED NOT NULL DEFAULT 0, MaxVolBytes BIGINT UNSIGNED NOT NULL, AutoPrune TINYINT DEFAULT 0, Recycle TINYINT DEFAULT 0, @@ -173,7 +175,7 @@ CREATE TABLE Version ( ); -- Initialize Version -INSERT INTO Version (VersionId) VALUES (6); +INSERT INTO Version (VersionId) VALUES (7); CREATE TABLE Counters ( Counter TINYBLOB NOT NULL, diff --git a/bacula/src/cats/make_sqlite_tables.in b/bacula/src/cats/make_sqlite_tables.in index 56244601a6..d6a77d4f3d 100644 --- a/bacula/src/cats/make_sqlite_tables.in +++ b/bacula/src/cats/make_sqlite_tables.in @@ -115,6 +115,8 @@ CREATE TABLE Media ( MaxVolJobs INTEGER UNSIGNED DEFAULT 0, MaxVolFiles INTEGER UNSIGNED DEFAULT 0, MaxVolBytes BIGINT UNSIGNED DEFAULT 0, + Drive INTEGER DEFAULT 0, + InChanger TINYINT DEFAULT 0, PRIMARY KEY(MediaId) ); @@ -184,7 +186,7 @@ CREATE TABLE Version ( ); -- Initialize Version -INSERT INTO Version (VersionId) VALUES (6); +INSERT INTO Version (VersionId) VALUES (7); CREATE TABLE Counters ( Counter TEXT NOT NULL, diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 441947369c..767492e635 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -31,7 +31,7 @@ /* sql.c */ B_DB *db_init_database(JCR *jcr, char *db_name, char *db_user, char *db_password, - char *db_address, int db_port, char *db_socket); + char *db_address, int db_port, char *db_socket); int db_open_database(JCR *jcr, B_DB *db); void db_close_database(JCR *jcr, B_DB *db); void db_escape_string(char *snew, char *old, int len); @@ -51,7 +51,7 @@ int db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr); int db_create_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *media_dbr); int db_create_client_record(JCR *jcr, B_DB *db, CLIENT_DBR *cr); int db_create_fileset_record(JCR *jcr, B_DB *db, FILESET_DBR *fsr); -int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr); +int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr); int db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jr); int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr); @@ -105,6 +105,6 @@ int db_update_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *mr); int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr); int db_add_SIG_to_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, char *SIG, int type); int db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId); -void db_make_slot_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); +void db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); #endif /* __SQL_PROTOS_H */ diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 2cca2d6e4c..b4a95977c2 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -256,8 +256,10 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) sql_free_result(mdb); } - /* Make sur Slot, if non-zero, is unique */ - db_make_slot_unique(jcr, mdb, mr); + /* Make sure that if InChanger is non-zero any other identical slot + * has InChanger zero. + */ + db_make_inchanger_unique(jcr, mdb, mr); /* Must create it */ if (mr->LabelDate) { @@ -269,8 +271,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) Mmsg(&mdb->cmd, "INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes," "Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," -"VolStatus,LabelDate,Slot,VolBytes) " -"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s','%s',%d,%s)", +"VolStatus,LabelDate,Slot,VolBytes,Drive,InChanger) " +"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s','%s',%d,%s,%d,%d)", mr->VolumeName, mr->MediaType, mr->PoolId, edit_uint64(mr->MaxVolBytes,ed1), @@ -282,7 +284,9 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->MaxVolFiles, mr->VolStatus, dt, mr->Slot, - edit_uint64(mr->VolBytes, ed5)); + edit_uint64(mr->VolBytes, ed5), + mr->Drive, + mr->InChanger); Dmsg1(500, "Create Volume: %s\n", mdb->cmd); if (!INSERT_DB(jcr, mdb, mdb->cmd)) { diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index b37efec6c5..2846fc8567 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -272,21 +272,21 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) stat = UPDATE_DB(jcr, mdb, mdb->cmd); } - /* Make sure Slot, if non-zero, is unique */ - db_make_slot_unique(jcr, mdb, mr); + /* Make sure InChanger is 0 for any record having the same Slot */ + db_make_inchanger_unique(jcr, mdb, mr); ttime = mr->LastWritten; localtime_r(&ttime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); - Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%u,\ - VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,\ - VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s',\ - Slot=%d WHERE VolumeName='%s'", - mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), - mr->VolMounts, mr->VolErrors, mr->VolWrites, - edit_uint64(mr->MaxVolBytes, ed2), dt, - mr->VolStatus, mr->Slot, mr->VolumeName); + Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%u," + "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," + "VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s'," + "Slot=%d,Drive=%d,InChanger=%d WHERE VolumeName='%s'", + mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), + mr->VolMounts, mr->VolErrors, mr->VolWrites, + edit_uint64(mr->MaxVolBytes, ed2), dt, + mr->VolStatus, mr->Slot, mr->VolumeName, mr->Drive, mr->InChanger); Dmsg1(400, "%s\n", mdb->cmd); @@ -296,16 +296,16 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) } /* - * If we have a non-zero Slot, ensure that no other Media - * record in this Pool has the same Slot by setting Slot=0. + * If we have a non-zero InChanger, ensure that no other Media + * record in this Pool has InChanger set on the same Slot. * * This routine assumes the database is already locked. */ void -db_make_slot_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) +db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) { - if (mr->Slot != 0) { - Mmsg(&mdb->cmd, "UPDATE Media SET Slot=0 WHERE PoolId=%u " + if (mr->InChanger != 0) { + Mmsg(&mdb->cmd, "UPDATE Media SET InChanger=0 WHERE PoolId=%u " "AND Slot=%d\n", mr->PoolId, mr->Slot); Dmsg1(400, "%s\n", mdb->cmd); UPDATE_DB(jcr, mdb, mdb->cmd); diff --git a/bacula/src/cats/update_bacula_tables.in b/bacula/src/cats/update_bacula_tables.in new file mode 100755 index 0000000000..a1b1984cac --- /dev/null +++ b/bacula/src/cats/update_bacula_tables.in @@ -0,0 +1,13 @@ +#!/bin/sh +# +# This routine alters the appropriately configured +# Bacula tables for either MySQL or SQLite +# +if test xsqlite = x@DB_NAME@ ; then + echo "Altering SQLite tables" + . ./update_sqlite_tables +fi +if test xmysql = x@DB_NAME@ ; then + echo "Altering MySQL tables" + . ./update_mysql_tables +fi diff --git a/bacula/src/cats/update_mysql_tables.in b/bacula/src/cats/update_mysql_tables.in new file mode 100755 index 0000000000..b017499574 --- /dev/null +++ b/bacula/src/cats/update_mysql_tables.in @@ -0,0 +1,47 @@ +#!/bin/sh +# +# Shell script to update MySQL tables from version 1.32 to 1.33 +# +echo " " +echo "Depending on the size of your database," +echo "this script may take several minutes to run." +echo " " +bindir=@SQL_BINDIR@ + +if $bindir/mysql $* -f < '9') { - return FALSE; - } - } - return TRUE; -} - /* Keywords (RHS) permitted in Run records */ static struct s_kw RunFields[] = { {"pool", 'P'}, @@ -420,7 +407,7 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass) *p++ = 0; /* separate two halves */ /* Check for day range */ - if (is_num(lc->str) && is_num(p)) { + if (is_an_integer(lc->str) && is_an_integer(p)) { code = atoi(lc->str) - 1; code2 = atoi(p) - 1; if (code < 0 || code > 30 || code2 < 0 || code2 > 30) { diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 0e36adb67d..c94fa5a253 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -184,7 +184,7 @@ static int add_cmd(UAContext *ua, char *cmd) int first_id = 0; char name[MAX_NAME_LENGTH]; STORE *store; - int slot = 0; + int Slot = 0, InChanger = 0; bsendmsg(ua, _( "You probably don't want to be using this command since it\n" @@ -287,13 +287,18 @@ getVolName: if (!get_pint(ua, _("Enter slot (0 for none): "))) { return 1; } - slot = ua->pint32_val; + Slot = ua->pint32_val; + if (!get_yesno(ua, _("InChanger? yes/no: "))) { + return 1; + } + InChanger = ua->pint32_val; } set_pool_dbr_defaults_in_media_dbr(&mr, &pr); for (i=startnum; i < num+startnum; i++) { bsnprintf(mr.VolumeName, sizeof(mr.VolumeName), name, i); - mr.Slot = slot++; + mr.Slot = Slot++; + mr.InChanger = InChanger; Dmsg1(200, "Create Volume %s\n", mr.VolumeName); if (!db_create_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, db_strerror(ua->db)); @@ -794,7 +799,7 @@ static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) if (!db_sql_query(ua->db, query, NULL, NULL)) { bsendmsg(ua, "%s", db_strerror(ua->db)); } else { - bsendmsg(ua, _("New recycle flag is: %s\n"), + bsendmsg(ua, _("New Recycle flag is: %s\n"), mr->Recycle==1?_("yes"):_("no")); } free_pool_memory(query); @@ -895,6 +900,7 @@ static int update_volume(UAContext *ua) add_prompt(ua, _("Maximum Volume Bytes")); add_prompt(ua, _("Recycle Flag")); add_prompt(ua, _("Slot")); + add_prompt(ua, _("InChanger Flag")); add_prompt(ua, _("Volume Files")); add_prompt(ua, _("Pool")); add_prompt(ua, _("Done")); @@ -971,7 +977,7 @@ static int update_volume(UAContext *ua) break; case 7: /* Slot */ - int slot; + int Slot; memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; @@ -983,13 +989,13 @@ static int update_volume(UAContext *ua) if (!get_pint(ua, _("Enter new Slot: "))) { return 0; } - slot = ua->pint32_val; - if (pr.MaxVols > 0 && slot > (int)pr.MaxVols) { + Slot = ua->pint32_val; + if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) { bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"), pr.MaxVols); break; } - mr.Slot = slot; + mr.Slot = Slot; /* * Make sure to use db_update... rather than doing this directly, * so that any Slot is handled correctly. @@ -1001,7 +1007,25 @@ static int update_volume(UAContext *ua) } break; - case 8: /* Volume Files */ + case 8: /* InChanger */ + bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger); + if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) { + return 0; + } + mr.InChanger = ua->pint32_val; + /* + * Make sure to use db_update... rather than doing this directly, + * so that any Slot is handled correctly. + */ + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db)); + } else { + bsendmsg(ua, _("New InChanger flag is: %s\n"), mr.InChanger); + } + break; + + + case 9: /* Volume Files */ int32_t VolFiles; bsendmsg(ua, _("Warning changing Volume Files can result\n" "in loss of data on your Volume\n\n")); @@ -1027,7 +1051,7 @@ static int update_volume(UAContext *ua) free_pool_memory(query); break; - case 9: /* Volume's Pool */ + case 10: /* Volume's Pool */ memset(&pr, 0, sizeof(POOL_DBR)); pr.PoolId = mr.PoolId; if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { @@ -1040,6 +1064,7 @@ static int update_volume(UAContext *ua) } update_volpool(ua, ua->cmd, &mr); return 1; + default: /* Done or error */ bsendmsg(ua, "Selection done.\n"); return 1; diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index b6e1c55c23..c79cef291f 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -43,8 +43,12 @@ static int do_label(UAContext *ua, char *cmd, int relabel); static void label_from_barcodes(UAContext *ua); static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, POOL_DBR *pr, int relabel, bool media_record_exits); -static vol_list_t *get_slot_list_from_SD(UAContext *ua); +static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan); +static void free_vol_list(vol_list_t *vol_list); static int is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr); +static BSOCK *open_sd_bsock(UAContext *ua); +static void close_sd_bsock(UAContext *ua); +static char *get_volume_name_from_SD(UAContext *ua, int Slot); /* @@ -62,6 +66,91 @@ int relabel_cmd(UAContext *ua, char *cmd) return do_label(ua, cmd, 1); /* relabel tape */ } +#define MAX_SLOTS 5000 + +static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) +{ + int i; + char *msg; + + for (int i=0; i= 0) { + /* scan slot list in ua->argv[i] */ + char *p, *e, *h; + int beg, end; + + strip_trailing_junk(ua->argv[i]); + for (p=ua->argv[i]; p && *p; p=e) { + /* Check for list */ + e = strchr(p, ','); + if (e) { + *e++ = 0; + } + /* Check for range */ + h = strchr(p, '-'); /* range? */ + if (h == p) { + msg = _("Negative numbers not permitted\n"); + goto bail_out; + } + if (h) { + *h++ = 0; + if (!is_an_integer(h)) { + msg = _("Range end is not integer.\n"); + goto bail_out; + } + skip_spaces(&p); + if (!is_an_integer(p)) { + msg = _("Range start is not an integer.\n"); + goto bail_out; + } + beg = atoi(p); + end = atoi(h); + if (end < beg) { + msg = _("Range end not bigger than start.\n"); + goto bail_out; + } + } else { + skip_spaces(&p); + if (!is_an_integer(p)) { + msg = _("Input value is not an integer.\n"); + goto bail_out; + } + beg = end = atoi(p); + } + if (beg <= 0 || end <= 0) { + msg = _("Values must be be greater than zero.\n"); + goto bail_out; + } + if (end >= num_slots) { + msg = _("Slot too large.\n"); + goto bail_out; + } + for (i=beg; i<=end; i++) { + slot_list[i] = 1; /* Turn on specified range */ + } + } + } else { + /* Turn everything on */ + for (i=0; ijcr->store = store; - vol_list = get_slot_list_from_SD(ua); + scan = find_arg(ua, _("scan")) >= 0; + + slot_list = (char *)malloc(MAX_SLOTS); + if (!get_user_slot_list(ua, slot_list, MAX_SLOTS)) { + free(slot_list); + return 1; + } + vol_list = get_vol_list_from_SD(ua, scan); if (!vol_list) { bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n")); @@ -91,13 +189,28 @@ int update_slots(UAContext *ua) /* Walk through the list updating the media records */ for (vl=vol_list; vl; vl=vl->next) { - + /* Check if user wants us to look at this slot */ + if (!slot_list[vl->Slot]) { + continue; + } + /* If scanning, we read the label rather than the barcode */ + if (scan) { + if (vl->VolName) { + free(vl->VolName); + vl->VolName = NULL; + } + vl->VolName = get_volume_name_from_SD(ua, vl->Slot); + } + if (!vl->VolName) { + continue; + } memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); db_lock(ua->db); if (db_get_media_record(ua->jcr, ua->db, &mr)) { - if (mr.Slot != vl->Slot) { + if (mr.Slot != vl->Slot || !mr.InChanger) { mr.Slot = vl->Slot; + mr.InChanger = 1; if (!db_update_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, _("%s\n"), db_strerror(ua->db)); } else { @@ -120,23 +233,15 @@ int update_slots(UAContext *ua) bail_out: - /* Free list */ - for (vl=vol_list; vl; ) { - vol_list_t *ovl; - free(vl->VolName); - ovl = vl; - vl = vl->next; - free(ovl); - } - if (ua->jcr->store_bsock) { - bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); - bnet_close(ua->jcr->store_bsock); - ua->jcr->store_bsock = NULL; - } + free_vol_list(vol_list); + free(slot_list); + close_sd_bsock(ua); + return 1; } + /* * Common routine for both label and relabel */ @@ -144,7 +249,6 @@ static int do_label(UAContext *ua, char *cmd, int relabel) { STORE *store; BSOCK *sd; - sd = ua->jcr->store_bsock; char dev_name[MAX_NAME_LENGTH]; MEDIA_DBR mr, omr; POOL_DBR pr; @@ -241,6 +345,7 @@ checkName: } else { mr.Slot = ua->pint32_val; } + mr.InChanger = 1; /* assumed if we are labeling it */ } bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); @@ -253,17 +358,11 @@ checkName: } } - bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); - return 1; - } - sd = ua->jcr->store_bsock; ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists); if (ok) { + sd = ua->jcr->store_bsock; if (relabel) { if (!db_delete_media_record(ua->jcr, ua->db, &omr)) { bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"), @@ -297,9 +396,7 @@ checkName: if (print_reminder) { bsendmsg(ua, _("Do not forget to mount the drive!!!\n")); } - bnet_sig(sd, BNET_TERMINATE); - bnet_close(sd); - ua->jcr->store_bsock = NULL; + close_sd_bsock(ua); return 1; } @@ -315,8 +412,15 @@ static void label_from_barcodes(UAContext *ua) MEDIA_DBR mr, omr; vol_list_t *vl, *vol_list = NULL; bool media_record_exists; + char *slot_list; - vol_list = get_slot_list_from_SD(ua); + slot_list = (char *)malloc(MAX_SLOTS); + if (!get_user_slot_list(ua, slot_list, MAX_SLOTS)) { + free(slot_list); + return; + } + + vol_list = get_vol_list_from_SD(ua, false /*no scan*/); if (!vol_list) { bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n")); @@ -328,6 +432,9 @@ static void label_from_barcodes(UAContext *ua) "Slot Volume\n" "==============\n")); for (vl=vol_list; vl; vl=vl->next) { + if (!vl->VolName || !slot_list[vl->Slot]) { + continue; + } bsendmsg(ua, "%4d %s\n", vl->Slot, vl->VolName); } if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) || @@ -343,7 +450,9 @@ static void label_from_barcodes(UAContext *ua) /* Fire off the label requests */ for (vl=vol_list; vl; vl=vl->next) { - + if (!vl->VolName || !slot_list[vl->Slot]) { + continue; + } memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); media_record_exists = false; @@ -351,10 +460,17 @@ static void label_from_barcodes(UAContext *ua) if (mr.VolBytes != 0) { bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), vl->Slot, mr.VolumeName); + if (!mr.InChanger) { + mr.InChanger = 1; + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db)); + } + } continue; } media_record_exists = true; } + mr.InChanger = 1; /* * Deal with creating cleaning tape here. Normal tapes created in * send_label_request() below @@ -377,38 +493,17 @@ static void label_from_barcodes(UAContext *ua) continue; /* done, go handle next volume */ } bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); - if (ua->jcr->store_bsock) { - bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); - bnet_close(ua->jcr->store_bsock); - ua->jcr->store_bsock = NULL; - } - bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); - goto bail_out; - } mr.Slot = vl->Slot; - send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists); + if (!send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists)) { + goto bail_out; + } } bail_out: - /* Free list */ - for (vl=vol_list; vl; ) { - vol_list_t *ovl; - free(vl->VolName); - ovl = vl; - vl = vl->next; - free(ovl); - } - - if (ua->jcr->store_bsock) { - bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); - bnet_close(ua->jcr->store_bsock); - ua->jcr->store_bsock = NULL; - } + free_vol_list(vol_list); + close_sd_bsock(ua); return; } @@ -456,7 +551,9 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, char dev_name[MAX_NAME_LENGTH]; int ok = FALSE; - sd = ua->jcr->store_bsock; + if (!(sd=open_sd_bsock(ua))) { + return 0; + } bstrncpy(dev_name, ua->jcr->store->dev_name, sizeof(dev_name)); bash_spaces(dev_name); bash_spaces(mr->VolumeName); @@ -490,6 +587,7 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, if (ok) { if (media_record_exists) { /* we update it */ mr->VolBytes = 1; + mr->InChanger = 1; if (!db_update_media_record(ua->jcr, ua->db, mr)) { bsendmsg(ua, "%s", db_strerror(ua->db)); ok = FALSE; @@ -497,6 +595,7 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, } else { /* create the media record */ set_pool_dbr_defaults_in_media_dbr(mr, pr); mr->VolBytes = 1; /* flag indicating Volume labeled */ + mr->InChanger = 1; if (db_create_media_record(ua->jcr, ua->db, mr)) { bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), mr->VolumeName, mr->Slot); @@ -511,7 +610,69 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, return ok; } -static vol_list_t *get_slot_list_from_SD(UAContext *ua) +static BSOCK *open_sd_bsock(UAContext *ua) +{ + STORE *store = ua->jcr->store; + + if (!ua->jcr->store_bsock) { + bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), + store->hdr.name, store->address, store->SDport); + if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { + bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); + return NULL; + } + } + return ua->jcr->store_bsock; +} + +static void close_sd_bsock(UAContext *ua) +{ + if (ua->jcr->store_bsock) { + bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); + bnet_close(ua->jcr->store_bsock); + ua->jcr->store_bsock = NULL; + } +} + +static char *get_volume_name_from_SD(UAContext *ua, int Slot) +{ + STORE *store = ua->jcr->store; + BSOCK *sd; + char dev_name[MAX_NAME_LENGTH]; + char *VolName = NULL; + int rtn_slot; + + if (!(sd=open_sd_bsock(ua))) { + return NULL; + } + bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); + bash_spaces(dev_name); + /* Ask for autochanger list of volumes */ + bnet_fsend(sd, _("readlabel %s Slot=%d\n"), dev_name, Slot); + Dmsg1(100, "Sent: %s", sd->msg); + + /* Get Volume name in this Slot */ + while (bnet_recv(sd) >= 0) { + bsendmsg(ua, "%s", sd->msg); + if (strncmp(sd->msg, "3001 Volume=", 12) == 0) { + VolName = (char *)malloc(sd->msglen); + if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) { + break; + } + free(VolName); + VolName = NULL; + } + } + Dmsg1(200, "get_vol_name=%s\n", NPRT(VolName)); + return VolName; +} + +/* + * We get the slot list from the Storage daemon. + * If scan is set, we return all slots found, + * otherwise, we return only slots with valid barcodes (Volume names) + */ +static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) { STORE *store = ua->jcr->store; char dev_name[MAX_NAME_LENGTH]; @@ -520,13 +681,9 @@ static vol_list_t *get_slot_list_from_SD(UAContext *ua) vol_list_t *vol_list = NULL; - bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); + if (!(sd=open_sd_bsock(ua))) { return NULL; } - sd = ua->jcr->store_bsock; bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); bash_spaces(dev_name); @@ -547,25 +704,46 @@ static vol_list_t *get_slot_list_from_SD(UAContext *ua) continue; } - /* Validate Slot:Barcode */ + /* Validate Slot: if scanning, otherwise Slot:Barcode */ p = strchr(sd->msg, ':'); - if (p && strlen(p) > 1) { - *p++ = 0; - if (!is_an_integer(sd->msg)) { + if (scan && p) { + /* Scanning -- require only valid slot */ + Slot = atoi(sd->msg); + if (Slot <= 0) { + p--; + *p = ':'; + bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); continue; } } else { - continue; - } - Slot = atoi(sd->msg); - if (Slot <= 0 || !is_volume_name_legal(ua, p)) { - continue; + /* Not scanning */ + if (p && strlen(p) > 1) { + *p++ = 0; + if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) { + p--; + *p = ':'; + bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); + continue; + } + } else { + continue; + } + if (!is_volume_name_legal(ua, p)) { + p--; + *p = ':'; + bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg); + continue; + } } /* Add Slot and VolumeName to list */ vl = (vol_list_t *)malloc(sizeof(vol_list_t)); vl->Slot = Slot; - vl->VolName = bstrdup(p); + if (p) { + vl->VolName = bstrdup(p); + } else { + vl->VolName = NULL; + } if (!vol_list) { vl->next = vol_list; vol_list = vl; @@ -580,9 +758,26 @@ static vol_list_t *get_slot_list_from_SD(UAContext *ua) } } } + close_sd_bsock(ua); return vol_list; } +static void free_vol_list(vol_list_t *vol_list) +{ + vol_list_t *vl; + /* Free list */ + for (vl=vol_list; vl; ) { + vol_list_t *ovl; + if (vl->VolName) { + free(vl->VolName); + } + ovl = vl; + vl = vl->next; + free(ovl); + } +} + + /* * Check if this is a cleaning tape by comparing the Volume name * with the Cleaning Prefix. If they match, this is a cleaning diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index 0b1e1ef07e..98d2528c4a 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -738,15 +738,16 @@ STORE *get_storage_resource(UAContext *ua, int use_default) for (i=1; iargc; i++) { if (use_default && !ua->argv[i]) { + /* Ignore scan and barcode(s) keywords */ + if (strncasecmp("scan", ua->argk[i], 4) == 0 || + strncasecmp("barcode", ua->argk[i], 7) == 0) { + continue; + } /* Default argument is storage */ if (store_name) { bsendmsg(ua, _("Storage name given twice.\n")); return NULL; } - /* Ignore barcode(s) keywords */ - if (strncasecmp("barcode", ua->argk[i], 7) == 0) { - continue; - } store_name = ua->argk[i]; if (*store_name == '?') { *store_name = 0; diff --git a/bacula/src/filed/win32/Makefile.in b/bacula/src/filed/win32/Makefile.in index 7d8e42062e..c31a19cf0e 100755 --- a/bacula/src/filed/win32/Makefile.in +++ b/bacula/src/filed/win32/Makefile.in @@ -61,6 +61,7 @@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status clean: rm -f *.exe *.o *.res *.a 1 2 3 + rm -f bin/smtp.exe bin/console.exe rm -f bin/bacula-fd.exe bin/bsmtp.exe bin/testfind.exe distclean: clean diff --git a/bacula/src/filed/win32/bin/chown.exe b/bacula/src/filed/win32/bin/chown.exe index cc88a8bcdb..8403c8e4a8 100755 Binary files a/bacula/src/filed/win32/bin/chown.exe and b/bacula/src/filed/win32/bin/chown.exe differ diff --git a/bacula/src/filed/win32/bin/cygwin1.dll b/bacula/src/filed/win32/bin/cygwin1.dll index 5dff143282..78210c9523 100755 Binary files a/bacula/src/filed/win32/bin/cygwin1.dll and b/bacula/src/filed/win32/bin/cygwin1.dll differ diff --git a/bacula/src/filed/win32/bin/cygz.dll b/bacula/src/filed/win32/bin/cygz.dll index 6672c9e83a..08386eac7b 100755 Binary files a/bacula/src/filed/win32/bin/cygz.dll and b/bacula/src/filed/win32/bin/cygz.dll differ diff --git a/bacula/src/filed/win32/bin/mount.exe b/bacula/src/filed/win32/bin/mount.exe index bc46d6feab..beda551a88 100755 Binary files a/bacula/src/filed/win32/bin/mount.exe and b/bacula/src/filed/win32/bin/mount.exe differ diff --git a/bacula/src/filed/win32/bin/sh.exe b/bacula/src/filed/win32/bin/sh.exe index 5f736fd9dc..34ffc0e591 100755 Binary files a/bacula/src/filed/win32/bin/sh.exe and b/bacula/src/filed/win32/bin/sh.exe differ diff --git a/bacula/src/filed/win32/bin/umount.exe b/bacula/src/filed/win32/bin/umount.exe index eef24c7bce..cb6b25112d 100755 Binary files a/bacula/src/filed/win32/bin/umount.exe and b/bacula/src/filed/win32/bin/umount.exe differ diff --git a/bacula/src/lib/scan.c b/bacula/src/lib/scan.c index f435502b6c..9f38dc755b 100644 --- a/bacula/src/lib/scan.c +++ b/bacula/src/lib/scan.c @@ -65,7 +65,7 @@ int skip_spaces(char **msg) if (!p) { return 0; } - while (*p && *p == ' ') { + while (*p && B_ISSPACE(*p)) { p++; } *msg = p; @@ -85,7 +85,7 @@ int skip_nonspaces(char **msg) if (!p) { return 0; } - while (*p && *p != ' ') { + while (*p && !B_ISSPACE(*p)) { p++; } *msg = p; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index c89a91e213..8811dcbe5a 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -256,7 +256,8 @@ int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) /* - * + * Request to mount next Volume, which Volume not specified + * * Entered with device blocked. * Leaves with device blocked. * @@ -362,8 +363,8 @@ Please use the \"label\" command to create a new Volume for:\n\ wait_sec = min_wait; num_wait = 0; /* If no VolumeName, and cannot get one, try again */ - if (jcr->VolumeName[0] == 0 && - !dir_find_next_appendable_volume(jcr) && !job_canceled(jcr)) { + if (jcr->VolumeName[0] == 0 && !job_canceled(jcr) && + !dir_find_next_appendable_volume(jcr)) { Jmsg(jcr, M_MOUNT, 0, _( "Someone woke me up, but I cannot find any appendable\n\ volumes for Job=%s.\n"), jcr->Job); @@ -378,7 +379,8 @@ volumes for Job=%s.\n"), jcr->Job); } /* - * + * Request to mount specific Volume + * * Entered with device blocked and jcr->VolumeName is desired * volume. * Leaves with device blocked. @@ -540,7 +542,7 @@ static int wait_for_sysop(JCR *jcr, DEVICE *dev, int wait_sec) Dmsg1(100, "Additional wait %d sec.\n", add_wait); } - dev->dev_blocked = dev_blocked; + dev->dev_blocked = dev_blocked; /* restore entry state */ V(dev->mutex); return stat; } diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index cceb5cac51..ab506c3a58 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -64,6 +64,7 @@ extern int status_cmd(JCR *sjcr); /* Forward referenced functions */ static int label_cmd(JCR *jcr); static int relabel_cmd(JCR *jcr); +static int readlabel_cmd(JCR *jcr); static int release_cmd(JCR *jcr); static int setdebug_cmd(JCR *jcr); static int cancel_cmd(JCR *cjcr); @@ -71,6 +72,8 @@ static int mount_cmd(JCR *jcr); static int unmount_cmd(JCR *jcr); static int autochanger_cmd(JCR *sjcr); static int do_label(JCR *jcr, int relabel); +static bool find_device(JCR *jcr, char *dname); +static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot); static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, char *newname, char *poolname, int Slot, int relabel); @@ -94,6 +97,7 @@ static struct s_cmds cmds[] = { {"status", status_cmd}, {"autochanger", autochanger_cmd}, {"release", release_cmd}, + {"readlabel", readlabel_cmd}, {NULL, NULL} /* list terminator */ }; @@ -264,9 +268,8 @@ static int do_label(JCR *jcr, int relabel) { POOLMEM *dname, *newname, *oldname, *poolname, *mtype; BSOCK *dir = jcr->dir_bsock; - DEVRES *device; DEVICE *dev; - int found = 0, ok = 0; + bool ok = false; int slot; dname = get_memory(dir->msglen+1); @@ -277,36 +280,23 @@ static int do_label(JCR *jcr, int relabel) if (relabel) { if (sscanf(dir->msg, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d", dname, oldname, newname, poolname, mtype, &slot) == 6) { - ok = 1; + ok = true; } } else { *oldname = 0; if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d", dname, newname, poolname, mtype, &slot) == 5) { - ok = 1; + ok = true; } } if (ok) { - unbash_spaces(dname); unbash_spaces(newname); unbash_spaces(oldname); unbash_spaces(poolname); unbash_spaces(mtype); - device = NULL; - LockRes(); - while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) { - /* Find resource, and make sure we were able to open it */ - if (strcmp(device->hdr.name, dname) == 0 && device->dev) { - Dmsg1(20, "Found device %s\n", device->hdr.name); - found = 1; - break; - } - } - UnlockRes(); - if (found) { + if (find_device(jcr, dname)) { /******FIXME**** compare MediaTypes */ - jcr->device = device; - dev = device->dev; + dev = jcr->device->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!(dev->state & ST_OPENED)) { @@ -375,9 +365,6 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, /* Ensure that the device is open -- autoload_device() closes it */ for ( ; !(dev->state & ST_OPENED); ) { if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) { - if (dev->dev_errno == EAGAIN || dev->dev_errno == EBUSY) { - bmicrosleep(30, 0); - } bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"), dev_name(dev), strerror_dev(dev)); goto bail_out; @@ -410,7 +397,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, } pm_strcpy(&jcr->VolumeName, newname); bnet_fsend(dir, _("3000 OK label. Volume=%s Device=%s\n"), - newname, dev->dev_name); + newname, dev_name(dev)); break; case VOL_NO_MEDIA: bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev)); @@ -452,7 +439,7 @@ static int read_label(JCR *jcr, DEVICE *dev) break; default: bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device \"%s\" because:\n%s"), - dev->dev_name, jcr->errmsg); + dev_name(dev), jcr->errmsg); stat = 0; break; } @@ -461,45 +448,52 @@ static int read_label(JCR *jcr, DEVICE *dev) return stat; } +static bool find_device(JCR *jcr, char *dname) +{ + DEVRES *device = NULL; + bool found = false; + + unbash_spaces(dname); + LockRes(); + while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) { + /* Find resource, and make sure we were able to open it */ + if (strcmp(device->hdr.name, dname) == 0 && device->dev) { + Dmsg1(20, "Found device %s\n", device->hdr.name); + jcr->device = device; + found = true; + break; + } + } + UnlockRes(); + return found; +} + + /* * Mount command from Director */ static int mount_cmd(JCR *jcr) { - POOLMEM *dev_name; + POOLMEM *dname; BSOCK *dir = jcr->dir_bsock; - DEVRES *device; DEVICE *dev; - int found = 0; - - dev_name = get_memory(dir->msglen+1); - if (sscanf(dir->msg, "mount %s", dev_name) == 1) { - unbash_spaces(dev_name); - device = NULL; - LockRes(); - while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) { - /* Find resource, and make sure we were able to open it */ - if (strcmp(device->hdr.name, dev_name) == 0 && device->dev) { - Dmsg1(20, "Found device %s\n", device->hdr.name); - found = 1; - break; - } - } - UnlockRes(); - if (found) { + + dname = get_memory(dir->msglen+1); + if (sscanf(dir->msg, "mount %s", dname) == 1) { + if (find_device(jcr, dname)) { DEV_BLOCK *block; - jcr->device = device; - dev = device->dev; + dev = jcr->device->dev; P(dev->mutex); /* Use P to avoid indefinite block */ switch (dev->dev_blocked) { /* device blocked? */ case BST_WAITING_FOR_SYSOP: /* Someone is waiting, wake him */ Dmsg0(100, "Waiting for mount. Attempting to wake thread\n"); dev->dev_blocked = BST_MOUNT; - bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev->dev_name); + bnet_fsend(dir, "3001 OK mount. Device=%s\n", dev_name(dev)); pthread_cond_signal(&dev->wait_next_vol); break; + /* In both of these two cases, we (the user) unmounted the Volume */ case BST_UNMOUNTED_WAITING_FOR_SYSOP: case BST_UNMOUNTED: /* We freed the device, so reopen it and wake any waiting threads */ @@ -512,8 +506,9 @@ static int mount_cmd(JCR *jcr) read_dev_volume_label(jcr, dev, block); free_block(block); if (dev->dev_blocked == BST_UNMOUNTED) { + /* We blocked the device, so unblock it */ Dmsg0(100, "Unmounted. Unblocking device\n"); - read_label(jcr, dev); + read_label(jcr, dev); /* this should not be necessary */ unblock_device(dev); } else { Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n"); @@ -521,33 +516,33 @@ static int mount_cmd(JCR *jcr) } if (dev_state(dev, ST_LABEL)) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), - dev->dev_name, dev->VolHdr.VolName); + dev_name(dev), dev->VolHdr.VolName); } else { bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n" "If this is not a blank tape, try unmounting and remounting the Volume.\n"), - dev->dev_name); + dev_name(dev)); } pthread_cond_signal(&dev->wait_next_vol); break; case BST_DOING_ACQUIRE: bnet_fsend(dir, _("3001 Device %s is mounted; doing acquire.\n"), - dev->dev_name); + dev_name(dev)); break; case BST_WRITING_LABEL: - bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev->dev_name); + bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev_name(dev)); break; case BST_NOT_BLOCKED: if (dev_state(dev, ST_OPENED)) { if (dev_state(dev, ST_LABEL)) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), - dev->dev_name, dev->VolHdr.VolName); + dev_name(dev), dev->VolHdr.VolName); } else { bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n" "If this is not a blank tape, try unmounting and remounting the Volume.\n"), - dev->dev_name); + dev_name(dev)); } } else { if (!dev_is_tape(dev)) { @@ -562,11 +557,11 @@ static int mount_cmd(JCR *jcr) read_label(jcr, dev); if (dev_state(dev, ST_LABEL)) { bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"), - dev->dev_name, dev->VolHdr.VolName); + dev_name(dev), dev->VolHdr.VolName); } else { bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n" "If this is not a blank tape, try unmounting and remounting the Volume.\n"), - dev->dev_name); + dev_name(dev)); } } break; @@ -577,13 +572,13 @@ static int mount_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device %s not found\n"), dev_name); + bnet_fsend(dir, _("3999 Device %s not found\n"), dname); } } else { pm_strcpy(&jcr->errmsg, dir->msg); bnet_fsend(dir, _("3909 Error scanning mount command: %s\n"), jcr->errmsg); } - free_memory(dev_name); + free_memory(dname); bnet_sig(dir, BNET_EOD); return 1; } @@ -595,27 +590,12 @@ static int unmount_cmd(JCR *jcr) { POOLMEM *dname; BSOCK *dir = jcr->dir_bsock; - DEVRES *device; DEVICE *dev; - int found = 0; dname = get_memory(dir->msglen+1); if (sscanf(dir->msg, "unmount %s", dname) == 1) { - unbash_spaces(dname); - device = NULL; - LockRes(); - while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) { - /* Find resource, and make sure we were able to open it */ - if (strcmp(device->hdr.name, dname) == 0 && device->dev) { - Dmsg1(20, "Found device %s\n", device->hdr.name); - found = 1; - break; - } - } - UnlockRes(); - if (found) { - jcr->device = device; - dev = device->dev; + if (find_device(jcr, dname)) { + dev = jcr->device->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!(dev->state & ST_OPENED)) { Dmsg0(90, "Device already unmounted\n"); @@ -631,18 +611,15 @@ static int unmount_cmd(JCR *jcr) bnet_fsend(dir, _("3001 Device %s unmounted.\n"), dev_name(dev)); } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { - bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), dev_name(dev)); } else if (dev->dev_blocked == BST_WRITING_LABEL) { - bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), dev_name(dev)); } else if (dev_state(dev, ST_READ) || dev->num_writers) { if (dev_state(dev, ST_READ)) { Dmsg0(90, "Device in read mode\n"); - bnet_fsend(dir, _("3904 Device %s is busy with 1 reader.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3904 Device %s is busy with 1 reader.\n"), dev_name(dev)); } else { Dmsg1(90, "Device busy with %d writers\n", dev->num_writers); bnet_fsend(dir, _("3905 Device %s is busy with %d writer(s).\n"), @@ -689,27 +666,12 @@ static int release_cmd(JCR *jcr) { POOLMEM *dname; BSOCK *dir = jcr->dir_bsock; - DEVRES *device; DEVICE *dev; - int found = 0; dname = get_memory(dir->msglen+1); if (sscanf(dir->msg, "release %s", dname) == 1) { - unbash_spaces(dname); - device = NULL; - LockRes(); - while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) { - /* Find resource, and make sure we were able to open it */ - if (strcmp(device->hdr.name, dname) == 0 && device->dev) { - Dmsg1(20, "Found device %s\n", device->hdr.name); - found = 1; - break; - } - } - UnlockRes(); - if (found) { - jcr->device = device; - dev = device->dev; + if (find_device(jcr, dname)) { + dev = jcr->device->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!(dev->state & ST_OPENED)) { Dmsg0(90, "Device already released\n"); @@ -722,18 +684,15 @@ static int release_cmd(JCR *jcr) bnet_fsend(dir, _("3912 Device %s waiting for mount.\n"), dev_name(dev)); } else if (dev->dev_blocked == BST_DOING_ACQUIRE) { - bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"), dev_name(dev)); } else if (dev->dev_blocked == BST_WRITING_LABEL) { - bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), dev_name(dev)); } else if (dev_state(dev, ST_READ) || dev->num_writers) { if (dev_state(dev, ST_READ)) { Dmsg0(90, "Device in read mode\n"); - bnet_fsend(dir, _("3915 Device %s is busy with 1 reader.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3915 Device %s is busy with 1 reader.\n"), dev_name(dev)); } else { Dmsg1(90, "Device busy with %d writers\n", dev->num_writers); bnet_fsend(dir, _("3916 Device %s is busy with %d writer(s).\n"), @@ -766,33 +725,17 @@ static int release_cmd(JCR *jcr) */ static int autochanger_cmd(JCR *jcr) { - POOLMEM *devname; + POOLMEM *dname; BSOCK *dir = jcr->dir_bsock; - DEVRES *device; DEVICE *dev; - int found = 0; - - devname = get_memory(dir->msglen+1); - if (sscanf(dir->msg, "autochanger list %s ", devname) == 1) { - unbash_spaces(devname); - device = NULL; - LockRes(); - while ((device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device))) { - /* Find resource, and make sure we were able to open it */ - if (strcmp(device->hdr.name, devname) == 0 && device->dev) { - Dmsg1(20, "Found device %s\n", device->hdr.name); - found = 1; - break; - } - } - UnlockRes(); - if (found) { - jcr->device = device; - dev = device->dev; + + dname = get_memory(dir->msglen+1); + if (sscanf(dir->msg, "autochanger list %s ", dname) == 1) { + if (find_device(jcr, dname)) { + dev = jcr->device->dev; P(dev->mutex); /* Use P to avoid indefinite block */ if (!dev_is_tape(dev)) { - bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev_name(dev)); } else if (!(dev->state & ST_OPENED)) { if (open_dev(dev, NULL, READ_WRITE) < 0) { bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev)); @@ -808,8 +751,7 @@ static int autochanger_cmd(JCR *jcr) autochanger_list(jcr, dev, dir); } else if (dev_state(dev, ST_READ) || dev->num_writers) { if (dev_state(dev, ST_READ)) { - bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), - dev_name(dev)); + bnet_fsend(dir, _("3901 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"), dev_name(dev), dev->num_writers); @@ -819,14 +761,112 @@ static int autochanger_cmd(JCR *jcr) } V(dev->mutex); } else { - bnet_fsend(dir, _("3999 Device %s not found\n"), devname); + bnet_fsend(dir, _("3999 Device %s not found\n"), dname); } } else { /* error on scanf */ pm_strcpy(&jcr->errmsg, dir->msg); bnet_fsend(dir, _("3908 Error scanning autocharger list command: %s\n"), jcr->errmsg); } - free_memory(devname); + free_memory(dname); bnet_sig(dir, BNET_EOD); return 1; } + +/* + * Read and return the Volume label + */ +static int readlabel_cmd(JCR *jcr) +{ + POOLMEM *dname; + BSOCK *dir = jcr->dir_bsock; + DEVICE *dev; + int Slot; + + dname = get_memory(dir->msglen+1); + if (sscanf(dir->msg, "readlabel %s Slot=%d", dname, &Slot) == 2) { + if (find_device(jcr, dname)) { + dev = jcr->device->dev; + + P(dev->mutex); /* Use P to avoid indefinite block */ + if (!(dev->state & ST_OPENED)) { + if (open_dev(dev, NULL, READ_WRITE) < 0) { + bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev)); + } else { + read_volume_label(jcr, dev, Slot); + force_close_dev(dev); + } + /* Under certain "safe" conditions, we can steal the lock */ + } else if (dev->dev_blocked && + (dev->dev_blocked == BST_UNMOUNTED || + dev->dev_blocked == BST_WAITING_FOR_SYSOP || + dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) { + read_volume_label(jcr, dev, Slot); + } else if (dev_state(dev, ST_READ) || dev->num_writers) { + if (dev_state(dev, ST_READ)) { + bnet_fsend(dir, _("3911 Device %s is busy with 1 reader.\n"), + dev_name(dev)); + } else { + bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"), + dev_name(dev), dev->num_writers); + } + } else { /* device not being used */ + read_volume_label(jcr, dev, Slot); + } + V(dev->mutex); + } else { + bnet_fsend(dir, _("3999 Device %s not found\n"), dname); + } + } else { + pm_strcpy(&jcr->errmsg, dir->msg); + bnet_fsend(dir, _("3909 Error scanning readlabel command: %s\n"), jcr->errmsg); + } + free_memory(dname); + bnet_sig(dir, BNET_EOD); + return 1; +} + +/* + * Read the tape label + * + * Enter with the mutex set + */ +static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot) +{ + BSOCK *dir = jcr->dir_bsock; + DEV_BLOCK *block; + bsteal_lock_t hold; + + steal_device_lock(dev, &hold, BST_WRITING_LABEL); + + jcr->VolumeName[0] = 0; + jcr->VolCatInfo.Slot = Slot; + autoload_device(jcr, dev, 0, dir); /* autoload if possible */ + block = new_block(dev); + + /* Ensure that the device is open -- autoload_device() closes it */ + for ( ; !(dev->state & ST_OPENED); ) { + if (open_dev(dev, jcr->VolumeName, READ_WRITE) < 0) { + bnet_fsend(dir, _("3910 Unable to open device %s. ERR=%s\n"), + dev_name(dev), strerror_dev(dev)); + goto bail_out; + } + } + + dev->state &= ~ST_LABEL; /* force read of label */ + switch (read_dev_volume_label(jcr, dev, block)) { + case VOL_OK: + bnet_fsend(dir, _("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolName, Slot); + Dmsg1(100, "Volume: %s\n", dev->VolHdr.VolName); + break; + default: + bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device \"%s\" because:\n%s"), + dev_name(dev), jcr->errmsg); + break; + } + +bail_out: + free_block(block); + give_back_device_lock(dev, &hold); + return; +} diff --git a/bacula/src/tools/Makefile.in b/bacula/src/tools/Makefile.in index c820dfa35f..afee465707 100644 --- a/bacula/src/tools/Makefile.in +++ b/bacula/src/tools/Makefile.in @@ -36,7 +36,7 @@ EXTRAOBJS = @OBJLIST@ .c.o: $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $< #------------------------------------------------------------------------- -all: Makefile bsmtp dbcheck testfind testls hammer +all: Makefile bsmtp dbcheck testfind testls @echo "==== Make of tools is good ====" @echo " " diff --git a/bacula/src/version.h b/bacula/src/version.h index 66d98188d1..2a8b2205c5 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.33" #define VSTRING "1" -#define BDATE "14 Nov 2003" -#define LSMDATE "14Nov03" +#define BDATE "18 Nov 2003" +#define LSMDATE "18Nov03" /* Debug flags */ #undef DEBUG