From: Kern Sibbald Date: Wed, 19 Mar 2008 16:32:21 +0000 (+0000) Subject: Move X-Git-Tag: Release-2.2.9-b7~64 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5395b9d89ad0d0d5a621b4ee2a47888883e5265f;p=bacula%2Fbacula Move git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.2@6633 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/patches/2.0.x/2.2.7-fpformat.patch b/bacula/patches/2.0.x/2.2.7-fpformat.patch deleted file mode 100644 index c022627abd..0000000000 --- a/bacula/patches/2.0.x/2.2.7-fpformat.patch +++ /dev/null @@ -1,120 +0,0 @@ - - This patch fixes a float point editing bug introduced in 2.2.7 (I think) - causing the rate fields to be formated incorrectly (actually trunctated). - This fixes bug #1036. - - Apply it to version 2.2.7 with: - - cd - patch -p0 <2.2.7-fpformat.patch - ./configure - make - ... - make install - - -Index: src/lib/bsnprintf.c -=================================================================== ---- src/lib/bsnprintf.c (revision 6183) -+++ src/lib/bsnprintf.c (working copy) -@@ -16,7 +16,7 @@ - /* - Bacula® - The Network Backup Solution - -- Copyright (C) 2005-2007 Free Software Foundation Europe e.V. -+ Copyright (C) 2005-2008 Free Software Foundation Europe e.V. - - The main author of Bacula is Kern Sibbald, with contributions from - many others, a complete list can be found in the file AUTHORS. -@@ -566,11 +566,11 @@ - return result; - } - --static long round(LDOUBLE value) -+static int64_t round(LDOUBLE value) - { -- long intpart; -+ int64_t intpart; - -- intpart = (long)value; -+ intpart = (int64_t)value; - value = value - intpart; - if (value >= 0.5) - intpart++; -@@ -584,8 +584,8 @@ - int signvalue = 0; - LDOUBLE ufvalue; - #ifndef HAVE_FCVT -- char iconvert[25]; -- char fconvert[25]; -+ char iconvert[311]; -+ char fconvert[311]; - #else - char iconvert[311]; - char fconvert[311]; -@@ -602,6 +602,7 @@ - int caps = 0; - int64_t intpart; - int64_t fracpart; -+ const char *cvt_str; - - /* - * AIX manpage says the default is 0, but Solaris says the default -@@ -625,7 +626,7 @@ - #endif - - #ifndef HAVE_FCVT -- intpart = (long)ufvalue; -+ intpart = (int64_t)ufvalue; - - /* - * Sorry, we only support 9 digits past the decimal because of our -@@ -645,28 +646,30 @@ - } - - #ifdef DEBUG_SNPRINTF -- printf("fmtfp: %g %d.%d min=%d max=%d\n", -+ printf("fmtfp: %g %lld.%lld min=%d max=%d\n", - (double)fvalue, intpart, fracpart, min, max); - #endif - - /* Convert integer part */ -+ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef"; - do { -- iconvert[iplace++] = -- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10]; -+ iconvert[iplace++] = cvt_str[(int)(intpart % 10)]; - intpart = (intpart / 10); -- } while (intpart && (iplace < (int)sizeof(iplace))); -- if (iplace == (int)sizeof(iplace)) { -+ } while (intpart && (iplace < (int)sizeof(iconvert))); -+ -+ if (iplace == (int)sizeof(fconvert)) { - iplace--; - } - iconvert[iplace] = 0; - - /* Convert fractional part */ -+ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef"; - do { -- fconvert[fplace++] = -- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10]; -+ fconvert[fplace++] = cvt_str[fracpart % 10]; - fracpart = (fracpart / 10); -- } while (fracpart && (fplace < (int)sizeof(fplace))); -- if (fplace == (int)sizeof(fplace)) { -+ } while (fracpart && (fplace < (int)sizeof(fconvert))); -+ -+ if (fplace == (int)sizeof(fconvert)) { - fplace--; - } - fconvert[fplace] = 0; -@@ -825,7 +828,7 @@ - NULL - }; - double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, -- 0.9996, 1.996, 4.136, 6442452944.1234, 0 -+ 0.9996, 1.996, 4.136, 6442452944.1234, 0, 23365.5 - }; - #endif - char *int_fmt[] = { diff --git a/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch b/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch deleted file mode 100644 index c636dd68ba..0000000000 --- a/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch +++ /dev/null @@ -1,56 +0,0 @@ - - This patch permits to use migration options with JobDefs. - This patch fixes bug #1028. - - Apply the patch to 2.2.7 (and possibly any 2.2.x version with): - - cd - patch -p0 <2.2.7-jobdefs-migtype.patch - ./configure - make - ... - make install - -Index: src/dird/dird.c -=================================================================== ---- src/dird/dird.c (revision 6183) -+++ src/dird/dird.c (working copy) -@@ -58,6 +58,7 @@ - void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass); - void store_level(LEX *lc, RES_ITEM *item, int index, int pass); - void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); -+void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); - void init_device_resources(); - - static char *runjob = NULL; -@@ -698,6 +699,7 @@ - job_items[i].handler == store_jobtype || - job_items[i].handler == store_level || - job_items[i].handler == store_pint || -+ job_items[i].handler == store_migtype || - job_items[i].handler == store_replace) { - def_ivalue = (int *)((char *)(job->jobdefs) + offset); - Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n", -Index: src/dird/dird_conf.c -=================================================================== ---- src/dird/dird_conf.c (revision 6183) -+++ src/dird/dird_conf.c (working copy) -@@ -74,8 +74,8 @@ - void store_level(LEX *lc, RES_ITEM *item, int index, int pass); - void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); - void store_acl(LEX *lc, RES_ITEM *item, int index, int pass); -+void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); - static void store_device(LEX *lc, RES_ITEM *item, int index, int pass); --static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); - static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass); - static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass); - static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass); -@@ -1548,7 +1548,7 @@ - * Store JobType (backup, verify, restore) - * - */ --static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) -+void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) - { - int token, i; - diff --git a/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch b/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch deleted file mode 100644 index fafb85d1e1..0000000000 --- a/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch +++ /dev/null @@ -1,30 +0,0 @@ - - This patch fixes bug #1034 about Temporary MySQL table 'batch' - disappears if MySQL connection times out. - - Apply the patch to 2.2.7 (and possibly any 2.2.x version with): - - cd - patch -p0 <2.2.7-mysql-batch-timeout.patch - ./configure - make - ... - make install - - - -Index: src/cats/mysql.c -=================================================================== ---- src/cats/mysql.c (révision 6192) -+++ src/cats/mysql.c (copie de travail) -@@ -205,6 +205,10 @@ - Dmsg3(100, "opendb ref=%d connected=%d db=%p\n", mdb->ref_count, - mdb->connected, mdb->db); - -+ /* Set connection timeout to 8 days specialy for batch mode */ -+ sql_query(mdb, "SET wait_timeout=691200"); -+ sql_query(mdb, "SET interactive_timeout=691200"); -+ - V(mutex); - return 1; - } diff --git a/bacula/patches/2.0.x/2.2.7-old-postgresql.patch b/bacula/patches/2.0.x/2.2.7-old-postgresql.patch deleted file mode 100644 index d13b11865d..0000000000 --- a/bacula/patches/2.0.x/2.2.7-old-postgresql.patch +++ /dev/null @@ -1,26 +0,0 @@ - - If you have an old version of PostgreSQL, for example, - version 7.3 or older, it may not properly build with the current - Bacula release due to incompatible changes in the PostgreSQL - header files between version. Only in the case that build fails, - you might try applying this patch with: - - cd - patch -p1 <2.2.7-old-postgresql.patch - ./configure - make - ... - make install - - -diff -uNr bacula-2.2.7/src/cats/postgresql.c bacula-2.2.7-fixed/src/cats/postgresql.c ---- bacula-2.2.7/src/cats/postgresql.c 2007-12-08 04:54:55.000000000 -0500 -+++ bacula-2.2.7-fixed/src/cats/postgresql.c 2007-12-29 08:34:10.000000000 -0500 -@@ -47,7 +47,6 @@ - #ifdef HAVE_POSTGRESQL - - #include "postgres_ext.h" /* needed for NAMEDATALEN */ --#include "pg_config_manual.h" /* get NAMEDATALEN on version 8.3 or later */ - - /* ----------------------------------------------------------------------- - * diff --git a/bacula/patches/2.0.x/2.2.7-reserve.patch b/bacula/patches/2.0.x/2.2.7-reserve.patch deleted file mode 100644 index 42daad1280..0000000000 --- a/bacula/patches/2.0.x/2.2.7-reserve.patch +++ /dev/null @@ -1,1467 +0,0 @@ - - This patch has a number of cleanups and improvements to the SD - reservations system. It should fix a number of problems with - dual drive autochangers as well ensure that volume use durations - and max volume jobs are better respected. - - Apply it to version 2.2.7 (possibly some earlier versions) with: - - cd - patch -p1 <2.2.7-reserve.patch - ./configure - make - ... - make install - - -diff -ur k1/src/lib/message.c k3/src/lib/message.c ---- k1/src/lib/message.c 2007-10-19 13:47:58.000000000 +0200 -+++ k3/src/lib/message.c 2007-12-22 19:13:00.000000000 +0100 -@@ -54,6 +54,7 @@ - int verbose = 0; /* increase User messages */ - /* Keep debug level set to zero by default */ - int debug_level = 0; /* debug level */ -+bool dbg_timestamp = false; /* print timestamp in debug output */ - time_t daemon_start_time = 0; /* Daemon start time */ - const char *version = VERSION " (" BDATE ")"; - char my_name[30]; /* daemon name is stored here */ -diff -ur k1/src/lib/message.h k3/src/lib/message.h ---- k1/src/lib/message.h 2007-10-03 13:36:47.000000000 +0200 -+++ k3/src/lib/message.h 2007-12-22 19:13:06.000000000 +0100 -@@ -154,6 +154,7 @@ - extern DLL_IMP_EXP sql_escape p_sql_escape; - - extern DLL_IMP_EXP int debug_level; -+extern DLL_IMP_EXP bool dbg_timestamp; /* print timestamp in debug output */ - extern DLL_IMP_EXP int verbose; - extern DLL_IMP_EXP char my_name[]; - extern DLL_IMP_EXP const char * working_directory; -diff -ur k1/src/stored/acquire.c k3/src/stored/acquire.c ---- k1/src/stored/acquire.c 2007-09-14 11:49:06.000000000 +0200 -+++ k3/src/stored/acquire.c 2007-12-22 19:12:23.000000000 +0100 -@@ -30,7 +30,7 @@ - * - * Kern Sibbald, August MMII - * -- * Version $Id: acquire.c 5552 2007-09-14 09:49:06Z kerns $ -+ * Version $Id: acquire.c 6081 2007-12-21 14:11:40Z kerns $ - */ - - #include "bacula.h" /* pull in global headers */ -@@ -38,6 +38,7 @@ - - /* Forward referenced functions */ - static void attach_dcr_to_dev(DCR *dcr); -+static bool is_suitable_volume_mounted(DCR *dcr); - - - /********************************************************************* -@@ -316,9 +317,9 @@ - */ - DCR *acquire_device_for_append(DCR *dcr) - { -- bool release = false; -- bool recycle = false; - bool do_mount = false; -+ bool release = false; -+ bool have_vol; - DEVICE *dev = dcr->dev; - JCR *jcr = dcr->jcr; - -@@ -337,6 +338,11 @@ - goto get_out; - } - -+ /* -+ * have_vol defines whether or not mount_next_write_volume should -+ * ask the Director again about what Volume to use. -+ */ -+ have_vol = is_suitable_volume_mounted(dcr); - if (dev->can_append()) { - Dmsg0(190, "device already in append.\n"); - /* -@@ -351,25 +357,11 @@ - * dcr->VolumeName is what we pass into the routines, or - * get back from the subroutines. - */ -- bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName)); -- if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) && -+ if (!have_vol && - !(dir_find_next_appendable_volume(dcr) && - strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */ -- Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName, -- dcr->VolumeName); -- /* Release volume reserved by dir_find_next_appendable_volume() */ -- if (dcr->VolumeName[0]) { -- volume_unused(dcr); -- } -- if (dev->num_writers != 0) { -- Jmsg3(jcr, M_FATAL, 0, _("Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), -- dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName); -- Dmsg3(200, "Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n", -- dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName); -- goto get_out; -- } - /* Wrong tape mounted, release it, then fall through to get correct one */ -- Dmsg0(190, "Wrong tape mounted, release and try mount.\n"); -+ Dmsg0(50, "Wrong tape mounted, release and try mount.\n"); - release = true; - do_mount = true; - } else { -@@ -378,14 +370,17 @@ - * we do not need to do mount_next_write_volume(), unless - * we need to recycle the tape. - */ -- recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; -- Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle); -- if (recycle && dev->num_writers != 0) { -+ do_mount = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; -+ Dmsg2(190, "jid=%u Correct tape mounted. recycle=%d\n", -+ (uint32_t)jcr->JobId, do_mount); -+#ifdef xxx -+ if (do_mount && dev->num_writers != 0) { - Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\"" - " on device %s because it is in use by another job.\n"), - dev->VolHdr.VolumeName, dev->print_name()); - goto get_out; - } -+#endif - if (dev->num_writers == 0) { - memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); - } -@@ -415,21 +410,23 @@ - } - } else { - /* Not already in append mode, so mount the device */ -- Dmsg0(190, "Not in append mode, try mount.\n"); -+ Dmsg2(190, "jid=%u Not in append mode, try mount have_vol=%d\n", -+ (uint32_t)jcr->JobId, have_vol); -+ - ASSERT(dev->num_writers == 0); - do_mount = true; - } - -- if (do_mount || recycle) { -- Dmsg0(190, "Do mount_next_write_vol\n"); -- bool mounted = mount_next_write_volume(dcr, release); -+ if (do_mount || !have_vol) { -+ Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId); -+ bool mounted = mount_next_write_volume(dcr, have_vol, release); - if (!mounted) { - if (!job_canceled(jcr)) { - /* Reduce "noise" -- don't print if job canceled */ - Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), - dev->print_name()); -- Dmsg1(200, "Could not ready device %s for append.\n", -- dev->print_name()); -+ Dmsg2(200, "jid=%u Could not ready device %s for append.\n", -+ (uint32_t)jcr->JobId, dev->print_name()); - } - goto get_out; - } -@@ -441,11 +438,12 @@ - jcr->NumWriteVolumes = 1; - } - dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ -- dir_update_volume_info(dcr, false); /* send Volume info to Director */ -+ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ - dev->dlock(); - if (dcr->reserved_device) { - dev->reserved_device--; -- Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); -+ Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, -+ dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; - } - dev->dunblock(DEV_LOCKED); -@@ -458,7 +456,8 @@ - dev->dlock(); - if (dcr->reserved_device) { - dev->reserved_device--; -- Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); -+ Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, -+ dev->reserved_device, dev->print_name()); - dcr->reserved_device = false; - } - dev->dunblock(DEV_LOCKED); -@@ -466,6 +465,18 @@ - } - - -+static bool is_suitable_volume_mounted(DCR *dcr) -+{ -+ DEVICE *dev = dcr->dev; -+ -+ /* Volume mounted? */ -+ if (dev->VolHdr.VolumeName[0] == 0) { -+ return false; /* no */ -+ } -+ bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName)); -+ return dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE); -+} -+ - /* - * This job is done, so release the device. From a Unix standpoint, - * the device remains open. -@@ -496,7 +507,7 @@ - if (dev->can_read()) { - dev->clear_read(); /* clear read bit */ - Dmsg0(100, "dir_update_vol_info. Release0\n"); -- dir_update_volume_info(dcr, false); /* send Volume info to Director */ -+ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ - - } else if (dev->num_writers > 0) { - /* -@@ -522,7 +533,7 @@ - dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ - /* Note! do volume update before close, which zaps VolCatInfo */ - Dmsg0(100, "dir_update_vol_info. Release0\n"); -- dir_update_volume_info(dcr, false); /* send Volume info to Director */ -+ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ - } - } - -@@ -621,7 +632,12 @@ - if (dcr->attached_to_dev) { - detach_dcr_from_dev(dcr); - } -- dcr->max_job_spool_size = dev->device->max_job_spool_size; -+ /* Use job spoolsize prior to device spoolsize */ -+ if (jcr->spool_size) { -+ dcr->max_job_spool_size = jcr->spool_size; -+ } else { -+ dcr->max_job_spool_size = dev->device->max_job_spool_size; -+ } - dcr->device = dev->device; - dcr->dev = dev; - attach_dcr_to_dev(dcr); -diff -ur k1/src/stored/askdir.c k3/src/stored/askdir.c ---- k1/src/stored/askdir.c 2007-09-09 12:03:23.000000000 +0200 -+++ k3/src/stored/askdir.c 2007-12-22 19:11:50.000000000 +0100 -@@ -31,7 +31,7 @@ - * - * Kern Sibbald, December 2000 - * -- * Version $Id: askdir.c 5503 2007-09-09 10:03:23Z kerns $ -+ * Version $Id: askdir.c 5852 2007-11-04 19:57:42Z kerns $ - */ - - #include "bacula.h" /* pull in global headers */ -@@ -42,7 +42,7 @@ - static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n"; - static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s" - " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u" -- " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s" -+ " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%s VolStatus=%s" - " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s" - " VolFirstWritten=%s VolParts=%u\n"; - static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" -@@ -98,7 +98,7 @@ - } else { - pm_strcpy(ChangerName, "*"); - } -- ok =bnet_fsend(dir, Device_update, -+ ok = dir->fsend(Device_update, - jcr->Job, - dev_name.c_str(), - dev->can_append()!=0, -@@ -125,7 +125,7 @@ - pm_strcpy(MediaType, device->media_type); - bash_spaces(MediaType); - /* This is mostly to indicate that we are here */ -- ok = bnet_fsend(dir, Device_update, -+ ok = dir->fsend(Device_update, - jcr->Job, - dev_name.c_str(), /* Changer name */ - 0, 0, 0, /* append, read, num_writers */ -@@ -148,7 +148,7 @@ - */ - bool dir_send_job_status(JCR *jcr) - { -- return bnet_fsend(jcr->dir_bsock, Job_status, jcr->Job, jcr->JobStatus); -+ return jcr->dir_bsock->fsend(Job_status, jcr->Job, jcr->JobStatus); - } - - /* -@@ -179,7 +179,7 @@ - return false; - } - memset(&vol, 0, sizeof(vol)); -- Dmsg1(100, "msg); -+ Dmsg1(100, "msg); - n = sscanf(dir->msg, OK_media, vol.VolCatName, - &vol.VolCatJobs, &vol.VolCatFiles, - &vol.VolCatBlocks, &vol.VolCatBytes, -@@ -191,7 +191,8 @@ - &vol.EndFile, &vol.EndBlock, &vol.VolCatParts, - &vol.LabelType, &vol.VolMediaId); - if (n != 22) { -- Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", n, dir->msglen, dir->msg); -+ Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", -+ n, dir->msglen, dir->msg); - Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg); - return false; - } -@@ -226,7 +227,7 @@ - bash_spaces(dcr->VolCatInfo.VolCatName); - dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName, - writing==GET_VOL_INFO_FOR_WRITE?1:0); -- Dmsg1(100, ">dird: %s\n", dir->msg); -+ Dmsg1(100, ">dird %s", dir->msg); - unbash_spaces(dcr->VolCatInfo.VolCatName); - bool ok = do_get_volume_info(dcr); - V(vol_info_mutex); -@@ -253,7 +254,9 @@ - BSOCK *dir = jcr->dir_bsock; - bool found = false; - -- Dmsg0(200, "dir_find_next_appendable_volume\n"); -+ Dmsg2(200, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", -+ dcr->reserved_device, dcr->VolumeName); -+ - /* - * Try the twenty oldest or most available volumes. Note, - * the most available could already be mounted on another -@@ -268,7 +271,7 @@ - dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type); - unbash_spaces(dcr->media_type); - unbash_spaces(dcr->pool_name); -- Dmsg1(100, ">dird: %s", dir->msg); -+ Dmsg1(100, ">dird %s", dir->msg); - bool ok = do_get_volume_info(dcr); - if (ok) { - if (!is_volume_in_use(dcr)) { -@@ -311,14 +314,13 @@ - * back to the director. The information comes from the - * dev record. - */ --bool dir_update_volume_info(DCR *dcr, bool label) -+bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten) - { - JCR *jcr = dcr->jcr; - BSOCK *dir = jcr->dir_bsock; - DEVICE *dev = dcr->dev; -- time_t LastWritten = time(NULL); - VOLUME_CAT_INFO *vol = &dev->VolCatInfo; -- char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50]; -+ char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50]; - int InChanger; - bool ok = false; - POOL_MEM VolumeName; -@@ -341,21 +343,25 @@ - if (label) { - bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); - } -+// if (update_LastWritten) { -+ vol->VolLastWritten = time(NULL); -+// } - pm_strcpy(VolumeName, vol->VolCatName); - bash_spaces(VolumeName); - InChanger = vol->InChanger; -- bnet_fsend(dir, Update_media, jcr->Job, -+ dir->fsend(Update_media, jcr->Job, - VolumeName.c_str(), vol->VolCatJobs, vol->VolCatFiles, - vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1), - vol->VolCatMounts, vol->VolCatErrors, - vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), -- LastWritten, vol->VolCatStatus, vol->Slot, label, -+ edit_uint64(vol->VolLastWritten, ed6), -+ vol->VolCatStatus, vol->Slot, label, - InChanger, /* bool in structure */ - edit_int64(vol->VolReadTime, ed3), - edit_int64(vol->VolWriteTime, ed4), - edit_uint64(vol->VolFirstWritten, ed5), - vol->VolCatParts); -- Dmsg1(100, ">dird: %s", dir->msg); -+ Dmsg1(100, ">dird %s", dir->msg); - - /* Do not lock device here because it may be locked from label */ - if (!do_get_volume_info(dcr)) { -@@ -364,7 +370,7 @@ - vol->VolCatName, jcr->errmsg); - goto bail_out; - } -- Dmsg1(420, "get_volume_info(): %s", dir->msg); -+ Dmsg1(420, "get_volume_info() %s", dir->msg); - /* Update dev Volume info in case something changed (e.g. expired) */ - dev->VolCatInfo = dcr->VolCatInfo; - ok = true; -@@ -393,20 +399,20 @@ - } - - dcr->WroteVol = false; -- bnet_fsend(dir, Create_job_media, jcr->Job, -+ dir->fsend(Create_job_media, jcr->Job, - dcr->VolFirstIndex, dcr->VolLastIndex, - dcr->StartFile, dcr->EndFile, - dcr->StartBlock, dcr->EndBlock, - dcr->Copy, dcr->Stripe, - edit_uint64(dcr->VolMediaId, ed1)); -- Dmsg1(100, ">dird: %s", dir->msg); -+ Dmsg1(100, ">dird %s", dir->msg); - if (bnet_recv(dir) <= 0) { - Dmsg0(190, "create_jobmedia error bnet_recv\n"); - Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"), -- bnet_strerror(dir)); -+ dir->bstrerror()); - return false; - } -- Dmsg1(100, "msg); -+ Dmsg1(100, "msg); - if (strcmp(dir->msg, OK_create) != 0) { - Dmsg1(130, "Bad response from Dir: %s\n", dir->msg); - Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg); -@@ -429,9 +435,10 @@ - return true; - #endif - -- dir->msglen = sprintf(dir->msg, FileAttributes, jcr->Job); -- dir->msg = check_pool_memory_size(dir->msg, dir->msglen + -- sizeof(DEV_RECORD) + rec->data_len); -+ dir->msg = check_pool_memory_size(dir->msg, sizeof(FileAttributes) + -+ MAX_NAME_LENGTH + sizeof(DEV_RECORD) + rec->data_len + 1); -+ dir->msglen = bsnprintf(dir->msg, sizeof(FileAttributes) + -+ MAX_NAME_LENGTH + 1, FileAttributes, jcr->Job); - ser_begin(dir->msg + dir->msglen, 0); - ser_uint32(rec->VolSessionId); - ser_uint32(rec->VolSessionTime); -@@ -440,8 +447,8 @@ - ser_uint32(rec->data_len); - ser_bytes(rec->data, rec->data_len); - dir->msglen = ser_length(dir->msg); -- Dmsg1(1800, ">dird: %s\n", dir->msg); /* Attributes */ -- return bnet_send(dir); -+ Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */ -+ return dir->send(); - } - - -diff -ur k1/src/stored/bcopy.c k3/src/stored/bcopy.c ---- k1/src/stored/bcopy.c 2007-12-03 20:27:38.000000000 +0100 -+++ k3/src/stored/bcopy.c 2007-12-22 19:10:29.000000000 +0100 -@@ -32,7 +32,7 @@ - * Kern E. Sibbald, October 2002 - * - * -- * Version $Id: bcopy.c 6017 2007-12-03 19:27:38Z kerns $ -+ * Version $Id: bcopy.c 6016 2007-12-03 19:27:21Z kerns $ - */ - - #include "bacula.h" -@@ -42,6 +42,7 @@ - int generate_daemon_event(JCR *jcr, const char *event) { return 1; } - - /* Forward referenced functions */ -+static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); - static bool record_cb(DCR *dcr, DEV_RECORD *rec); - - -@@ -52,10 +53,11 @@ - static JCR *out_jcr; /* output jcr */ - static BSR *bsr = NULL; - static const char *wd = "/tmp"; --static int list_records = 0; -+static bool list_records = false; - static uint32_t records = 0; - static uint32_t jobs = 0; - static DEV_BLOCK *out_block; -+static SESSION_LABEL sessrec; - - #define CONFIG_FILE "bacula-sd.conf" - char *configfile = NULL; -@@ -73,7 +75,7 @@ - "Usage: bcopy [-d debug_level] \n" - " -b bootstrap specify a bootstrap file\n" - " -c specify configuration file\n" --" -d set debug level to nn\n" -+" -d set debug level to \n" - " -i specify input Volume names (separated by |)\n" - " -o specify output Volume names (separated by |)\n" - " -p proceed inspite of errors\n" -@@ -113,9 +115,14 @@ - break; - - case 'd': /* debug level */ -- debug_level = atoi(optarg); -- if (debug_level <= 0) -- debug_level = 1; -+ if (*optarg == 't') { -+ dbg_timestamp = true; -+ } else { -+ debug_level = atoi(optarg); -+ if (debug_level <= 0) { -+ debug_level = 1; -+ } -+ } - break; - - case 'i': /* input Volume name */ -@@ -201,6 +208,7 @@ - out_block = out_jcr->dcr->block; - - ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume); -+ - if (ok || out_dev->can_write()) { - if (!write_block_to_device(out_jcr->dcr)) { - Pmsg0(000, _("Write of last block failed.\n")); -@@ -233,6 +241,7 @@ - * - */ - if (rec->FileIndex < 0) { -+ get_session_record(in_dcr->dev, rec, &sessrec); - - if (verbose > 1) { - dump_label_record(in_dcr->dev, rec, 1); -@@ -294,10 +303,46 @@ - return true; - } - -+static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) -+{ -+ const char *rtype; -+ memset(sessrec, 0, sizeof(sessrec)); -+ switch (rec->FileIndex) { -+ case PRE_LABEL: -+ rtype = _("Fresh Volume Label"); -+ break; -+ case VOL_LABEL: -+ rtype = _("Volume Label"); -+ unser_volume_label(dev, rec); -+ break; -+ case SOS_LABEL: -+ rtype = _("Begin Job Session"); -+ unser_session_label(sessrec, rec); -+ break; -+ case EOS_LABEL: -+ rtype = _("End Job Session"); -+ unser_session_label(sessrec, rec); -+ break; -+ case 0: -+ case EOM_LABEL: -+ rtype = _("End of Medium"); -+ break; -+ default: -+ rtype = _("Unknown"); -+ break; -+ } -+ Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", -+ rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); -+ if (verbose) { -+ Pmsg5(-1, _("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n"), -+ rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); -+ } -+} -+ - - /* Dummies to replace askdir.c */ - bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} --bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } -+bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } - bool dir_create_jobmedia_record(DCR *dcr) { return 1; } - bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } - bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} -diff -ur k1/src/stored/bextract.c k3/src/stored/bextract.c ---- k1/src/stored/bextract.c 2007-10-03 13:36:47.000000000 +0200 -+++ k3/src/stored/bextract.c 2007-12-22 19:10:20.000000000 +0100 -@@ -4,7 +4,7 @@ - * - * Kern E. Sibbald, MM - * -- * Version $Id: bextract.c 5713 2007-10-03 11:36:47Z kerns $ -+ * Version $Id: bextract.c 5852 2007-11-04 19:57:42Z kerns $ - * - */ - /* -@@ -79,7 +79,7 @@ - "Usage: bextract \n" - " -b specify a bootstrap file\n" - " -c specify a configuration file\n" --" -d set debug level to nn\n" -+" -d set debug level to \n" - " -e exclude list\n" - " -i include list\n" - " -p proceed inspite of I/O errors\n" -@@ -126,9 +126,14 @@ - break; - - case 'd': /* debug level */ -- debug_level = atoi(optarg); -- if (debug_level <= 0) -- debug_level = 1; -+ if (*optarg == 't') { -+ dbg_timestamp = true; -+ } else { -+ debug_level = atoi(optarg); -+ if (debug_level <= 0) { -+ debug_level = 1; -+ } -+ } - break; - - case 'e': /* exclude list */ -@@ -476,7 +481,7 @@ - - /* Dummies to replace askdir.c */ - bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} --bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } -+bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } - bool dir_create_jobmedia_record(DCR *dcr) { return 1; } - bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } - bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} -diff -ur k1/src/stored/block.c k3/src/stored/block.c ---- k1/src/stored/block.c 2007-10-03 13:36:47.000000000 +0200 -+++ k3/src/stored/block.c 2007-12-22 19:12:33.000000000 +0100 -@@ -32,7 +32,7 @@ - * Kern Sibbald, March MMI - * added BB02 format October MMII - * -- * Version $Id: block.c 5713 2007-10-03 11:36:47Z kerns $ -+ * Version $Id: block.c 5852 2007-11-04 19:57:42Z kerns $ - * - */ - -@@ -746,7 +746,7 @@ - dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; - } - -- if (!dir_update_volume_info(dcr, false)) { -+ if (!dir_update_volume_info(dcr, false, true)) { - ok = false; - } - Dmsg1(100, "dir_update_volume_info terminate writing -- %s\n", ok?"OK":"ERROR"); -@@ -798,7 +798,7 @@ - return false; - } - dev->VolCatInfo.VolCatFiles = dev->file; -- if (!dir_update_volume_info(dcr, false)) { -+ if (!dir_update_volume_info(dcr, false, false)) { - Dmsg0(190, "Error from update_vol_info.\n"); - terminate_writing_volume(dcr); - dev->dev_errno = EIO; -@@ -856,7 +856,7 @@ - - dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; - -- if (!dir_update_volume_info(dcr, false)) { -+ if (!dir_update_volume_info(dcr, false, false)) { - Dmsg0(190, "Error from update_vol_info.\n"); - dev->dev_errno = EIO; - return false; -diff -ur k1/src/stored/bls.c k3/src/stored/bls.c ---- k1/src/stored/bls.c 2007-10-03 13:36:47.000000000 +0200 -+++ k3/src/stored/bls.c 2007-12-22 19:10:57.000000000 +0100 -@@ -31,7 +31,7 @@ - * - * Kern Sibbald, MM - * -- * Version $Id: bls.c 5713 2007-10-03 11:36:47Z kerns $ -+ * Version $Id: bls.c 5852 2007-11-04 19:57:42Z kerns $ - */ - - #include "bacula.h" -@@ -79,7 +79,7 @@ - "Usage: bls [options] \n" - " -b specify a bootstrap file\n" - " -c specify a config file\n" --" -d specify debug level\n" -+" -d set debug level to \n" - " -e exclude list\n" - " -i include list\n" - " -j list jobs\n" -@@ -130,9 +130,14 @@ - break; - - case 'd': /* debug level */ -- debug_level = atoi(optarg); -- if (debug_level <= 0) -- debug_level = 1; -+ if (*optarg == 't') { -+ dbg_timestamp = true; -+ } else { -+ debug_level = atoi(optarg); -+ if (debug_level <= 0) { -+ debug_level = 1; -+ } -+ } - break; - - case 'e': /* exclude list */ -@@ -440,7 +445,7 @@ - - /* Dummies to replace askdir.c */ - bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} --bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } -+bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } - bool dir_create_jobmedia_record(DCR *dcr) { return 1; } - bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } - bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} -diff -ur k1/src/stored/bscan.c k3/src/stored/bscan.c ---- k1/src/stored/bscan.c 2007-10-03 13:36:47.000000000 +0200 -+++ k3/src/stored/bscan.c 2007-12-22 19:11:05.000000000 +0100 -@@ -34,7 +34,7 @@ - * Kern E. Sibbald, December 2001 - * - * -- * Version $Id: bscan.c 5713 2007-10-03 11:36:47Z kerns $ -+ * Version $Id: bscan.c 5852 2007-11-04 19:57:42Z kerns $ - */ - - #include "bacula.h" -@@ -116,7 +116,7 @@ - "Usage: bscan [ options ] \n" - " -b bootstrap specify a bootstrap file\n" - " -c specify configuration file\n" --" -d set debug level to nn\n" -+" -d set debug level to \n" - " -m update media info in database\n" - " -n specify the database name (default bacula)\n" - " -u specify database user name (default bacula)\n" -@@ -166,9 +166,14 @@ - break; - - case 'd': /* debug level */ -- debug_level = atoi(optarg); -- if (debug_level <= 0) -- debug_level = 1; -+ if (*optarg == 't') { -+ dbg_timestamp = true; -+ } else { -+ debug_level = atoi(optarg); -+ if (debug_level <= 0) { -+ debug_level = 1; -+ } -+ } - break; - - case 'h': -@@ -1271,7 +1276,7 @@ - - /* Dummies to replace askdir.c */ - bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} --bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } -+bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } - bool dir_create_jobmedia_record(DCR *dcr) { return 1; } - bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } - bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} -diff -ur k1/src/stored/btape.c k3/src/stored/btape.c ---- k1/src/stored/btape.c 2007-06-07 16:46:43.000000000 +0200 -+++ k3/src/stored/btape.c 2007-12-22 19:11:14.000000000 +0100 -@@ -37,7 +37,7 @@ - * Note, this program reads stored.conf, and will only - * talk to devices that are configured. - * -- * Version $Id: btape.c 4992 2007-06-07 14:46:43Z kerns $ -+ * Version $Id: btape.c 5852 2007-11-04 19:57:42Z kerns $ - * - */ - -@@ -220,9 +220,13 @@ - break; - - case 'd': /* set debug level */ -- debug_level = atoi(optarg); -- if (debug_level <= 0) { -- debug_level = 1; -+ if (*optarg == 't') { -+ dbg_timestamp = true; -+ } else { -+ debug_level = atoi(optarg); -+ if (debug_level <= 0) { -+ debug_level = 1; -+ } - } - break; - -@@ -2598,7 +2602,7 @@ - "Usage: btape \n" - " -b specify bootstrap file\n" - " -c set configuration file to file\n" --" -d set debug level to nn\n" -+" -d set debug level to \n" - " -p proceed inspite of I/O errors\n" - " -s turn off signals\n" - " -v be verbose\n" -@@ -2644,7 +2648,7 @@ - bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} - bool dir_send_job_status(JCR *jcr) {return 1;} - --bool dir_update_volume_info(DCR *dcr, bool relabel) -+bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) - { - return 1; - } -diff -ur k1/src/stored/dev.c k3/src/stored/dev.c ---- k1/src/stored/dev.c 2007-12-02 19:03:17.000000000 +0100 -+++ k3/src/stored/dev.c 2007-12-22 19:11:57.000000000 +0100 -@@ -47,7 +47,7 @@ - * daemon. More complicated coding (double buffering, writer - * thread, ...) is left for a later version. - * -- * Version $Id: dev.c 6011 2007-12-02 18:03:17Z kerns $ -+ * Version $Id: dev.c 5999 2007-11-29 21:36:36Z ricozz $ - */ - - /* -@@ -89,7 +89,7 @@ - /* Forward referenced functions */ - void set_os_device_parameters(DCR *dcr); - static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat); --static char *mode_to_str(int mode); -+static const char *mode_to_str(int mode); - - /* - * Allocate and initialize the DEVICE structure -@@ -490,7 +490,7 @@ - Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), - be.bstrerror()); - Dmsg1(100, "open failed: %s", errmsg); -- Emsg0(M_FATAL, 0, errmsg); -+ Jmsg1(NULL, M_WARNING, 0, "%s", errmsg); - } else { - dev_errno = 0; - file = 0; -@@ -2468,7 +2468,7 @@ - mt_stat->mt_fileno >= 0; - } - --static char *modes[] = { -+static const char *modes[] = { - "CREATE_READ_WRITE", - "OPEN_READ_WRITE", - "OPEN_READ_ONLY", -@@ -2476,7 +2476,7 @@ - }; - - --static char *mode_to_str(int mode) -+static const char *mode_to_str(int mode) - { - static char buf[100]; - if (mode < 1 || mode > 4) { -diff -ur k1/src/stored/dev.h k3/src/stored/dev.h ---- k1/src/stored/dev.h 2007-09-09 12:03:23.000000000 +0200 -+++ k3/src/stored/dev.h 2007-12-22 19:12:14.000000000 +0100 -@@ -31,7 +31,7 @@ - * - * Kern Sibbald, MM - * -- * Version $Id: dev.h 5503 2007-09-09 10:03:23Z kerns $ -+ * Version $Id: dev.h 5852 2007-11-04 19:57:42Z kerns $ - * - */ - -@@ -158,6 +158,7 @@ - btime_t VolWriteTime; /* time spent writing this Volume */ - int64_t VolMediaId; /* MediaId */ - utime_t VolFirstWritten; /* Time of first write */ -+ utime_t VolLastWritten; /* Time of last write */ - bool InChanger; /* Set if vol in current magazine */ - char VolCatStatus[20]; /* Volume status */ - char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ -@@ -473,8 +474,9 @@ - class VOLRES { - public: - dlink link; -- char *vol_name; -- DEVICE *dev; -+ char *vol_name; /* Volume name */ -+ DEVICE *dev; /* Pointer to device to which we are attached */ -+ bool released; /* set when the Volume can be released */ - }; - - -diff -ur k1/src/stored/device.c k3/src/stored/device.c ---- k1/src/stored/device.c 2007-06-29 14:12:26.000000000 +0200 -+++ k3/src/stored/device.c 2007-12-22 19:11:23.000000000 +0100 -@@ -53,7 +53,7 @@ - * - * Kern Sibbald, MM, MMI - * -- * Version $Id: device.c 5114 2007-06-29 12:12:26Z kerns $ -+ * Version $Id: device.c 5852 2007-11-04 19:57:42Z kerns $ - */ - - #include "bacula.h" /* pull in global headers */ -@@ -122,7 +122,8 @@ - edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), - bstrftime(dt, sizeof(dt), time(NULL))); - -- if (!mount_next_write_volume(dcr, 1)) { -+ /* Called with have_vol=false, release=true */ -+ if (!mount_next_write_volume(dcr, false, true)) { - free_block(label_blk); - dcr->block = block; - dev->dlock(); -@@ -131,7 +132,7 @@ - dev->dlock(); /* lock again */ - - dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ -- dir_update_volume_info(dcr, false); /* send Volume info to Director */ -+ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ - - Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"), - dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL))); -diff -ur k1/src/stored/dvd.c k3/src/stored/dvd.c ---- k1/src/stored/dvd.c 2007-06-07 16:46:43.000000000 +0200 -+++ k3/src/stored/dvd.c 2007-12-22 19:26:23.000000000 +0100 -@@ -1,16 +1,7 @@ - /* -- * -- * dvd.c -- Routines specific to DVD devices (and -- * possibly other removable hard media). -- * -- * Nicolas Boichat, MMV -- * -- * Version $Id: dvd.c 4992 2007-06-07 14:46:43Z kerns $ -- */ --/* - Bacula® - The Network Backup Solution - -- Copyright (C) 2005-2006 Free Software Foundation Europe e.V. -+ Copyright (C) 2005-2007 Free Software Foundation Europe e.V. - - The main author of Bacula is Kern Sibbald, with contributions from - many others, a complete list can be found in the file AUTHORS. -@@ -34,6 +25,15 @@ - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. - */ -+/* -+ * -+ * dvd.c -- Routines specific to DVD devices (and -+ * possibly other removable hard media). -+ * -+ * Nicolas Boichat, MMV -+ * -+ * Version $Id: dvd.c 5852 2007-11-04 19:57:42Z kerns $ -+ */ - - #include "bacula.h" - #include "stored.h" -@@ -686,7 +686,7 @@ - dcr->VolCatInfo.VolCatBytes = 0; - - /* Update catalog */ -- if (!dir_update_volume_info(dcr, false)) { -+ if (!dir_update_volume_info(dcr, false, true)) { - return false; - } - -diff -ur k1/src/stored/job.c k3/src/stored/job.c ---- k1/src/stored/job.c 2007-09-29 00:01:16.000000000 +0200 -+++ k3/src/stored/job.c 2007-12-22 19:11:41.000000000 +0100 -@@ -30,7 +30,7 @@ - * - * Kern Sibbald, MM - * -- * Version $Id: job.c 5686 2007-09-28 22:01:16Z kerns $ -+ * Version $Id: job.c 5697 2007-09-30 17:40:08Z ricozz $ - * - */ - -@@ -49,9 +49,13 @@ - /* Requests from the Director daemon */ - static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " - "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " -+ "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d SpoolSize=%s\n"; -+static char oldjobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " -+ "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " - "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d\n"; - - -+ - /* Responses sent to Director daemon */ - static char OKjob[] = "3000 OK Job SDid=%u SDtime=%u Authorization=%s\n"; - static char BAD_job[] = "3915 Bad Job command. stat=%d CMD: %s\n"; -@@ -73,6 +77,7 @@ - { - int JobId; - char auth_key[100]; -+ char spool_size[30]; - char seed[100]; - BSOCK *dir = jcr->dir_bsock; - POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; -@@ -85,17 +90,26 @@ - * Get JobId and permissions from Director - */ - Dmsg1(100, "msg); -+ bstrncpy(spool_size, "0", sizeof(spool_size)); - stat = sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(), - client_name.c_str(), - &JobType, &level, fileset_name.c_str(), &no_attributes, -- &spool_attributes, fileset_md5.c_str(), &spool_data, -+ &spool_attributes, fileset_md5.c_str(), &spool_data, -+ &write_part_after_job, &PreferMountedVols, spool_size); -+ if (stat != 14) { -+ /* Try old version */ -+ stat = sscanf(dir->msg, oldjobcmd, &JobId, job.c_str(), job_name.c_str(), -+ client_name.c_str(), -+ &JobType, &level, fileset_name.c_str(), &no_attributes, -+ &spool_attributes, fileset_md5.c_str(), &spool_data, - &write_part_after_job, &PreferMountedVols); -- if (stat != 13) { -- pm_strcpy(jcr->errmsg, dir->msg); -- dir->fsend(BAD_job, stat, jcr->errmsg); -- Dmsg1(100, ">dird: %s", dir->msg); -- set_jcr_job_status(jcr, JS_ErrorTerminated); -- return false; -+ if (stat != 13) { -+ pm_strcpy(jcr->errmsg, dir->msg); -+ dir->fsend(BAD_job, stat, jcr->errmsg); -+ Dmsg1(100, ">dird: %s", dir->msg); -+ set_jcr_job_status(jcr, JS_ErrorTerminated); -+ return false; -+ } - } - /* - * Since this job could be rescheduled, we -@@ -125,6 +139,7 @@ - jcr->no_attributes = no_attributes; - jcr->spool_attributes = spool_attributes; - jcr->spool_data = spool_data; -+ jcr->spool_size = str_to_int64(spool_size); - jcr->write_part_after_job = write_part_after_job; - jcr->fileset_md5 = get_pool_memory(PM_NAME); - pm_strcpy(jcr->fileset_md5, fileset_md5); -diff -ur k1/src/stored/label.c k3/src/stored/label.c ---- k1/src/stored/label.c 2007-10-03 13:36:47.000000000 +0200 -+++ k3/src/stored/label.c 2007-12-22 19:10:49.000000000 +0100 -@@ -32,7 +32,7 @@ - * Kern Sibbald, MM - * - * -- * Version $Id: label.c 5713 2007-10-03 11:36:47Z kerns $ -+ * Version $Id: label.c 5852 2007-11-04 19:57:42Z kerns $ - */ - - #include "bacula.h" /* pull in global headers */ -@@ -505,7 +505,7 @@ - } - Dmsg0(150, "dir_update_vol_info. Set Append\n"); - bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus)); -- if (!dir_update_volume_info(dcr, true)) { /* indicate doing relabel */ -+ if (!dir_update_volume_info(dcr, true, true)) { /* indicate doing relabel */ - return false; - } - if (recycle) { -@@ -716,7 +716,7 @@ - } - break; - default: -- Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label); -+ Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label = %d\n"), label); - break; - } - create_session_label(dcr, rec, label); -diff -ur k1/src/stored/mount.c k3/src/stored/mount.c ---- k1/src/stored/mount.c 2007-09-14 11:49:06.000000000 +0200 -+++ k3/src/stored/mount.c 2007-12-22 19:11:30.000000000 +0100 -@@ -32,7 +32,7 @@ - * - * Kern Sibbald, August MMII - * -- * Version $Id: mount.c 5552 2007-09-14 09:49:06Z kerns $ -+ * Version $Id: mount.c 5852 2007-11-04 19:57:42Z kerns $ - */ - - #include "bacula.h" /* pull in global headers */ -@@ -60,7 +60,7 @@ - * impossible to get the requested Volume. - * - */ --bool mount_next_write_volume(DCR *dcr, bool release) -+bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release) - { - int retry = 0; - bool ask = false, recycle, autochanger; -@@ -108,12 +108,16 @@ - * in dcr->VolCatInfo - */ - Dmsg0(200, "Before dir_find_next_appendable_volume.\n"); -- while (!dir_find_next_appendable_volume(dcr)) { -- Dmsg0(200, "not dir_find_next\n"); -- if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { -- return false; -+ if (!have_vol) { -+ while (!dir_find_next_appendable_volume(dcr)) { -+ Dmsg0(200, "not dir_find_next\n"); -+ if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { -+ return false; -+ } -+ Dmsg0(200, "Again dir_find_next_append...\n"); - } -- Dmsg0(200, "Again dir_find_next_append...\n"); -+ } else { -+ have_vol = false; /* set false for next pass if any */ - } - if (job_canceled(jcr)) { - return false; -@@ -144,7 +148,7 @@ - * If we autochanged to correct Volume or (we have not just - * released the Volume AND we can automount) we go ahead - * and read the label. If there is no tape in the drive, -- * we will err, recurse and ask the operator the next time. -+ * we will fail, recurse and ask the operator the next time. - */ - if (!release && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) { - Dmsg0(150, "(1)Ask=0\n"); -@@ -432,7 +436,7 @@ - } - dev->VolCatInfo.VolCatMounts++; /* Update mounts */ - Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts); -- if (!dir_update_volume_info(dcr, false)) { -+ if (!dir_update_volume_info(dcr, false, false)) { - return false; - } - -@@ -519,7 +523,7 @@ - Dmsg0(150, "dir_update_vol_info. Set Append\n"); - /* Copy Director's info into the device info */ - dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ -- if (!dir_update_volume_info(dcr, true)) { /* indicate tape labeled */ -+ if (!dir_update_volume_info(dcr, true, true)) { /* indicate tape labeled */ - return try_error; - } - Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"), -@@ -552,7 +556,7 @@ - dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ - bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus)); - Dmsg0(150, "dir_update_vol_info. Set Error.\n"); -- dir_update_volume_info(dcr, false); -+ dir_update_volume_info(dcr, false, false); - } - - /* -@@ -570,7 +574,7 @@ - dcr->VolCatInfo.InChanger = false; - dev->VolCatInfo.InChanger = false; - Dmsg0(400, "update vol info in mount\n"); -- dir_update_volume_info(dcr, true); /* set new status */ -+ dir_update_volume_info(dcr, true, false); /* set new status */ - } - - /* -@@ -588,6 +592,7 @@ - /* - * First erase all memory of the current volume - */ -+ free_volume(dev); - dev->block_num = dev->file = 0; - dev->EndBlock = dev->EndFile = 0; - memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo)); -diff -ur k1/src/stored/protos.h k3/src/stored/protos.h ---- k1/src/stored/protos.h 2007-06-28 13:57:03.000000000 +0200 -+++ k3/src/stored/protos.h 2007-12-22 19:12:43.000000000 +0100 -@@ -28,7 +28,7 @@ - /* - * Protypes for stored -- Kern Sibbald MM - * -- * Version $Id: protos.h 5112 2007-06-28 11:57:03Z kerns $ -+ * Version $Id: protos.h 5852 2007-11-04 19:57:42Z kerns $ - */ - - /* From stored.c */ -@@ -49,7 +49,7 @@ - }; - bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); - bool dir_find_next_appendable_volume(DCR *dcr); --bool dir_update_volume_info(DCR *dcr, bool label); -+bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten); - bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); - bool dir_ask_sysop_to_mount_volume(DCR *dcr); - bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); -@@ -182,7 +182,7 @@ - bool is_this_bsr_done(BSR *bsr, DEV_RECORD *rec); - - /* From mount.c */ --bool mount_next_write_volume(DCR *dcr, bool release); -+bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release); - bool mount_next_read_volume(DCR *dcr); - void mark_volume_in_error(DCR *dcr); - -diff -ur k1/src/stored/record.c k3/src/stored/record.c ---- k1/src/stored/record.c 2007-06-07 16:46:43.000000000 +0200 -+++ k3/src/stored/record.c 2007-12-22 19:12:06.000000000 +0100 -@@ -1,14 +1,4 @@ - /* -- * -- * record.c -- tape record handling functions -- * -- * Kern Sibbald, April MMI -- * added BB02 format October MMII -- * -- * Version $Id: record.c 4992 2007-06-07 14:46:43Z kerns $ -- * -- */ --/* - Bacula® - The Network Backup Solution - - Copyright (C) 2001-2006 Free Software Foundation Europe e.V. -@@ -35,6 +25,16 @@ - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. - */ -+/* -+ * -+ * record.c -- tape record handling functions -+ * -+ * Kern Sibbald, April MMI -+ * added BB02 format October MMII -+ * -+ * Version $Id: record.c 6014 2007-12-03 18:14:27Z kerns $ -+ * -+ */ - - - #include "bacula.h" -@@ -254,7 +254,7 @@ - ASSERT(block->buf_len >= block->binbuf); - - Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n" --"rem=%d remainder=%d\n", -+ "rem=%d remainder=%d\n", - FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, - stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, - remlen, rec->remainder); -@@ -365,7 +365,7 @@ - if (!sm_check_rtn(__FILE__, __LINE__, False)) { - /* We damaged a buffer */ - Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n" --"rem=%d remainder=%d\n", -+ "rem=%d remainder=%d\n", - FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, - stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, - remlen, rec->remainder); -diff -ur k1/src/stored/reserve.c k3/src/stored/reserve.c ---- k1/src/stored/reserve.c 2007-08-04 18:46:32.000000000 +0200 -+++ k3/src/stored/reserve.c 2007-12-22 19:09:56.000000000 +0100 -@@ -212,11 +212,11 @@ - if (dev) { - len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name()); - sendit(msg.c_str(), len, arg); -- len = Mmsg(msg, " Reader=%d writers=%d reserved=%d\n", dev->can_read()?1:0, -- dev->num_writers, dev->reserved_device); -+ len = Mmsg(msg, " Reader=%d writers=%d reserved=%d released=%d\n", -+ dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released); - sendit(msg.c_str(), len, arg); - } else { -- len = Mmsg(msg, "%s no dev\n", vol->vol_name); -+ len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released); - sendit(msg.c_str(), len, arg); - } - } -@@ -292,11 +292,11 @@ - * already exist and are correctly programmed and will need no changes -- use - * counts are always very tricky. - * -- * The old code had a concept of "reserving" a Volume, but it needs to be changed -+ * The old code had a concept of "reserving" a Volume, but was changed - * to reserving and using a drive. A volume is must be attached to (owned by) a - * drive and can move from drive to drive or be unused given certain specific - * conditions of the drive. The key is that the drive must "own" the Volume. -- * The old code has the job (dcr) owning the volume (more or less). The job is -+ * The old code had the job (dcr) owning the volume (more or less). The job was - * to change the insertion and removal of the volumes from the list to be based - * on the drive rather than the job. - * -@@ -329,13 +329,14 @@ - * because it was probably inserted by another job. - */ - if (strcmp(vol->vol_name, VolumeName) == 0) { -+ Dmsg1(dbglvl, "OK, vol=%s on device.\n", VolumeName); - goto get_out; /* Volume already on this device */ - } else { -- Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", -+ Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", - (int)dcr->jcr->JobId, vol->vol_name, vol->vol_name); -- debug_list_volumes("reserve_vol free"); - vol_list->remove(vol); - free_vol_item(vol); -+ debug_list_volumes("reserve_vol free"); - } - } - -@@ -378,12 +379,16 @@ - Dmsg4(dbglvl, "jid=%u Volume busy could not swap vol=%s from dev=%s to %s\n", - jid(), VolumeName, vol->dev->print_name(), dev->print_name()); - vol = NULL; /* device busy */ -+ goto get_out; - } - } - } - dev->vol = vol; - - get_out: -+ if (vol) { -+ vol->released = false; -+ } - debug_list_volumes("end new volume"); - unlock_volumes(); - return vol; -@@ -462,6 +467,7 @@ - * explicitly read in this drive. This allows the SD to remember - * where the tapes are or last were. - */ -+ dev->vol->released = true; - if (dev->is_tape() || dev->is_autochanger()) { - return true; - } else { -@@ -837,6 +843,7 @@ - dlist *temp_vol_list, *save_vol_list; - VOLRES *vol = NULL; - lock_volumes(); -+ Dmsg0(dbglvl, "lock volumes\n"); - - /* - * Create a temporary copy of the volume list. We do this, -@@ -1122,6 +1129,26 @@ - */ - if (dcr->volume_in_use && !rctx.PreferMountedVols) { - rctx.PreferMountedVols = true; -+ if (dcr->VolumeName[0]) { -+ volume_unused(dcr); -+ } -+ goto bail_out; -+ } -+ /* -+ * Note. Under some circumstances, the Director can hand us -+ * a Volume name that is no the same as the one on the current -+ * drive, and in that case, the call above to find the next -+ * volume will fail because in attempting to reserve the Volume -+ * the code will realize that we already have a tape mounted, -+ * and it will fail. This *should* only happen if there are -+ * writers, thus the following test. In that case, we simply -+ * bail out, and continue waiting, rather than plunging on -+ * and hoping that the operator can resolve the problem. -+ */ -+ if (dcr->dev->num_writers != 0) { -+ if (dcr->VolumeName[0]) { -+ volume_unused(dcr); -+ } - goto bail_out; - } - } -@@ -1270,6 +1297,51 @@ - return ok; - } - -+static int is_pool_ok(DCR *dcr) -+{ -+ DEVICE *dev = dcr->dev; -+ JCR *jcr = dcr->jcr; -+ -+ /* Now check if we want the same Pool and pool type */ -+ if (strcmp(dev->pool_name, dcr->pool_name) == 0 && -+ strcmp(dev->pool_type, dcr->pool_type) == 0) { -+ /* OK, compatible device */ -+ Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name()); -+ return 1; -+ } else { -+ /* Drive Pool not suitable for us */ -+ Mmsg(jcr->errmsg, _( -+"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), -+ (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name, -+ dev->reserved_device, dev->print_name()); -+ queue_reserve_message(jcr); -+ Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n", -+ dev->pool_name, dcr->pool_name); -+ } -+ return 0; -+} -+ -+static bool is_max_jobs_ok(DCR *dcr) -+{ -+ DEVICE *dev = dcr->dev; -+ JCR *jcr = dcr->jcr; -+ -+ Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n", -+ dcr->VolCatInfo.VolCatMaxJobs, -+ dcr->VolCatInfo.VolCatJobs, dev->reserved_device, -+ dcr->VolumeName); -+ if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <= -+ (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) { -+ /* Max Job Vols depassed or already reserved */ -+ Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"), -+ (uint32_t)jcr->JobId, dev->print_name()); -+ queue_reserve_message(jcr); -+ Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg); -+ return false; /* wait */ -+ } -+ return true; -+} -+ - /* - * Returns: 1 if drive can be reserved - * 0 if we should wait -@@ -1285,6 +1357,11 @@ - rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, - rctx.autochanger_only, rctx.any_drive); - -+ /* Check for max jobs on this Volume */ -+ if (!is_max_jobs_ok(dcr)) { -+ return 0; -+ } -+ - /* setting any_drive overrides PreferMountedVols flag */ - if (!rctx.any_drive) { - /* -@@ -1374,32 +1451,10 @@ - if (dev->num_writers == 0) { - /* Now check if there are any reservations on the drive */ - if (dev->reserved_device) { -- /* Now check if we want the same Pool and pool type */ -- if (strcmp(dev->pool_name, dcr->pool_name) == 0 && -- strcmp(dev->pool_type, dcr->pool_type) == 0) { -- /* OK, compatible device */ -- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, reserved, pool matches\n", -- jcr->JobId, dev->print_name()); -- return 1; -- } else { -- /* Drive Pool not suitable for us */ -- Mmsg(jcr->errmsg, _( --"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), -- jcr->JobId, dcr->pool_name, dev->pool_name, -- dev->reserved_device, dev->print_name()); -- queue_reserve_message(jcr); -- Dmsg3(dbglvl, "jid=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n", -- (int)jcr->JobId, dev->pool_name, dcr->pool_name); -- return 0; /* wait */ -- } -+ return is_pool_ok(dcr); - } else if (dev->can_append()) { -- /* Device in append mode, check if changing pool */ -- if (strcmp(dev->pool_name, dcr->pool_name) == 0 && -- strcmp(dev->pool_type, dcr->pool_type) == 0) { -- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, can_append, pool matches.\n", -- jcr->JobId, dev->print_name()); -- /* OK, compatible device */ -- return 1; -+ if (is_pool_ok(dcr)) { -+ return 1; - } else { - /* Changing pool, unload old tape if any in drive */ - Dmsg1(dbglvl, "jid=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n", -@@ -1419,22 +1474,7 @@ - * available if pool is the same). - */ - if (dev->can_append() || dev->num_writers > 0) { -- /* Yes, now check if we want the same Pool and pool type */ -- if (strcmp(dev->pool_name, dcr->pool_name) == 0 && -- strcmp(dev->pool_type, dcr->pool_type) == 0) { -- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers>=0, can_append, pool matches.\n", -- jcr->JobId, dev->print_name()); -- /* OK, compatible device */ -- return 1; -- } else { -- /* Drive Pool not suitable for us */ -- Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"), -- jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name()); -- queue_reserve_message(jcr); -- Dmsg3(dbglvl, "jid=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n", -- (int)jcr->JobId, dev->pool_name, dcr->pool_name); -- return 0; /* wait */ -- } -+ return is_pool_ok(dcr); - } else { - Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId); - Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"), diff --git a/bacula/patches/2.2.x/2.2.7-fpformat.patch b/bacula/patches/2.2.x/2.2.7-fpformat.patch new file mode 100644 index 0000000000..c022627abd --- /dev/null +++ b/bacula/patches/2.2.x/2.2.7-fpformat.patch @@ -0,0 +1,120 @@ + + This patch fixes a float point editing bug introduced in 2.2.7 (I think) + causing the rate fields to be formated incorrectly (actually trunctated). + This fixes bug #1036. + + Apply it to version 2.2.7 with: + + cd + patch -p0 <2.2.7-fpformat.patch + ./configure + make + ... + make install + + +Index: src/lib/bsnprintf.c +=================================================================== +--- src/lib/bsnprintf.c (revision 6183) ++++ src/lib/bsnprintf.c (working copy) +@@ -16,7 +16,7 @@ + /* + Bacula® - The Network Backup Solution + +- Copyright (C) 2005-2007 Free Software Foundation Europe e.V. ++ Copyright (C) 2005-2008 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. +@@ -566,11 +566,11 @@ + return result; + } + +-static long round(LDOUBLE value) ++static int64_t round(LDOUBLE value) + { +- long intpart; ++ int64_t intpart; + +- intpart = (long)value; ++ intpart = (int64_t)value; + value = value - intpart; + if (value >= 0.5) + intpart++; +@@ -584,8 +584,8 @@ + int signvalue = 0; + LDOUBLE ufvalue; + #ifndef HAVE_FCVT +- char iconvert[25]; +- char fconvert[25]; ++ char iconvert[311]; ++ char fconvert[311]; + #else + char iconvert[311]; + char fconvert[311]; +@@ -602,6 +602,7 @@ + int caps = 0; + int64_t intpart; + int64_t fracpart; ++ const char *cvt_str; + + /* + * AIX manpage says the default is 0, but Solaris says the default +@@ -625,7 +626,7 @@ + #endif + + #ifndef HAVE_FCVT +- intpart = (long)ufvalue; ++ intpart = (int64_t)ufvalue; + + /* + * Sorry, we only support 9 digits past the decimal because of our +@@ -645,28 +646,30 @@ + } + + #ifdef DEBUG_SNPRINTF +- printf("fmtfp: %g %d.%d min=%d max=%d\n", ++ printf("fmtfp: %g %lld.%lld min=%d max=%d\n", + (double)fvalue, intpart, fracpart, min, max); + #endif + + /* Convert integer part */ ++ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + do { +- iconvert[iplace++] = +- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10]; ++ iconvert[iplace++] = cvt_str[(int)(intpart % 10)]; + intpart = (intpart / 10); +- } while (intpart && (iplace < (int)sizeof(iplace))); +- if (iplace == (int)sizeof(iplace)) { ++ } while (intpart && (iplace < (int)sizeof(iconvert))); ++ ++ if (iplace == (int)sizeof(fconvert)) { + iplace--; + } + iconvert[iplace] = 0; + + /* Convert fractional part */ ++ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + do { +- fconvert[fplace++] = +- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10]; ++ fconvert[fplace++] = cvt_str[fracpart % 10]; + fracpart = (fracpart / 10); +- } while (fracpart && (fplace < (int)sizeof(fplace))); +- if (fplace == (int)sizeof(fplace)) { ++ } while (fracpart && (fplace < (int)sizeof(fconvert))); ++ ++ if (fplace == (int)sizeof(fconvert)) { + fplace--; + } + fconvert[fplace] = 0; +@@ -825,7 +828,7 @@ + NULL + }; + double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, +- 0.9996, 1.996, 4.136, 6442452944.1234, 0 ++ 0.9996, 1.996, 4.136, 6442452944.1234, 0, 23365.5 + }; + #endif + char *int_fmt[] = { diff --git a/bacula/patches/2.2.x/2.2.7-jobdefs-migtype.patch b/bacula/patches/2.2.x/2.2.7-jobdefs-migtype.patch new file mode 100644 index 0000000000..c636dd68ba --- /dev/null +++ b/bacula/patches/2.2.x/2.2.7-jobdefs-migtype.patch @@ -0,0 +1,56 @@ + + This patch permits to use migration options with JobDefs. + This patch fixes bug #1028. + + Apply the patch to 2.2.7 (and possibly any 2.2.x version with): + + cd + patch -p0 <2.2.7-jobdefs-migtype.patch + ./configure + make + ... + make install + +Index: src/dird/dird.c +=================================================================== +--- src/dird/dird.c (revision 6183) ++++ src/dird/dird.c (working copy) +@@ -58,6 +58,7 @@ + void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass); + void store_level(LEX *lc, RES_ITEM *item, int index, int pass); + void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); ++void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); + void init_device_resources(); + + static char *runjob = NULL; +@@ -698,6 +699,7 @@ + job_items[i].handler == store_jobtype || + job_items[i].handler == store_level || + job_items[i].handler == store_pint || ++ job_items[i].handler == store_migtype || + job_items[i].handler == store_replace) { + def_ivalue = (int *)((char *)(job->jobdefs) + offset); + Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n", +Index: src/dird/dird_conf.c +=================================================================== +--- src/dird/dird_conf.c (revision 6183) ++++ src/dird/dird_conf.c (working copy) +@@ -74,8 +74,8 @@ + void store_level(LEX *lc, RES_ITEM *item, int index, int pass); + void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); + void store_acl(LEX *lc, RES_ITEM *item, int index, int pass); ++void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_device(LEX *lc, RES_ITEM *item, int index, int pass); +-static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass); +@@ -1548,7 +1548,7 @@ + * Store JobType (backup, verify, restore) + * + */ +-static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) ++void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) + { + int token, i; + diff --git a/bacula/patches/2.2.x/2.2.7-mysql-batch-timeout.patch b/bacula/patches/2.2.x/2.2.7-mysql-batch-timeout.patch new file mode 100644 index 0000000000..fafb85d1e1 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.7-mysql-batch-timeout.patch @@ -0,0 +1,30 @@ + + This patch fixes bug #1034 about Temporary MySQL table 'batch' + disappears if MySQL connection times out. + + Apply the patch to 2.2.7 (and possibly any 2.2.x version with): + + cd + patch -p0 <2.2.7-mysql-batch-timeout.patch + ./configure + make + ... + make install + + + +Index: src/cats/mysql.c +=================================================================== +--- src/cats/mysql.c (révision 6192) ++++ src/cats/mysql.c (copie de travail) +@@ -205,6 +205,10 @@ + Dmsg3(100, "opendb ref=%d connected=%d db=%p\n", mdb->ref_count, + mdb->connected, mdb->db); + ++ /* Set connection timeout to 8 days specialy for batch mode */ ++ sql_query(mdb, "SET wait_timeout=691200"); ++ sql_query(mdb, "SET interactive_timeout=691200"); ++ + V(mutex); + return 1; + } diff --git a/bacula/patches/2.2.x/2.2.7-old-postgresql.patch b/bacula/patches/2.2.x/2.2.7-old-postgresql.patch new file mode 100644 index 0000000000..d13b11865d --- /dev/null +++ b/bacula/patches/2.2.x/2.2.7-old-postgresql.patch @@ -0,0 +1,26 @@ + + If you have an old version of PostgreSQL, for example, + version 7.3 or older, it may not properly build with the current + Bacula release due to incompatible changes in the PostgreSQL + header files between version. Only in the case that build fails, + you might try applying this patch with: + + cd + patch -p1 <2.2.7-old-postgresql.patch + ./configure + make + ... + make install + + +diff -uNr bacula-2.2.7/src/cats/postgresql.c bacula-2.2.7-fixed/src/cats/postgresql.c +--- bacula-2.2.7/src/cats/postgresql.c 2007-12-08 04:54:55.000000000 -0500 ++++ bacula-2.2.7-fixed/src/cats/postgresql.c 2007-12-29 08:34:10.000000000 -0500 +@@ -47,7 +47,6 @@ + #ifdef HAVE_POSTGRESQL + + #include "postgres_ext.h" /* needed for NAMEDATALEN */ +-#include "pg_config_manual.h" /* get NAMEDATALEN on version 8.3 or later */ + + /* ----------------------------------------------------------------------- + * diff --git a/bacula/patches/2.2.x/2.2.7-reserve.patch b/bacula/patches/2.2.x/2.2.7-reserve.patch new file mode 100644 index 0000000000..42daad1280 --- /dev/null +++ b/bacula/patches/2.2.x/2.2.7-reserve.patch @@ -0,0 +1,1467 @@ + + This patch has a number of cleanups and improvements to the SD + reservations system. It should fix a number of problems with + dual drive autochangers as well ensure that volume use durations + and max volume jobs are better respected. + + Apply it to version 2.2.7 (possibly some earlier versions) with: + + cd + patch -p1 <2.2.7-reserve.patch + ./configure + make + ... + make install + + +diff -ur k1/src/lib/message.c k3/src/lib/message.c +--- k1/src/lib/message.c 2007-10-19 13:47:58.000000000 +0200 ++++ k3/src/lib/message.c 2007-12-22 19:13:00.000000000 +0100 +@@ -54,6 +54,7 @@ + int verbose = 0; /* increase User messages */ + /* Keep debug level set to zero by default */ + int debug_level = 0; /* debug level */ ++bool dbg_timestamp = false; /* print timestamp in debug output */ + time_t daemon_start_time = 0; /* Daemon start time */ + const char *version = VERSION " (" BDATE ")"; + char my_name[30]; /* daemon name is stored here */ +diff -ur k1/src/lib/message.h k3/src/lib/message.h +--- k1/src/lib/message.h 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/lib/message.h 2007-12-22 19:13:06.000000000 +0100 +@@ -154,6 +154,7 @@ + extern DLL_IMP_EXP sql_escape p_sql_escape; + + extern DLL_IMP_EXP int debug_level; ++extern DLL_IMP_EXP bool dbg_timestamp; /* print timestamp in debug output */ + extern DLL_IMP_EXP int verbose; + extern DLL_IMP_EXP char my_name[]; + extern DLL_IMP_EXP const char * working_directory; +diff -ur k1/src/stored/acquire.c k3/src/stored/acquire.c +--- k1/src/stored/acquire.c 2007-09-14 11:49:06.000000000 +0200 ++++ k3/src/stored/acquire.c 2007-12-22 19:12:23.000000000 +0100 +@@ -30,7 +30,7 @@ + * + * Kern Sibbald, August MMII + * +- * Version $Id: acquire.c 5552 2007-09-14 09:49:06Z kerns $ ++ * Version $Id: acquire.c 6081 2007-12-21 14:11:40Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -38,6 +38,7 @@ + + /* Forward referenced functions */ + static void attach_dcr_to_dev(DCR *dcr); ++static bool is_suitable_volume_mounted(DCR *dcr); + + + /********************************************************************* +@@ -316,9 +317,9 @@ + */ + DCR *acquire_device_for_append(DCR *dcr) + { +- bool release = false; +- bool recycle = false; + bool do_mount = false; ++ bool release = false; ++ bool have_vol; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + +@@ -337,6 +338,11 @@ + goto get_out; + } + ++ /* ++ * have_vol defines whether or not mount_next_write_volume should ++ * ask the Director again about what Volume to use. ++ */ ++ have_vol = is_suitable_volume_mounted(dcr); + if (dev->can_append()) { + Dmsg0(190, "device already in append.\n"); + /* +@@ -351,25 +357,11 @@ + * dcr->VolumeName is what we pass into the routines, or + * get back from the subroutines. + */ +- bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName)); +- if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) && ++ if (!have_vol && + !(dir_find_next_appendable_volume(dcr) && + strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */ +- Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName, +- dcr->VolumeName); +- /* Release volume reserved by dir_find_next_appendable_volume() */ +- if (dcr->VolumeName[0]) { +- volume_unused(dcr); +- } +- if (dev->num_writers != 0) { +- Jmsg3(jcr, M_FATAL, 0, _("Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), +- dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName); +- Dmsg3(200, "Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n", +- dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName); +- goto get_out; +- } + /* Wrong tape mounted, release it, then fall through to get correct one */ +- Dmsg0(190, "Wrong tape mounted, release and try mount.\n"); ++ Dmsg0(50, "Wrong tape mounted, release and try mount.\n"); + release = true; + do_mount = true; + } else { +@@ -378,14 +370,17 @@ + * we do not need to do mount_next_write_volume(), unless + * we need to recycle the tape. + */ +- recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; +- Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle); +- if (recycle && dev->num_writers != 0) { ++ do_mount = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; ++ Dmsg2(190, "jid=%u Correct tape mounted. recycle=%d\n", ++ (uint32_t)jcr->JobId, do_mount); ++#ifdef xxx ++ if (do_mount && dev->num_writers != 0) { + Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\"" + " on device %s because it is in use by another job.\n"), + dev->VolHdr.VolumeName, dev->print_name()); + goto get_out; + } ++#endif + if (dev->num_writers == 0) { + memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); + } +@@ -415,21 +410,23 @@ + } + } else { + /* Not already in append mode, so mount the device */ +- Dmsg0(190, "Not in append mode, try mount.\n"); ++ Dmsg2(190, "jid=%u Not in append mode, try mount have_vol=%d\n", ++ (uint32_t)jcr->JobId, have_vol); ++ + ASSERT(dev->num_writers == 0); + do_mount = true; + } + +- if (do_mount || recycle) { +- Dmsg0(190, "Do mount_next_write_vol\n"); +- bool mounted = mount_next_write_volume(dcr, release); ++ if (do_mount || !have_vol) { ++ Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId); ++ bool mounted = mount_next_write_volume(dcr, have_vol, release); + if (!mounted) { + if (!job_canceled(jcr)) { + /* Reduce "noise" -- don't print if job canceled */ + Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), + dev->print_name()); +- Dmsg1(200, "Could not ready device %s for append.\n", +- dev->print_name()); ++ Dmsg2(200, "jid=%u Could not ready device %s for append.\n", ++ (uint32_t)jcr->JobId, dev->print_name()); + } + goto get_out; + } +@@ -441,11 +438,12 @@ + jcr->NumWriteVolumes = 1; + } + dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + dev->dlock(); + if (dcr->reserved_device) { + dev->reserved_device--; +- Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); ++ Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, ++ dev->reserved_device, dev->print_name()); + dcr->reserved_device = false; + } + dev->dunblock(DEV_LOCKED); +@@ -458,7 +456,8 @@ + dev->dlock(); + if (dcr->reserved_device) { + dev->reserved_device--; +- Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); ++ Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, ++ dev->reserved_device, dev->print_name()); + dcr->reserved_device = false; + } + dev->dunblock(DEV_LOCKED); +@@ -466,6 +465,18 @@ + } + + ++static bool is_suitable_volume_mounted(DCR *dcr) ++{ ++ DEVICE *dev = dcr->dev; ++ ++ /* Volume mounted? */ ++ if (dev->VolHdr.VolumeName[0] == 0) { ++ return false; /* no */ ++ } ++ bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName)); ++ return dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE); ++} ++ + /* + * This job is done, so release the device. From a Unix standpoint, + * the device remains open. +@@ -496,7 +507,7 @@ + if (dev->can_read()) { + dev->clear_read(); /* clear read bit */ + Dmsg0(100, "dir_update_vol_info. Release0\n"); +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + + } else if (dev->num_writers > 0) { + /* +@@ -522,7 +533,7 @@ + dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ + /* Note! do volume update before close, which zaps VolCatInfo */ + Dmsg0(100, "dir_update_vol_info. Release0\n"); +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + } + } + +@@ -621,7 +632,12 @@ + if (dcr->attached_to_dev) { + detach_dcr_from_dev(dcr); + } +- dcr->max_job_spool_size = dev->device->max_job_spool_size; ++ /* Use job spoolsize prior to device spoolsize */ ++ if (jcr->spool_size) { ++ dcr->max_job_spool_size = jcr->spool_size; ++ } else { ++ dcr->max_job_spool_size = dev->device->max_job_spool_size; ++ } + dcr->device = dev->device; + dcr->dev = dev; + attach_dcr_to_dev(dcr); +diff -ur k1/src/stored/askdir.c k3/src/stored/askdir.c +--- k1/src/stored/askdir.c 2007-09-09 12:03:23.000000000 +0200 ++++ k3/src/stored/askdir.c 2007-12-22 19:11:50.000000000 +0100 +@@ -31,7 +31,7 @@ + * + * Kern Sibbald, December 2000 + * +- * Version $Id: askdir.c 5503 2007-09-09 10:03:23Z kerns $ ++ * Version $Id: askdir.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -42,7 +42,7 @@ + static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n"; + static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s" + " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u" +- " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s" ++ " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%s VolStatus=%s" + " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s" + " VolFirstWritten=%s VolParts=%u\n"; + static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" +@@ -98,7 +98,7 @@ + } else { + pm_strcpy(ChangerName, "*"); + } +- ok =bnet_fsend(dir, Device_update, ++ ok = dir->fsend(Device_update, + jcr->Job, + dev_name.c_str(), + dev->can_append()!=0, +@@ -125,7 +125,7 @@ + pm_strcpy(MediaType, device->media_type); + bash_spaces(MediaType); + /* This is mostly to indicate that we are here */ +- ok = bnet_fsend(dir, Device_update, ++ ok = dir->fsend(Device_update, + jcr->Job, + dev_name.c_str(), /* Changer name */ + 0, 0, 0, /* append, read, num_writers */ +@@ -148,7 +148,7 @@ + */ + bool dir_send_job_status(JCR *jcr) + { +- return bnet_fsend(jcr->dir_bsock, Job_status, jcr->Job, jcr->JobStatus); ++ return jcr->dir_bsock->fsend(Job_status, jcr->Job, jcr->JobStatus); + } + + /* +@@ -179,7 +179,7 @@ + return false; + } + memset(&vol, 0, sizeof(vol)); +- Dmsg1(100, "msg); ++ Dmsg1(100, "msg); + n = sscanf(dir->msg, OK_media, vol.VolCatName, + &vol.VolCatJobs, &vol.VolCatFiles, + &vol.VolCatBlocks, &vol.VolCatBytes, +@@ -191,7 +191,8 @@ + &vol.EndFile, &vol.EndBlock, &vol.VolCatParts, + &vol.LabelType, &vol.VolMediaId); + if (n != 22) { +- Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", n, dir->msglen, dir->msg); ++ Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", ++ n, dir->msglen, dir->msg); + Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg); + return false; + } +@@ -226,7 +227,7 @@ + bash_spaces(dcr->VolCatInfo.VolCatName); + dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName, + writing==GET_VOL_INFO_FOR_WRITE?1:0); +- Dmsg1(100, ">dird: %s\n", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + unbash_spaces(dcr->VolCatInfo.VolCatName); + bool ok = do_get_volume_info(dcr); + V(vol_info_mutex); +@@ -253,7 +254,9 @@ + BSOCK *dir = jcr->dir_bsock; + bool found = false; + +- Dmsg0(200, "dir_find_next_appendable_volume\n"); ++ Dmsg2(200, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", ++ dcr->reserved_device, dcr->VolumeName); ++ + /* + * Try the twenty oldest or most available volumes. Note, + * the most available could already be mounted on another +@@ -268,7 +271,7 @@ + dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type); + unbash_spaces(dcr->media_type); + unbash_spaces(dcr->pool_name); +- Dmsg1(100, ">dird: %s", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + bool ok = do_get_volume_info(dcr); + if (ok) { + if (!is_volume_in_use(dcr)) { +@@ -311,14 +314,13 @@ + * back to the director. The information comes from the + * dev record. + */ +-bool dir_update_volume_info(DCR *dcr, bool label) ++bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten) + { + JCR *jcr = dcr->jcr; + BSOCK *dir = jcr->dir_bsock; + DEVICE *dev = dcr->dev; +- time_t LastWritten = time(NULL); + VOLUME_CAT_INFO *vol = &dev->VolCatInfo; +- char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50]; ++ char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50]; + int InChanger; + bool ok = false; + POOL_MEM VolumeName; +@@ -341,21 +343,25 @@ + if (label) { + bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); + } ++// if (update_LastWritten) { ++ vol->VolLastWritten = time(NULL); ++// } + pm_strcpy(VolumeName, vol->VolCatName); + bash_spaces(VolumeName); + InChanger = vol->InChanger; +- bnet_fsend(dir, Update_media, jcr->Job, ++ dir->fsend(Update_media, jcr->Job, + VolumeName.c_str(), vol->VolCatJobs, vol->VolCatFiles, + vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1), + vol->VolCatMounts, vol->VolCatErrors, + vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), +- LastWritten, vol->VolCatStatus, vol->Slot, label, ++ edit_uint64(vol->VolLastWritten, ed6), ++ vol->VolCatStatus, vol->Slot, label, + InChanger, /* bool in structure */ + edit_int64(vol->VolReadTime, ed3), + edit_int64(vol->VolWriteTime, ed4), + edit_uint64(vol->VolFirstWritten, ed5), + vol->VolCatParts); +- Dmsg1(100, ">dird: %s", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + + /* Do not lock device here because it may be locked from label */ + if (!do_get_volume_info(dcr)) { +@@ -364,7 +370,7 @@ + vol->VolCatName, jcr->errmsg); + goto bail_out; + } +- Dmsg1(420, "get_volume_info(): %s", dir->msg); ++ Dmsg1(420, "get_volume_info() %s", dir->msg); + /* Update dev Volume info in case something changed (e.g. expired) */ + dev->VolCatInfo = dcr->VolCatInfo; + ok = true; +@@ -393,20 +399,20 @@ + } + + dcr->WroteVol = false; +- bnet_fsend(dir, Create_job_media, jcr->Job, ++ dir->fsend(Create_job_media, jcr->Job, + dcr->VolFirstIndex, dcr->VolLastIndex, + dcr->StartFile, dcr->EndFile, + dcr->StartBlock, dcr->EndBlock, + dcr->Copy, dcr->Stripe, + edit_uint64(dcr->VolMediaId, ed1)); +- Dmsg1(100, ">dird: %s", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + if (bnet_recv(dir) <= 0) { + Dmsg0(190, "create_jobmedia error bnet_recv\n"); + Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"), +- bnet_strerror(dir)); ++ dir->bstrerror()); + return false; + } +- Dmsg1(100, "msg); ++ Dmsg1(100, "msg); + if (strcmp(dir->msg, OK_create) != 0) { + Dmsg1(130, "Bad response from Dir: %s\n", dir->msg); + Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg); +@@ -429,9 +435,10 @@ + return true; + #endif + +- dir->msglen = sprintf(dir->msg, FileAttributes, jcr->Job); +- dir->msg = check_pool_memory_size(dir->msg, dir->msglen + +- sizeof(DEV_RECORD) + rec->data_len); ++ dir->msg = check_pool_memory_size(dir->msg, sizeof(FileAttributes) + ++ MAX_NAME_LENGTH + sizeof(DEV_RECORD) + rec->data_len + 1); ++ dir->msglen = bsnprintf(dir->msg, sizeof(FileAttributes) + ++ MAX_NAME_LENGTH + 1, FileAttributes, jcr->Job); + ser_begin(dir->msg + dir->msglen, 0); + ser_uint32(rec->VolSessionId); + ser_uint32(rec->VolSessionTime); +@@ -440,8 +447,8 @@ + ser_uint32(rec->data_len); + ser_bytes(rec->data, rec->data_len); + dir->msglen = ser_length(dir->msg); +- Dmsg1(1800, ">dird: %s\n", dir->msg); /* Attributes */ +- return bnet_send(dir); ++ Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */ ++ return dir->send(); + } + + +diff -ur k1/src/stored/bcopy.c k3/src/stored/bcopy.c +--- k1/src/stored/bcopy.c 2007-12-03 20:27:38.000000000 +0100 ++++ k3/src/stored/bcopy.c 2007-12-22 19:10:29.000000000 +0100 +@@ -32,7 +32,7 @@ + * Kern E. Sibbald, October 2002 + * + * +- * Version $Id: bcopy.c 6017 2007-12-03 19:27:38Z kerns $ ++ * Version $Id: bcopy.c 6016 2007-12-03 19:27:21Z kerns $ + */ + + #include "bacula.h" +@@ -42,6 +42,7 @@ + int generate_daemon_event(JCR *jcr, const char *event) { return 1; } + + /* Forward referenced functions */ ++static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); + static bool record_cb(DCR *dcr, DEV_RECORD *rec); + + +@@ -52,10 +53,11 @@ + static JCR *out_jcr; /* output jcr */ + static BSR *bsr = NULL; + static const char *wd = "/tmp"; +-static int list_records = 0; ++static bool list_records = false; + static uint32_t records = 0; + static uint32_t jobs = 0; + static DEV_BLOCK *out_block; ++static SESSION_LABEL sessrec; + + #define CONFIG_FILE "bacula-sd.conf" + char *configfile = NULL; +@@ -73,7 +75,7 @@ + "Usage: bcopy [-d debug_level] \n" + " -b bootstrap specify a bootstrap file\n" + " -c specify configuration file\n" +-" -d set debug level to nn\n" ++" -d set debug level to \n" + " -i specify input Volume names (separated by |)\n" + " -o specify output Volume names (separated by |)\n" + " -p proceed inspite of errors\n" +@@ -113,9 +115,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'i': /* input Volume name */ +@@ -201,6 +208,7 @@ + out_block = out_jcr->dcr->block; + + ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume); ++ + if (ok || out_dev->can_write()) { + if (!write_block_to_device(out_jcr->dcr)) { + Pmsg0(000, _("Write of last block failed.\n")); +@@ -233,6 +241,7 @@ + * + */ + if (rec->FileIndex < 0) { ++ get_session_record(in_dcr->dev, rec, &sessrec); + + if (verbose > 1) { + dump_label_record(in_dcr->dev, rec, 1); +@@ -294,10 +303,46 @@ + return true; + } + ++static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) ++{ ++ const char *rtype; ++ memset(sessrec, 0, sizeof(sessrec)); ++ switch (rec->FileIndex) { ++ case PRE_LABEL: ++ rtype = _("Fresh Volume Label"); ++ break; ++ case VOL_LABEL: ++ rtype = _("Volume Label"); ++ unser_volume_label(dev, rec); ++ break; ++ case SOS_LABEL: ++ rtype = _("Begin Job Session"); ++ unser_session_label(sessrec, rec); ++ break; ++ case EOS_LABEL: ++ rtype = _("End Job Session"); ++ unser_session_label(sessrec, rec); ++ break; ++ case 0: ++ case EOM_LABEL: ++ rtype = _("End of Medium"); ++ break; ++ default: ++ rtype = _("Unknown"); ++ break; ++ } ++ Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", ++ rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); ++ if (verbose) { ++ Pmsg5(-1, _("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n"), ++ rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); ++ } ++} ++ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/bextract.c k3/src/stored/bextract.c +--- k1/src/stored/bextract.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/bextract.c 2007-12-22 19:10:20.000000000 +0100 +@@ -4,7 +4,7 @@ + * + * Kern E. Sibbald, MM + * +- * Version $Id: bextract.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: bextract.c 5852 2007-11-04 19:57:42Z kerns $ + * + */ + /* +@@ -79,7 +79,7 @@ + "Usage: bextract \n" + " -b specify a bootstrap file\n" + " -c specify a configuration file\n" +-" -d set debug level to nn\n" ++" -d set debug level to \n" + " -e exclude list\n" + " -i include list\n" + " -p proceed inspite of I/O errors\n" +@@ -126,9 +126,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'e': /* exclude list */ +@@ -476,7 +481,7 @@ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/block.c k3/src/stored/block.c +--- k1/src/stored/block.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/block.c 2007-12-22 19:12:33.000000000 +0100 +@@ -32,7 +32,7 @@ + * Kern Sibbald, March MMI + * added BB02 format October MMII + * +- * Version $Id: block.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: block.c 5852 2007-11-04 19:57:42Z kerns $ + * + */ + +@@ -746,7 +746,7 @@ + dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; + } + +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, true)) { + ok = false; + } + Dmsg1(100, "dir_update_volume_info terminate writing -- %s\n", ok?"OK":"ERROR"); +@@ -798,7 +798,7 @@ + return false; + } + dev->VolCatInfo.VolCatFiles = dev->file; +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, false)) { + Dmsg0(190, "Error from update_vol_info.\n"); + terminate_writing_volume(dcr); + dev->dev_errno = EIO; +@@ -856,7 +856,7 @@ + + dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; + +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, false)) { + Dmsg0(190, "Error from update_vol_info.\n"); + dev->dev_errno = EIO; + return false; +diff -ur k1/src/stored/bls.c k3/src/stored/bls.c +--- k1/src/stored/bls.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/bls.c 2007-12-22 19:10:57.000000000 +0100 +@@ -31,7 +31,7 @@ + * + * Kern Sibbald, MM + * +- * Version $Id: bls.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: bls.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" +@@ -79,7 +79,7 @@ + "Usage: bls [options] \n" + " -b specify a bootstrap file\n" + " -c specify a config file\n" +-" -d specify debug level\n" ++" -d set debug level to \n" + " -e exclude list\n" + " -i include list\n" + " -j list jobs\n" +@@ -130,9 +130,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'e': /* exclude list */ +@@ -440,7 +445,7 @@ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/bscan.c k3/src/stored/bscan.c +--- k1/src/stored/bscan.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/bscan.c 2007-12-22 19:11:05.000000000 +0100 +@@ -34,7 +34,7 @@ + * Kern E. Sibbald, December 2001 + * + * +- * Version $Id: bscan.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: bscan.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" +@@ -116,7 +116,7 @@ + "Usage: bscan [ options ] \n" + " -b bootstrap specify a bootstrap file\n" + " -c specify configuration file\n" +-" -d set debug level to nn\n" ++" -d set debug level to \n" + " -m update media info in database\n" + " -n specify the database name (default bacula)\n" + " -u specify database user name (default bacula)\n" +@@ -166,9 +166,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'h': +@@ -1271,7 +1276,7 @@ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/btape.c k3/src/stored/btape.c +--- k1/src/stored/btape.c 2007-06-07 16:46:43.000000000 +0200 ++++ k3/src/stored/btape.c 2007-12-22 19:11:14.000000000 +0100 +@@ -37,7 +37,7 @@ + * Note, this program reads stored.conf, and will only + * talk to devices that are configured. + * +- * Version $Id: btape.c 4992 2007-06-07 14:46:43Z kerns $ ++ * Version $Id: btape.c 5852 2007-11-04 19:57:42Z kerns $ + * + */ + +@@ -220,9 +220,13 @@ + break; + + case 'd': /* set debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) { +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } + } + break; + +@@ -2598,7 +2602,7 @@ + "Usage: btape \n" + " -b specify bootstrap file\n" + " -c set configuration file to file\n" +-" -d set debug level to nn\n" ++" -d set debug level to \n" + " -p proceed inspite of I/O errors\n" + " -s turn off signals\n" + " -v be verbose\n" +@@ -2644,7 +2648,7 @@ + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} + bool dir_send_job_status(JCR *jcr) {return 1;} + +-bool dir_update_volume_info(DCR *dcr, bool relabel) ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) + { + return 1; + } +diff -ur k1/src/stored/dev.c k3/src/stored/dev.c +--- k1/src/stored/dev.c 2007-12-02 19:03:17.000000000 +0100 ++++ k3/src/stored/dev.c 2007-12-22 19:11:57.000000000 +0100 +@@ -47,7 +47,7 @@ + * daemon. More complicated coding (double buffering, writer + * thread, ...) is left for a later version. + * +- * Version $Id: dev.c 6011 2007-12-02 18:03:17Z kerns $ ++ * Version $Id: dev.c 5999 2007-11-29 21:36:36Z ricozz $ + */ + + /* +@@ -89,7 +89,7 @@ + /* Forward referenced functions */ + void set_os_device_parameters(DCR *dcr); + static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat); +-static char *mode_to_str(int mode); ++static const char *mode_to_str(int mode); + + /* + * Allocate and initialize the DEVICE structure +@@ -490,7 +490,7 @@ + Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), + be.bstrerror()); + Dmsg1(100, "open failed: %s", errmsg); +- Emsg0(M_FATAL, 0, errmsg); ++ Jmsg1(NULL, M_WARNING, 0, "%s", errmsg); + } else { + dev_errno = 0; + file = 0; +@@ -2468,7 +2468,7 @@ + mt_stat->mt_fileno >= 0; + } + +-static char *modes[] = { ++static const char *modes[] = { + "CREATE_READ_WRITE", + "OPEN_READ_WRITE", + "OPEN_READ_ONLY", +@@ -2476,7 +2476,7 @@ + }; + + +-static char *mode_to_str(int mode) ++static const char *mode_to_str(int mode) + { + static char buf[100]; + if (mode < 1 || mode > 4) { +diff -ur k1/src/stored/dev.h k3/src/stored/dev.h +--- k1/src/stored/dev.h 2007-09-09 12:03:23.000000000 +0200 ++++ k3/src/stored/dev.h 2007-12-22 19:12:14.000000000 +0100 +@@ -31,7 +31,7 @@ + * + * Kern Sibbald, MM + * +- * Version $Id: dev.h 5503 2007-09-09 10:03:23Z kerns $ ++ * Version $Id: dev.h 5852 2007-11-04 19:57:42Z kerns $ + * + */ + +@@ -158,6 +158,7 @@ + btime_t VolWriteTime; /* time spent writing this Volume */ + int64_t VolMediaId; /* MediaId */ + utime_t VolFirstWritten; /* Time of first write */ ++ utime_t VolLastWritten; /* Time of last write */ + bool InChanger; /* Set if vol in current magazine */ + char VolCatStatus[20]; /* Volume status */ + char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ +@@ -473,8 +474,9 @@ + class VOLRES { + public: + dlink link; +- char *vol_name; +- DEVICE *dev; ++ char *vol_name; /* Volume name */ ++ DEVICE *dev; /* Pointer to device to which we are attached */ ++ bool released; /* set when the Volume can be released */ + }; + + +diff -ur k1/src/stored/device.c k3/src/stored/device.c +--- k1/src/stored/device.c 2007-06-29 14:12:26.000000000 +0200 ++++ k3/src/stored/device.c 2007-12-22 19:11:23.000000000 +0100 +@@ -53,7 +53,7 @@ + * + * Kern Sibbald, MM, MMI + * +- * Version $Id: device.c 5114 2007-06-29 12:12:26Z kerns $ ++ * Version $Id: device.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -122,7 +122,8 @@ + edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), + bstrftime(dt, sizeof(dt), time(NULL))); + +- if (!mount_next_write_volume(dcr, 1)) { ++ /* Called with have_vol=false, release=true */ ++ if (!mount_next_write_volume(dcr, false, true)) { + free_block(label_blk); + dcr->block = block; + dev->dlock(); +@@ -131,7 +132,7 @@ + dev->dlock(); /* lock again */ + + dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + + Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"), + dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL))); +diff -ur k1/src/stored/dvd.c k3/src/stored/dvd.c +--- k1/src/stored/dvd.c 2007-06-07 16:46:43.000000000 +0200 ++++ k3/src/stored/dvd.c 2007-12-22 19:26:23.000000000 +0100 +@@ -1,16 +1,7 @@ + /* +- * +- * dvd.c -- Routines specific to DVD devices (and +- * possibly other removable hard media). +- * +- * Nicolas Boichat, MMV +- * +- * Version $Id: dvd.c 4992 2007-06-07 14:46:43Z kerns $ +- */ +-/* + Bacula® - The Network Backup Solution + +- Copyright (C) 2005-2006 Free Software Foundation Europe e.V. ++ Copyright (C) 2005-2007 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. +@@ -34,6 +25,15 @@ + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. + */ ++/* ++ * ++ * dvd.c -- Routines specific to DVD devices (and ++ * possibly other removable hard media). ++ * ++ * Nicolas Boichat, MMV ++ * ++ * Version $Id: dvd.c 5852 2007-11-04 19:57:42Z kerns $ ++ */ + + #include "bacula.h" + #include "stored.h" +@@ -686,7 +686,7 @@ + dcr->VolCatInfo.VolCatBytes = 0; + + /* Update catalog */ +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, true)) { + return false; + } + +diff -ur k1/src/stored/job.c k3/src/stored/job.c +--- k1/src/stored/job.c 2007-09-29 00:01:16.000000000 +0200 ++++ k3/src/stored/job.c 2007-12-22 19:11:41.000000000 +0100 +@@ -30,7 +30,7 @@ + * + * Kern Sibbald, MM + * +- * Version $Id: job.c 5686 2007-09-28 22:01:16Z kerns $ ++ * Version $Id: job.c 5697 2007-09-30 17:40:08Z ricozz $ + * + */ + +@@ -49,9 +49,13 @@ + /* Requests from the Director daemon */ + static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " + "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " ++ "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d SpoolSize=%s\n"; ++static char oldjobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " ++ "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " + "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d\n"; + + ++ + /* Responses sent to Director daemon */ + static char OKjob[] = "3000 OK Job SDid=%u SDtime=%u Authorization=%s\n"; + static char BAD_job[] = "3915 Bad Job command. stat=%d CMD: %s\n"; +@@ -73,6 +77,7 @@ + { + int JobId; + char auth_key[100]; ++ char spool_size[30]; + char seed[100]; + BSOCK *dir = jcr->dir_bsock; + POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; +@@ -85,17 +90,26 @@ + * Get JobId and permissions from Director + */ + Dmsg1(100, "msg); ++ bstrncpy(spool_size, "0", sizeof(spool_size)); + stat = sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(), + client_name.c_str(), + &JobType, &level, fileset_name.c_str(), &no_attributes, +- &spool_attributes, fileset_md5.c_str(), &spool_data, ++ &spool_attributes, fileset_md5.c_str(), &spool_data, ++ &write_part_after_job, &PreferMountedVols, spool_size); ++ if (stat != 14) { ++ /* Try old version */ ++ stat = sscanf(dir->msg, oldjobcmd, &JobId, job.c_str(), job_name.c_str(), ++ client_name.c_str(), ++ &JobType, &level, fileset_name.c_str(), &no_attributes, ++ &spool_attributes, fileset_md5.c_str(), &spool_data, + &write_part_after_job, &PreferMountedVols); +- if (stat != 13) { +- pm_strcpy(jcr->errmsg, dir->msg); +- dir->fsend(BAD_job, stat, jcr->errmsg); +- Dmsg1(100, ">dird: %s", dir->msg); +- set_jcr_job_status(jcr, JS_ErrorTerminated); +- return false; ++ if (stat != 13) { ++ pm_strcpy(jcr->errmsg, dir->msg); ++ dir->fsend(BAD_job, stat, jcr->errmsg); ++ Dmsg1(100, ">dird: %s", dir->msg); ++ set_jcr_job_status(jcr, JS_ErrorTerminated); ++ return false; ++ } + } + /* + * Since this job could be rescheduled, we +@@ -125,6 +139,7 @@ + jcr->no_attributes = no_attributes; + jcr->spool_attributes = spool_attributes; + jcr->spool_data = spool_data; ++ jcr->spool_size = str_to_int64(spool_size); + jcr->write_part_after_job = write_part_after_job; + jcr->fileset_md5 = get_pool_memory(PM_NAME); + pm_strcpy(jcr->fileset_md5, fileset_md5); +diff -ur k1/src/stored/label.c k3/src/stored/label.c +--- k1/src/stored/label.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/label.c 2007-12-22 19:10:49.000000000 +0100 +@@ -32,7 +32,7 @@ + * Kern Sibbald, MM + * + * +- * Version $Id: label.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: label.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -505,7 +505,7 @@ + } + Dmsg0(150, "dir_update_vol_info. Set Append\n"); + bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus)); +- if (!dir_update_volume_info(dcr, true)) { /* indicate doing relabel */ ++ if (!dir_update_volume_info(dcr, true, true)) { /* indicate doing relabel */ + return false; + } + if (recycle) { +@@ -716,7 +716,7 @@ + } + break; + default: +- Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label); ++ Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label = %d\n"), label); + break; + } + create_session_label(dcr, rec, label); +diff -ur k1/src/stored/mount.c k3/src/stored/mount.c +--- k1/src/stored/mount.c 2007-09-14 11:49:06.000000000 +0200 ++++ k3/src/stored/mount.c 2007-12-22 19:11:30.000000000 +0100 +@@ -32,7 +32,7 @@ + * + * Kern Sibbald, August MMII + * +- * Version $Id: mount.c 5552 2007-09-14 09:49:06Z kerns $ ++ * Version $Id: mount.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -60,7 +60,7 @@ + * impossible to get the requested Volume. + * + */ +-bool mount_next_write_volume(DCR *dcr, bool release) ++bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release) + { + int retry = 0; + bool ask = false, recycle, autochanger; +@@ -108,12 +108,16 @@ + * in dcr->VolCatInfo + */ + Dmsg0(200, "Before dir_find_next_appendable_volume.\n"); +- while (!dir_find_next_appendable_volume(dcr)) { +- Dmsg0(200, "not dir_find_next\n"); +- if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { +- return false; ++ if (!have_vol) { ++ while (!dir_find_next_appendable_volume(dcr)) { ++ Dmsg0(200, "not dir_find_next\n"); ++ if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { ++ return false; ++ } ++ Dmsg0(200, "Again dir_find_next_append...\n"); + } +- Dmsg0(200, "Again dir_find_next_append...\n"); ++ } else { ++ have_vol = false; /* set false for next pass if any */ + } + if (job_canceled(jcr)) { + return false; +@@ -144,7 +148,7 @@ + * If we autochanged to correct Volume or (we have not just + * released the Volume AND we can automount) we go ahead + * and read the label. If there is no tape in the drive, +- * we will err, recurse and ask the operator the next time. ++ * we will fail, recurse and ask the operator the next time. + */ + if (!release && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) { + Dmsg0(150, "(1)Ask=0\n"); +@@ -432,7 +436,7 @@ + } + dev->VolCatInfo.VolCatMounts++; /* Update mounts */ + Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts); +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, false)) { + return false; + } + +@@ -519,7 +523,7 @@ + Dmsg0(150, "dir_update_vol_info. Set Append\n"); + /* Copy Director's info into the device info */ + dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ +- if (!dir_update_volume_info(dcr, true)) { /* indicate tape labeled */ ++ if (!dir_update_volume_info(dcr, true, true)) { /* indicate tape labeled */ + return try_error; + } + Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"), +@@ -552,7 +556,7 @@ + dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ + bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus)); + Dmsg0(150, "dir_update_vol_info. Set Error.\n"); +- dir_update_volume_info(dcr, false); ++ dir_update_volume_info(dcr, false, false); + } + + /* +@@ -570,7 +574,7 @@ + dcr->VolCatInfo.InChanger = false; + dev->VolCatInfo.InChanger = false; + Dmsg0(400, "update vol info in mount\n"); +- dir_update_volume_info(dcr, true); /* set new status */ ++ dir_update_volume_info(dcr, true, false); /* set new status */ + } + + /* +@@ -588,6 +592,7 @@ + /* + * First erase all memory of the current volume + */ ++ free_volume(dev); + dev->block_num = dev->file = 0; + dev->EndBlock = dev->EndFile = 0; + memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo)); +diff -ur k1/src/stored/protos.h k3/src/stored/protos.h +--- k1/src/stored/protos.h 2007-06-28 13:57:03.000000000 +0200 ++++ k3/src/stored/protos.h 2007-12-22 19:12:43.000000000 +0100 +@@ -28,7 +28,7 @@ + /* + * Protypes for stored -- Kern Sibbald MM + * +- * Version $Id: protos.h 5112 2007-06-28 11:57:03Z kerns $ ++ * Version $Id: protos.h 5852 2007-11-04 19:57:42Z kerns $ + */ + + /* From stored.c */ +@@ -49,7 +49,7 @@ + }; + bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); + bool dir_find_next_appendable_volume(DCR *dcr); +-bool dir_update_volume_info(DCR *dcr, bool label); ++bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten); + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); + bool dir_ask_sysop_to_mount_volume(DCR *dcr); + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); +@@ -182,7 +182,7 @@ + bool is_this_bsr_done(BSR *bsr, DEV_RECORD *rec); + + /* From mount.c */ +-bool mount_next_write_volume(DCR *dcr, bool release); ++bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release); + bool mount_next_read_volume(DCR *dcr); + void mark_volume_in_error(DCR *dcr); + +diff -ur k1/src/stored/record.c k3/src/stored/record.c +--- k1/src/stored/record.c 2007-06-07 16:46:43.000000000 +0200 ++++ k3/src/stored/record.c 2007-12-22 19:12:06.000000000 +0100 +@@ -1,14 +1,4 @@ + /* +- * +- * record.c -- tape record handling functions +- * +- * Kern Sibbald, April MMI +- * added BB02 format October MMII +- * +- * Version $Id: record.c 4992 2007-06-07 14:46:43Z kerns $ +- * +- */ +-/* + Bacula® - The Network Backup Solution + + Copyright (C) 2001-2006 Free Software Foundation Europe e.V. +@@ -35,6 +25,16 @@ + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. + */ ++/* ++ * ++ * record.c -- tape record handling functions ++ * ++ * Kern Sibbald, April MMI ++ * added BB02 format October MMII ++ * ++ * Version $Id: record.c 6014 2007-12-03 18:14:27Z kerns $ ++ * ++ */ + + + #include "bacula.h" +@@ -254,7 +254,7 @@ + ASSERT(block->buf_len >= block->binbuf); + + Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n" +-"rem=%d remainder=%d\n", ++ "rem=%d remainder=%d\n", + FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, + stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, + remlen, rec->remainder); +@@ -365,7 +365,7 @@ + if (!sm_check_rtn(__FILE__, __LINE__, False)) { + /* We damaged a buffer */ + Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n" +-"rem=%d remainder=%d\n", ++ "rem=%d remainder=%d\n", + FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, + stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, + remlen, rec->remainder); +diff -ur k1/src/stored/reserve.c k3/src/stored/reserve.c +--- k1/src/stored/reserve.c 2007-08-04 18:46:32.000000000 +0200 ++++ k3/src/stored/reserve.c 2007-12-22 19:09:56.000000000 +0100 +@@ -212,11 +212,11 @@ + if (dev) { + len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name()); + sendit(msg.c_str(), len, arg); +- len = Mmsg(msg, " Reader=%d writers=%d reserved=%d\n", dev->can_read()?1:0, +- dev->num_writers, dev->reserved_device); ++ len = Mmsg(msg, " Reader=%d writers=%d reserved=%d released=%d\n", ++ dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released); + sendit(msg.c_str(), len, arg); + } else { +- len = Mmsg(msg, "%s no dev\n", vol->vol_name); ++ len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released); + sendit(msg.c_str(), len, arg); + } + } +@@ -292,11 +292,11 @@ + * already exist and are correctly programmed and will need no changes -- use + * counts are always very tricky. + * +- * The old code had a concept of "reserving" a Volume, but it needs to be changed ++ * The old code had a concept of "reserving" a Volume, but was changed + * to reserving and using a drive. A volume is must be attached to (owned by) a + * drive and can move from drive to drive or be unused given certain specific + * conditions of the drive. The key is that the drive must "own" the Volume. +- * The old code has the job (dcr) owning the volume (more or less). The job is ++ * The old code had the job (dcr) owning the volume (more or less). The job was + * to change the insertion and removal of the volumes from the list to be based + * on the drive rather than the job. + * +@@ -329,13 +329,14 @@ + * because it was probably inserted by another job. + */ + if (strcmp(vol->vol_name, VolumeName) == 0) { ++ Dmsg1(dbglvl, "OK, vol=%s on device.\n", VolumeName); + goto get_out; /* Volume already on this device */ + } else { +- Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", ++ Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", + (int)dcr->jcr->JobId, vol->vol_name, vol->vol_name); +- debug_list_volumes("reserve_vol free"); + vol_list->remove(vol); + free_vol_item(vol); ++ debug_list_volumes("reserve_vol free"); + } + } + +@@ -378,12 +379,16 @@ + Dmsg4(dbglvl, "jid=%u Volume busy could not swap vol=%s from dev=%s to %s\n", + jid(), VolumeName, vol->dev->print_name(), dev->print_name()); + vol = NULL; /* device busy */ ++ goto get_out; + } + } + } + dev->vol = vol; + + get_out: ++ if (vol) { ++ vol->released = false; ++ } + debug_list_volumes("end new volume"); + unlock_volumes(); + return vol; +@@ -462,6 +467,7 @@ + * explicitly read in this drive. This allows the SD to remember + * where the tapes are or last were. + */ ++ dev->vol->released = true; + if (dev->is_tape() || dev->is_autochanger()) { + return true; + } else { +@@ -837,6 +843,7 @@ + dlist *temp_vol_list, *save_vol_list; + VOLRES *vol = NULL; + lock_volumes(); ++ Dmsg0(dbglvl, "lock volumes\n"); + + /* + * Create a temporary copy of the volume list. We do this, +@@ -1122,6 +1129,26 @@ + */ + if (dcr->volume_in_use && !rctx.PreferMountedVols) { + rctx.PreferMountedVols = true; ++ if (dcr->VolumeName[0]) { ++ volume_unused(dcr); ++ } ++ goto bail_out; ++ } ++ /* ++ * Note. Under some circumstances, the Director can hand us ++ * a Volume name that is no the same as the one on the current ++ * drive, and in that case, the call above to find the next ++ * volume will fail because in attempting to reserve the Volume ++ * the code will realize that we already have a tape mounted, ++ * and it will fail. This *should* only happen if there are ++ * writers, thus the following test. In that case, we simply ++ * bail out, and continue waiting, rather than plunging on ++ * and hoping that the operator can resolve the problem. ++ */ ++ if (dcr->dev->num_writers != 0) { ++ if (dcr->VolumeName[0]) { ++ volume_unused(dcr); ++ } + goto bail_out; + } + } +@@ -1270,6 +1297,51 @@ + return ok; + } + ++static int is_pool_ok(DCR *dcr) ++{ ++ DEVICE *dev = dcr->dev; ++ JCR *jcr = dcr->jcr; ++ ++ /* Now check if we want the same Pool and pool type */ ++ if (strcmp(dev->pool_name, dcr->pool_name) == 0 && ++ strcmp(dev->pool_type, dcr->pool_type) == 0) { ++ /* OK, compatible device */ ++ Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name()); ++ return 1; ++ } else { ++ /* Drive Pool not suitable for us */ ++ Mmsg(jcr->errmsg, _( ++"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), ++ (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name, ++ dev->reserved_device, dev->print_name()); ++ queue_reserve_message(jcr); ++ Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n", ++ dev->pool_name, dcr->pool_name); ++ } ++ return 0; ++} ++ ++static bool is_max_jobs_ok(DCR *dcr) ++{ ++ DEVICE *dev = dcr->dev; ++ JCR *jcr = dcr->jcr; ++ ++ Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n", ++ dcr->VolCatInfo.VolCatMaxJobs, ++ dcr->VolCatInfo.VolCatJobs, dev->reserved_device, ++ dcr->VolumeName); ++ if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <= ++ (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) { ++ /* Max Job Vols depassed or already reserved */ ++ Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"), ++ (uint32_t)jcr->JobId, dev->print_name()); ++ queue_reserve_message(jcr); ++ Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg); ++ return false; /* wait */ ++ } ++ return true; ++} ++ + /* + * Returns: 1 if drive can be reserved + * 0 if we should wait +@@ -1285,6 +1357,11 @@ + rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device, + rctx.autochanger_only, rctx.any_drive); + ++ /* Check for max jobs on this Volume */ ++ if (!is_max_jobs_ok(dcr)) { ++ return 0; ++ } ++ + /* setting any_drive overrides PreferMountedVols flag */ + if (!rctx.any_drive) { + /* +@@ -1374,32 +1451,10 @@ + if (dev->num_writers == 0) { + /* Now check if there are any reservations on the drive */ + if (dev->reserved_device) { +- /* Now check if we want the same Pool and pool type */ +- if (strcmp(dev->pool_name, dcr->pool_name) == 0 && +- strcmp(dev->pool_type, dcr->pool_type) == 0) { +- /* OK, compatible device */ +- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, reserved, pool matches\n", +- jcr->JobId, dev->print_name()); +- return 1; +- } else { +- /* Drive Pool not suitable for us */ +- Mmsg(jcr->errmsg, _( +-"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), +- jcr->JobId, dcr->pool_name, dev->pool_name, +- dev->reserved_device, dev->print_name()); +- queue_reserve_message(jcr); +- Dmsg3(dbglvl, "jid=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n", +- (int)jcr->JobId, dev->pool_name, dcr->pool_name); +- return 0; /* wait */ +- } ++ return is_pool_ok(dcr); + } else if (dev->can_append()) { +- /* Device in append mode, check if changing pool */ +- if (strcmp(dev->pool_name, dcr->pool_name) == 0 && +- strcmp(dev->pool_type, dcr->pool_type) == 0) { +- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, can_append, pool matches.\n", +- jcr->JobId, dev->print_name()); +- /* OK, compatible device */ +- return 1; ++ if (is_pool_ok(dcr)) { ++ return 1; + } else { + /* Changing pool, unload old tape if any in drive */ + Dmsg1(dbglvl, "jid=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n", +@@ -1419,22 +1474,7 @@ + * available if pool is the same). + */ + if (dev->can_append() || dev->num_writers > 0) { +- /* Yes, now check if we want the same Pool and pool type */ +- if (strcmp(dev->pool_name, dcr->pool_name) == 0 && +- strcmp(dev->pool_type, dcr->pool_type) == 0) { +- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers>=0, can_append, pool matches.\n", +- jcr->JobId, dev->print_name()); +- /* OK, compatible device */ +- return 1; +- } else { +- /* Drive Pool not suitable for us */ +- Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"), +- jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name()); +- queue_reserve_message(jcr); +- Dmsg3(dbglvl, "jid=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n", +- (int)jcr->JobId, dev->pool_name, dcr->pool_name); +- return 0; /* wait */ +- } ++ return is_pool_ok(dcr); + } else { + Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId); + Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),