all Volumes from other drives.  "update slots all-drives"?
 
 Document:
+- Port limiting -m in iptables to prevent DoS attacks
+  could cause broken pipes on Bacula.
 - Document that Bootstrap files can be written with cataloging
   turned off.
 - Pruning with Admin job.
 - Document the multiple-drive-changer.txt script.
 
 For 1.37:
+- Cleaning tapes should have Status "Cleaning" rather than append.
 - Refuse to prune last valid Full backup. Same goes for Catalog.
 - Why is   SpoolDirectory = /home/bacula/spool;  not reported
   as an error when writing a DVD?
 - Add global lock on all devices when creating a device structure.
 
 Maybe in 1.37:
+- In restore don't compare byte count on a raw device -- directory
+  entry does not contain bytes.
 - To mark files as deleted, run essentially a Verify to disk, and
   when a file is found missing (MarkId != JobId), then create
   a new File record with FileIndex == -1. This could be done
 
 
 General:
 
+Changes to 1.37.28:
+29Jun05
+- Attempt to fix DVD writing by eliminating a number of the 
+  DVD subroutines to simplify.
+- Modify DEVICE::open() to take dcr as first argument. This
+  will permit providing more info to DVD opening.
+- Fix scanning for time/size items which in some cases
+  ate the next line.
+- Eliminate read_dvd_volume_label().  New code (not yet written)
+  *must* open dvd appropriately before calling 
+  read_dev_volume_label.
+- Modify open_first_part() open_next_part() to take DCR as 
+  argument.
+- Make label command from console work on DVDs.
+- Make mount command from console work on DVDs.
+  Unmount does not work yet.
+
 Changes to 1.37.27:
 27Jun05
 - Add Database vendor to CatalogRes tuple for Python.
 
     volstatus        text        not null
        check (volstatus in ('Full','Archive','Append',
              'Recycle','Purged','Read-Only','Disabled',
-             'Error','Busy','Used','Cleaning',"Scratch')),
+             'Error','Busy','Used','Cleaning','Scratch')),
     recycle          smallint    not null default 0,
     volretention      bigint     not null default 0,
     voluseduration    bigint     not null default 0,
 
  *
  *   Version $Id$
  */
-
 /*
-   Copyright (C) 2000-2005 Kern Sibbald
+   Copyright (C) 2002-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as ammended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
 
    if ((fd = fopen(fname, "r")) == NULL) {
       return NULL;
    }
-   Dmsg1(2000, "Open config file: %s\n", fname);
+   Dmsg1(400, "Open config file: %s\n", fname);
    nf = (LEX *)malloc(sizeof(LEX));
    if (lf) {
       memcpy(nf, lf, sizeof(LEX));
       }
       lf->line_no++;
       lf->col_no = 0;
+      Dmsg2(400, "fget line=%d %s", lf->line_no, lf->line);
    }
    lf->ch = (uint8_t)lf->line[lf->col_no];
    if (lf->ch == 0) {
 
    res_all.hdr.rcode = type;
    res_all.hdr.refcnt = 1;
 
+   /* Set defaults in each item */
    for (i=0; items[i].name; i++) {
       Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
             (items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
         scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
            lc->str, lc->line_no, lc->line);
      }
-     /* for each item not set, we copy the field from res */
-#ifdef xxx
-     for (int i=0; item->name;; i++, item++) {
-        if (bit_is_set(i, res->item_present)) {
-           Dmsg2(900, "Item %d is present in %s\n", i, res->name);
-        } else {
-           Dmsg2(900, "Item %d is not present in %s\n", i, res->name);
-        }
-     }
-     /* ***FIXME **** add code */
-#endif
    }
    scan_to_eol(lc);
 }
       scan_err1(lc, _("expected a size, got: %s"), lc->str);
       break;
    }
-   scan_to_eol(lc);
+   if (token != T_EOL) {
+      scan_to_eol(lc);
+   }
    set_bit(index, res_all.hdr.item_present);
    Dmsg0(900, "Leave store_size\n");
 }
                            return 0;
                         }
                      }
-                     Dmsg1(900, "calling handler for %s\n", items[i].name);
+                     Dmsg1(800, "calling handler for %s\n", items[i].name);
                      /* Call item handler */
                      items[i].handler(lc, &items[i], i, pass);
                      i = -1;
 
       Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
    }
    
-   dev->num_parts = dcr->VolCatInfo.VolCatParts;
-   
    for (i=0; i<5; i++) {
       dev->clear_labeled();              /* force reread of label */
       if (job_canceled(jcr)) {
        */
       for ( ; !dev->is_open(); ) {
          Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
-         if (dev->open(dcr->VolumeName, OPEN_READ_ONLY) < 0) {
+         if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
             if (dev->dev_errno == EIO) {   /* no tape loaded */
               Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
                     dev->print_name(), dcr->VolumeName, strerror_dev(dev));
          Dmsg1(129, "opened dev %s OK\n", dev->print_name());
       }
       
-      if (dev->is_dvd()) {
-         vol_label_status = read_dvd_volume_label(dcr, /*read*/false);
-      } else {
-         vol_label_status = read_dev_volume_label(dcr);
-      }
+      vol_label_status = read_dev_volume_label(dcr);
       
       Dmsg0(200, "calling read-vol-label\n");
       switch (vol_label_status) {
 
                jcr->dir_bsock->spool = false;
             }
          }
-         Dmsg0(350, "Enter bnet_get\n");
+         Dmsg0(650, "Enter bnet_get\n");
       }
-      Dmsg1(350, "End read loop with FD. Stat=%d\n", n);
+      Dmsg1(650, "End read loop with FD. Stat=%d\n", n);
       if (is_bnet_error(ds)) {
          Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds));
          Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
 
     bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName));
     memcpy(&dcr->VolCatInfo, &vol, sizeof(dcr->VolCatInfo));
 
+   /* ***FIXME*** we really should not do this but must for the moment */
+   if (dcr->dev->num_parts < dcr->VolCatInfo.VolCatParts) {
+      dcr->dev->num_parts = dcr->VolCatInfo.VolCatParts;
+   }
+
     Dmsg2(300, "do_reqest_vol_info got slot=%d Volume=%s\n",
           vol.Slot, vol.VolCatName);
     return true;
 
    }
    /* For we must now acquire the device for writing */
    lock_device(out_dev);
-   if (out_dev->open(out_jcr->dcr->VolumeName, OPEN_READ_WRITE) < 0) {
+   if (out_dev->open(out_jcr->dcr, OPEN_READ_WRITE) < 0) {
       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
       unlock_device(out_dev);
       exit(1);
 
    dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
    
    if (dev->is_dvd()) { /* Write the current (and last) part. */
-      open_next_part(dev);
+      open_next_part(dcr);
    }
    
    if (!dir_update_volume_info(dcr, false)) {
    if (!(dev->is_tape() || dev->is_fifo()) && dev->max_part_size > 0 &&
         (dev->part_size + block->binbuf) >= dev->max_part_size) {
       if (dev->part < dev->num_parts) {
-         Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
+         Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number"
+               " is less than the total number of parts (%d/%d, device=%s)\n"),
                dev->part, dev->num_parts, dev->print_name());
          dev->dev_errno = EIO;
          return false;
       }
       
-      if (open_next_part(dev) < 0) {
+      if (open_next_part(dcr) < 0) {
          Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
                 dev->print_name(), strerror_dev(dev));
          dev->dev_errno = EIO;
    Dmsg1(200, "dev->part_size=%u\n", (unsigned int)dev->part_size);
    Dmsg1(200, "dev->part=%u\n", (unsigned int)dev->part);
    Dmsg1(200, "dev->VolCatInfo.VolCatParts=%u\n", (unsigned int)dev->VolCatInfo.VolCatParts);
-   Dmsg3(200, "Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), ((dev->file_size-dev->part_start) == dev->part_size), (dev->part <= dev->VolCatInfo.VolCatParts));*/
+   Dmsg3(200, "Tests : %d %d %d\n", (dev->VolCatInfo.VolCatParts > 0), 
+         ((dev->file_size-dev->part_start) == dev->part_size), 
+         (dev->part <= dev->VolCatInfo.VolCatParts));*/
    /* Check for part file end */
    if ((dev->num_parts > 0) &&
         ((dev->file_size-dev->part_start) == dev->part_size) && 
         (dev->part < dev->num_parts)) {
-      if (open_next_part(dev) < 0) {
+      if (open_next_part(dcr) < 0) {
          Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
                dev->print_name(), strerror_dev(dev));
          dev->dev_errno = EIO;
 
    lock_device(dev);
    if (!dev->is_open()) {
       Dmsg1(200, "Opening device %s\n", dcr->VolumeName);
-      if (dev->open(dcr->VolumeName, OPEN_READ_WRITE) < 0) {
+      if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
          Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
          unlock_device(dev);
          free_block(block);
    }
 
    if (!dev->is_open()) {
-      if (!first_open_device(dev)) {
+      if (!first_open_device(dcr)) {
          Pmsg1(0, "Device open failed. ERR=%s\n", strerror_dev(dev));
       }
    }
 
          return NULL;
       }
    } else {
-      if (!first_open_device(dev)) {
-         Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dcr->dev_name);
+      if (!first_open_device(dcr)) {
+         Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
          return NULL;
       }
    }
 
 #endif
 
 /* Functions in dvd.c */ 
-void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name);
 void update_free_space_dev(DEVICE* dev);
 
 
 /* Forward referenced functions */
 void set_os_device_parameters(DEVICE *dev);
 static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat);
-static void open_tape_device(DEVICE *dev, int mode);
-static void open_file_device(DEVICE *dev, int mode);
-static void open_dvd_device(DEVICE *dev, int mode);
+static void open_tape_device(DCR *dcr, int mode);
+static void open_file_device(DCR *dcr, int mode);
+static void open_dvd_device(DCR *dcr, int mode);
 
 /*
  * Allocate and initialize the DEVICE structure
    } else if (S_ISFIFO(statp.st_mode)) {
       fifo = true;
    } else if (!(device->cap_bits & CAP_REQMOUNT)) {
-      Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory. st_mode=%x\n"),
+      Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n"
+            " or have RequiresMount=yes for DVD. st_mode=%x\n"),
          device->device_name, statp.st_mode);
       return NULL;
    }
  *    (archive_name) with the VolName concatenated.
  */
 int
-DEVICE::open(char *VolName, int mode)
+DEVICE::open(DCR *dcr, int mode)
 {
    if (is_open()) {
       if (openmode == mode) {
         ::close(fd); /* use system close so correct mode will be used on open */
       }
    }
-   if (VolName) {
-      bstrncpy(VolCatInfo.VolCatName, VolName, sizeof(VolCatInfo.VolCatName));
-   } else {
-      VolCatInfo.VolCatName[0] = 0;
-   }
+  bstrncpy(VolCatInfo.VolCatName, dcr->VolumeName, sizeof(VolCatInfo.VolCatName));
 
    Dmsg4(29, "open dev: tape=%d dev_name=%s vol=%s mode=%d\n", is_tape(),
          dev_name, VolCatInfo.VolCatName, mode);
    state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
    label_type = B_BACULA_LABEL;
    if (is_tape() || is_fifo()) {
-      open_tape_device(this, mode);
+      open_tape_device(dcr, mode);
    } else if (is_dvd()) {
       Dmsg1(100, "call open_dvd_device mode=%d\n", mode);
-      open_dvd_device(this, mode);
+      open_dvd_device(dcr, mode);
    } else {
       Dmsg1(100, "call open_file_device mode=%d\n", mode);
-      open_file_device(this, mode);
+      open_file_device(dcr, mode);
    }
    return fd;
 }
    }
 }
 
-static void open_tape_device(DEVICE *dev, int mode) 
+static void open_tape_device(DCR *dcr, int mode) 
 {
+   DEVICE *dev = dcr->dev;
    int nonblocking = 0;;
    dev->file_size = 0;
    int timeout;
 /*
  * Open a file device
  */
-static void open_file_device(DEVICE *dev, int mode) 
+static void open_file_device(DCR *dcr, int mode) 
 {
+   DEVICE *dev = dcr->dev;
    POOL_MEM archive_name(PM_FNAME);
 
    /*
       return;
    }
 
-   Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
-   get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+   pm_strcpy(archive_name, dev->dev_name);
+   if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
+      pm_strcat(archive_name, "/");
+   }
+   pm_strcat(archive_name, dev->VolCatInfo.VolCatName);
          
    Dmsg3(29, "open dev: %s dev=%s mode=%d\n", dev->is_dvd()?"DVD":"disk",
          archive_name.c_str(), mode);
 }
 
 /*
- * Open a DVD device
+ * Open a DVD device. N.B. at this point, dev->VolCatInfo.VolCatName
+ *  has the desired Volume name, but there is NO assurance that
+ *  any other field of VolCatInfo is correct.
  */
-static void open_dvd_device(DEVICE *dev, int mode) 
+static void open_dvd_device(DCR *dcr, int mode) 
 {
+   DEVICE *dev = dcr->dev;
    POOL_MEM archive_name(PM_FNAME);
    struct stat filestat;
 
    }
    dev->part_size = 0;
    
-   /* if num_parts has not been set, but VolCatInfo is available, copy
-    * it from the VolCatInfo.VolCatParts */
-   if (dev->num_parts < dev->VolCatInfo.VolCatParts) {
-      dev->num_parts = dev->VolCatInfo.VolCatParts;
-   }
-   
-   Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
-   get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+   Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
+   make_dvd_filename(dev, archive_name);
 
    if (mount_dev(dev, 1) < 0) {
       Mmsg(dev->errmsg, _("Could not mount device %s.\n"),
       struct stat statp;
       POOL_MEM archive_name(PM_FNAME);
       dev->part = dev->num_parts;
-      Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
-      get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+      Dmsg1(100, "Call make_dvd_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
+      make_dvd_filename(dev, archive_name);
       /* Check that the part file is empty */
       if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) {
          Dmsg1(100, "unlink(%s)\n", archive_name.c_str());
       /* maybe we should rewind and write and eof ???? */
    }
    
-   /* If there is more than one part, open the first one, and then truncate it. */
-   if (dev->num_parts > 0) {
-      dev->num_parts = 0;
-      dev->VolCatInfo.VolCatParts = 0;
-      if (open_first_part(dev, OPEN_READ_WRITE) < 0) {
-         berrno be;
-         Mmsg1(dev->errmsg, "Unable to truncate device, because I'm unable to open the first part. ERR=%s\n", be.strerror());
-      }
+   if (dev->is_dvd()) {
+      Mmsg1(dev->errmsg, _("Truncate DVD %s not supported.\n"), dev->print_name());
+      return false;   /* we cannot truncate DVDs */
    }
    
    if (ftruncate(dev->fd, 0) != 0) {
       berrno be;
-      Mmsg1(dev->errmsg, _("Unable to truncate device. ERR=%s\n"), be.strerror());
+      Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"), 
+            dev->print_name(), be.strerror());
       return false;
    }
    return true;
       Emsg0(M_FATAL, 0, dev->errmsg);
       return;
    }
+   Dmsg1(29, "term_dev: %s\n", dev->print_name());
    do_close(dev);
-   Dmsg0(29, "term_dev\n");
    if (dev->dev_name) {
       free_memory(dev->dev_name);
       dev->dev_name = NULL;
 
 int      weof_dev(DEVICE *dev, int num);
 bool     rewind_dev(DEVICE *dev);
 
+class DCR; /* forward reference */
 /*
  * Device structure definition. There is one of these for
  *  each physical device. Everything here is "global" to
    void block(int why); /* in dev.c */
    void unblock();      /* in dev.c */
    void close();        /* in dev.c */
-   int open(char *VolName, int mode); /* in dev.c */
+   int open(DCR *dcr, int mode); /* in dev.c */
    void set_mode(int mode); /* in dev.c */
 
    void set_blocked(int block) { dev_blocked = block; };
 
  *   Returns: false on failure
  *            true  on success
  */
-bool first_open_device(DEVICE *dev)
+bool first_open_device(DCR *dcr)
 {
+   DEVICE *dev = dcr->dev;
+
    Dmsg0(120, "start open_output_device()\n");
    if (!dev) {
       return false;
     }
    Dmsg0(129, "Opening device.\n");
    dev->open_nowait = true;
-   if (dev->open(NULL, mode) < 0) {
+   if (dev->open(dcr, mode) < 0) {
       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
       dev->open_nowait = false;
       unlock_device(dev);
    } else {
       mode = OPEN_READ_WRITE;
    }
-   if (dev->open(dcr->VolCatInfo.VolCatName, mode) < 0) {
+   if (dev->open(dcr, mode) < 0) {
       /* If polling, ignore the error */
       if (!dev->poll) {
          Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device %s: ERR=%s\n"),
 
 }
 
 /*
- * Label a tape
+ * Label a Volume
  *
  */
 static bool label_cmd(JCR *jcr)
    dcr->dev = dev;
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
 
+   /* Note, try_autoload_device() opens the device */
    if (!try_autoload_device(jcr, slot, newname)) {
       goto bail_out;                  /* error */
    }
 
    /* See what we have for a Volume */
-   if (dev->is_dvd()) {
-      label_status = read_dvd_volume_label(dcr, /*write*/true);
-   } else {
-      label_status = read_dev_volume_label(dcr);
-   }
+   label_status = read_dev_volume_label(dcr);
    
    switch(label_status) {
    case VOL_NAME_ERROR:
                                  "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
                              dev->print_name());
                }
-            } else {
-               if (!dev->is_tape()) {
-                  /* Nothing to do */
-                  break;
-               }
+            } else if (dev->is_tape()) {
                if (dev->open(NULL, OPEN_READ_WRITE) < 0) {
                   bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
                      strerror_dev(dev));
                                     "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
                              dev->print_name());
                }
+            } else if (dev->is_dvd()) {
+               if (mount_dev(dev, 1)) {
+                  bnet_fsend(dir, _("3002 Device %s is mounted.\n"), 
+                     dev->print_name());
+               } else {
+                  bnet_fsend(dir, "3907 %s", strerror_dev(dev));
+               } 
+            } else { /* must be file */
+               bnet_fsend(dir, _("3906 File device %s is always mounted.\n"),
+                  dev->print_name());
             }
             break;
 
 
    /* Ensure that the device is open -- autoload_device() closes it */
    for ( ; !dev->is_open(); ) {
-      if (dev->open(dcr->VolumeName, OPEN_READ_WRITE) < 0) {
+      if (dev->open(dcr, OPEN_READ_WRITE) < 0) {
          bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
             dev->print_name(), dev->strerror());
          return false;
 
 static bool do_mount_dev(DEVICE* dev, int mount, int dotimeout);
 static int dvd_write_part(DEVICE *dev);
 
-
 /* 
  * Write the current volume/part filename to archive_name.
  */
-void get_filename(DEVICE *dev, char *VolumeName, POOL_MEM& archive_name) 
+void make_dvd_filename(DEVICE *dev, POOL_MEM &archive_name) 
 {
    char partnumber[20];
    
-   if (dev->is_dvd()) {
-      /* If we try to open the last part, just open it from disk, 
-       * otherwise, open it from the spooling directory.
-       */
-      Dmsg2(100, "DVD part=%d num_parts=%d\n", dev->part, dev->num_parts);
-      if (dev->num_parts == 0 || dev->part < dev->num_parts) {
-         Dmsg1(100, "Arch = mount point: %s\n", dev->device->mount_point);
-         pm_strcpy(archive_name, dev->device->mount_point);
+   /*
+    * If we try to open the last part, just open it from disk, 
+    * otherwise, open it from the spooling directory.
+    */
+   Dmsg2(100, "DVD part=%d num_parts=%d\n", dev->part, dev->num_parts);
+   if (dev->part < dev->num_parts) {
+      Dmsg1(100, "Arch = mount point: %s\n", dev->device->mount_point);
+      pm_strcpy(archive_name, dev->device->mount_point);
+   } else {
+      /* Use the working directory if spool directory is not defined */
+      if (dev->device->spool_directory) {
+         pm_strcpy(archive_name, dev->device->spool_directory);
       } else {
-         /* Use the working directory if spool directory is not defined */
-         if (dev->device->spool_directory) {
-            Dmsg1(100, "Arch = spool: %s\n", dev->device->spool_directory);
-            pm_strcpy(archive_name, dev->device->spool_directory);
-         } else {
-            Dmsg1(100, "Arch = working: %s\n", working_directory);
-            pm_strcpy(archive_name, working_directory);
-         }
+         pm_strcpy(archive_name, working_directory);
       }
-   } else {
-      pm_strcpy(archive_name, dev->dev_name);
    }
       
    if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
       pm_strcat(archive_name, "/");
    }
-   pm_strcat(archive_name, VolumeName);
+
+   pm_strcat(archive_name, dev->VolCatInfo.VolCatName);
    /* if part != 0, append .# to the filename (where # is the part number) */
-   if (dev->is_dvd() && dev->part != 0) {
+   if (dev->part != 0) {
       pm_strcat(archive_name, ".");
       bsnprintf(partnumber, sizeof(partnumber), "%d", dev->part);
       pm_strcat(archive_name, partnumber);
    }
-   Dmsg1(100, "Exit get_filename: arch=%s\n", archive_name.c_str());
+   Dmsg1(100, "Exit make_dvd_filename: arch=%s\n", archive_name.c_str());
 }  
 
 /* Mount the device.
  *               opened.
  *               Maybe it should open the first part.  ***FIXME***
  *
- *         false if an error occured, and read_dvd_volume_label
+ *         false if an error occured, and read_dev_volume_label
  *               must abort with an IO_ERROR.
  *
  * To find the Volume name, it lists all the files on the DVD,
  * It is useful, so the operator can be told that a wrong volume is mounted, with
  * the label name of the current volume. We can also check that the currently
  * mounted disk is writable. (See also read_dev_volume_label_guess in label.c).
+
+   If we are writing, then there is no need to guess. We should just
+   check that the Volume does not already exist.
+
+   If we are reading, I don't see the reason to guess since we
+   know what Volume we want. The file either exists or does not
+   exist.
+
  *
  */
+#ifdef xxx
 bool can_open_mounted_dev(DEVICE *dev) 
 {
    Dmsg1(29, "Enter: dev=%s\n", dev->dev_name);
    
    return true;
 }
+#endif
 
 
 /* Update the free space on the device */
       
    status = run_program_full_output(ocmd.c_str(), timeout, results);
    if (status != 0) {
-      Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s", results);
+      Mmsg1(dev->errmsg, "Error while writing current part to the DVD: %s", 
+            results);
+      Dmsg1(000, "%s", dev->errmsg);
       dev->dev_errno = EIO;
       free_pool_memory(results);
       return -1;
    } else {
-      Dmsg1(29, "dvd_write_part: command output=%s\n", results);
+      Dmsg1(10, "dvd_write_part: command output=%s\n", results);
       POOL_MEM archive_name(PM_FNAME);
       Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
-      get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+      make_dvd_filename(dev, archive_name);
       unlink(archive_name.c_str());
       free_pool_memory(results);
       return 0;
  *  - Increment part number 
  *  - Reopen the device
  */
-int open_next_part(DEVICE *dev)
+int open_next_part(DCR *dcr)
 {
+   DEVICE *dev = dcr->dev;
       
    Dmsg3(29, "Enter: open_next_part %s %s %d\n", dev->dev_name, 
          dev->VolCatInfo.VolCatName, dev->openmode);
    dev->fd = -1;
    dev->clear_opened();
    
+   /*
+    * If we have a part open for write, then write it to
+    *  DVD before opening the next part.
+    */
    if (dev->is_dvd() && (dev->part == dev->num_parts) && dev->can_append()) {
       if (dvd_write_part(dev) < 0) {
          return -1;
    dev->part++;
    
    if ((dev->num_parts < dev->part) && dev->can_append()) {
-      dev->num_parts = dev->part;
-      
-      /* Check that the next part file does not exists.
-       * If it does, move it away... */
       POOL_MEM archive_name(PM_FNAME);
-      POOL_MEM archive_bkp_name(PM_FNAME);
       struct stat buf;
+
+      /* 
+       * First check what is on DVD.  If out part is there, we
+       *   are in trouble, so bail out.
+       */
+      make_dvd_filename(dev, archive_name);   /* makes dvd name */
+      if (stat(archive_name.c_str(), &buf) == 0) {
+         /* bad new bail out */
+         Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
+            archive_name.c_str());
+         return -1;
+      }
+
+      dev->num_parts = dev->part;
+      make_dvd_filename(dev, archive_name);   /* makes spool name */
       
-      Dmsg1(100, "Call get_filename. Vol=%s\n", dev->VolCatInfo.VolCatName);
-      get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
-      
-      /* Check if the next part exists. */
+      /* Check if the next part exists in spool directory . */
       if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
          Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
-         pm_strcpy(archive_bkp_name, archive_name.c_str());
-         pm_strcat(archive_bkp_name, ".bak");
-         unlink(archive_bkp_name.c_str()); 
-         
-         /* First try to rename it */
-         if (rename(archive_name.c_str(), archive_bkp_name.c_str()) < 0) {
+         /* Then try to unlink it */
+         if (unlink(archive_name.c_str()) < 0) {
             berrno be;
-            Dmsg3(29, "open_next_part can't rename %s to %s, ERR=%s\n", 
-                  archive_name.c_str(), archive_bkp_name.c_str(), be.strerror());
-            /* Then try to unlink it */
-            if (unlink(archive_name.c_str()) < 0) {
-               berrno be;
-               dev->dev_errno = errno;
-               Mmsg2(&dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), 
-                      archive_name.c_str(), be.strerror());
-               Emsg0(M_FATAL, 0, dev->errmsg);
-               return -1;
-            }
+            dev->dev_errno = errno;
+            Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), 
+                   archive_name.c_str(), be.strerror());
+            return -1;
          }
       }
    }
    
    Dmsg2(50, "Call dev->open(vol=%s, mode=%d", dev->VolCatInfo.VolCatName, 
          dev->openmode);
-   if (dev->open(dev->VolCatInfo.VolCatName, dev->openmode) < 0) {
+   /* Open next part */
+   if (dev->open(dcr, dev->openmode) < 0) {
       return -1;
    } 
+   dev->set_labeled();          /* all next parts are "labeled" */
    return dev->fd;
 }
 
  *  - Close the fd
  *  - Reopen the device
  */
-int open_first_part(DEVICE *dev, int mode)
+int open_first_part(DCR *dcr, int mode)
 {
+   DEVICE *dev = dcr->dev;
    Dmsg3(29, "Enter: open_first_part dev=%s Vol=%s mode=%d\n", dev->dev_name, 
          dev->VolCatInfo.VolCatName, dev->openmode);
    if (dev->fd >= 0) {
    dev->part_start = 0;
    dev->part = 0;
    
-   Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dev->VolCatInfo.VolCatName, 
+   Dmsg2(50, "Call dev->open(vol=%s, mode=%d)\n", dcr->VolCatInfo.VolCatName, 
          mode);
-   if (dev->open(dev->VolCatInfo.VolCatName, mode) < 0) {
+   if (dev->open(dcr, mode) < 0) {
       Dmsg0(50, "open dev() failed\n");
       return -1;
    }
 off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
 {
    int pos, openmode;
+   DCR *dcr;
    
    if (dev->num_parts == 0) { /* If there is only one part, simply call lseek. */
       return lseek(dev->fd, offset, whence);
    }
       
+   dcr = (DCR *)dev->attached_dcrs->first();  /* any dcr will do */
    switch(whence) {
    case SEEK_SET:
       Dmsg1(100, "lseek_dev SEEK_SET called %d\n", offset);
             }
          } else {
             /* Load next part, and start again */
-            if (open_next_part(dev) < 0) {
+            if (open_next_part(dcr) < 0) {
                Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
                return -1;
             }
           * We need to access a previous part, 
           * so just load the first one, and seek again
           * until the right one is loaded */
-         if (open_first_part(dev, dev->openmode) < 0) {
+         if (open_first_part(dcr, dev->openmode) < 0) {
             Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
             return -1;
          }
          openmode = dev->openmode;
          
          /* Works because num_parts > 0. */
-         if (open_first_part(dev, OPEN_READ_ONLY) < 0) {
+         if (open_first_part(dcr, OPEN_READ_ONLY) < 0) {
             Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
             return -1;
          }
          while (dev->part < (dev->num_parts-1)) {
-            if (open_next_part(dev) < 0) {
+            if (open_next_part(dcr) < 0) {
                Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
                return -1;
             }
          }
          dev->openmode = openmode;
-         if (open_next_part(dev) < 0) {
+         if (open_next_part(dcr) < 0) {
             Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
             return -1;
          }
          ok = false;
       }
       
-      if (ok && (open_next_part(dev) < 0)) {
+      if (ok && (open_next_part(dcr) < 0)) {
          Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
                dev->print_name(), strerror_dev(dev));
          dev->dev_errno = EIO;
    char add[20];
    
    POOL_MEM archive_name(PM_FNAME);
-   get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
 
    *omsg = 0;
    Dmsg1(800, "edit_device_codes: %s\n", imsg);
             str = dev->device->mount_point;
             break;
          case 'v':
+            make_dvd_filename(dev, archive_name);
             str = archive_name.c_str();
             break;
          default:
 
    return VOL_OK;
 }
 
-/* Read the volume label by guessing the volume name. (only for DVD devices)
- * write is true if we are reading the label before writing to the device.
- *
- * If the volume name cannot be guessed :
- *  Writing : returns the label of the current file (on the harddisk).
- *  Reading : returns an error
- */
-int read_dvd_volume_label(DCR *dcr, bool write) 
-{
-   int vol_label_status;
-   DEVICE *dev = dcr->dev;
-   JCR *jcr = dcr->jcr;
-   Dmsg3(100, "Enter: dvd_volume_label device=%s vol=%s dev_Vol=%s\n",
-         dev->print_name(), dcr->VolumeName, dev->VolHdr.VolumeName);
-   
-   if (!dev->is_dvd()) {  
-      Jmsg1(jcr, M_ABORT, 0, _("Device %s is not a DVD.\n"), dev->print_name());
-      return -1;    /* for compiler, won't get here */
-   }
-   
-   if (!write && (dcr->VolCatInfo.VolCatParts == 0)) {
-      Dmsg0(100, "Leave read_dvd_volume_label !writing, and VolCatParts == 0\n");
-      return read_dev_volume_label(dcr);
-   }
-   
-   /*
-    * For mounted devices, try to guess the Volume name
-    * and read the label if possible.
-    */
-   if (!can_open_mounted_dev(dev)) {     
-      if (!write || dcr->VolCatInfo.VolCatParts > 0) {
-         Mmsg2(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula labeled Volume."),
-               dev->print_name(), dcr->VolumeName);
-         Dmsg0(100, "Leave read_dvd_volume_label VOL_NO_LABEL (!open_mounted_dev)\n");
-         return VOL_NO_LABEL;
-      }
-      
-      /* At this point, we are writing */
-      if (dev->free_space_errno < 0) {
-         Dmsg0(100, "Exit: read_dvd_volume_label !free_space VOL_NO_MEDIA\n");
-         Mmsg2(jcr->errmsg, _("free_space error on %s. The current medium is probably not writable: ERR=%s.\n"),
-               dev->print_name(), dev->errmsg);
-         return VOL_NO_MEDIA;
-      }
-      
-      /* 
-       * If we can't guess the name, and we are writing, 
-       * just reopen the right file with open_first_part.
-       */
-      if (open_first_part(dev, OPEN_READ_WRITE) < 0) {
-         berrno be;
-         Mmsg2(jcr->errmsg, _("open_first_part error on %s: ERR=%s.\n"),
-               dev->print_name(), be.strerror());
-         Dmsg0(100, "Leave read_dvd_volume_label VOL_IO_ERROR (!open_mounted_dev && !open_first_part)\n");
-         return VOL_IO_ERROR;
-      }
-      
-      Dmsg0(100, "Leave read_dvd_volume_label !open_mounted_dev\n");
-      return read_dev_volume_label(dcr);
-
-   } else {
-      /* 
-       * If we get here, we can open the mounted device
-       */
-      if (write && dcr->dev->free_space_errno < 0) {
-         Dmsg0(100, "Leave read_dvd_volume_label !free_space VOL_NO_MEDIA\n");
-         Mmsg2(jcr->errmsg, _("free_space error on %s. The current medium is probably not writable: ERR=%s.\n"),
-               dev->print_name(), dev->errmsg);
-         return VOL_NO_MEDIA;
-      }
-      
-      if (!write || dcr->VolCatInfo.VolCatParts > 0) {
-         Dmsg0(100, "Exit: read_dvd_volume_label (open_mounted_dev && (!write || dcr->VolCatInfo.VolCatParts > 0))\n");
-         return read_dev_volume_label(dcr);
-      }
-      
-      /* At this point, we are writing */
-      if (open_first_part(dcr->dev, OPEN_READ_WRITE) < 0) {
-         berrno be;
-         Mmsg2(jcr->errmsg, _("open_first_part error on %s: ERR=%s.\n"),
-               dev->print_name(), be.strerror());
-         Dmsg0(100, "Leave read_dvd_volume_label VOL_IO_ERROR (open_mounted_dev && !open_first_part)\n");
-         return VOL_IO_ERROR;
-      }
-      vol_label_status = read_dev_volume_label(dcr);
-      
-      /* When writing, if the guessed volume name is not the right volume name, 
-       * report the error, otherwise, just continue with the right file.
-       */
-      if (vol_label_status != VOL_NAME_ERROR) {
-         Dmsg0(100, "Leave read_dvd_volume_label (open_mounted_dev && !VOL_NAME_ERROR)\n");
-         dev->clear_labeled();   
-         return read_dev_volume_label(dcr);
-      } else {
-         Dmsg0(100, "Leave read_dvd_volume_label (open_mounted_dev && VOL_NAME_ERROR)\n");
-         return vol_label_status;
-      }
-   }
-}
-
 /*
  * Put a volume label into the block
  *
 
    Dmsg3(100, "After find_next_append. Vol=%s Slot=%d Parts=%d\n",
          dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot, dcr->VolCatInfo.VolCatParts);
    
-   dev->num_parts = dcr->VolCatInfo.VolCatParts;
-
    /*
     * Get next volume and ready it for append
     * This code ensures that the device is ready for
       vol_label_status = VOL_OK;
       create_volume_label(dev, dcr->VolumeName, "Default");
       dev->VolHdr.LabelType = PRE_LABEL;
-   } else if (dev->is_dvd()) {
-      vol_label_status = read_dvd_volume_label(dcr, /*write*/true);
    } else {
       vol_label_status = read_dev_volume_label(dcr);
    }
 
 /* From dev.c */
 DEVICE  *init_dev(JCR *jcr, DEVRES *device);
 off_t    lseek_dev(DEVICE *dev, off_t offset, int whence);
-int      open_first_part(DEVICE *dev, int mode);
-int      open_next_part(DEVICE *dev);
+int      open_first_part(DCR *dcr, int mode);
+int      open_next_part(DCR *dcr);
 bool     can_open_mounted_dev(DEVICE *dev);
 bool     truncate_dev(DEVICE *dev);
 void     term_dev(DEVICE *dev);
 bool mount_dev(DEVICE* dev, int timeout);
 bool unmount_dev(DEVICE* dev, int timeout);
 void update_free_space_dev(DEVICE *dev);
-void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name);
+void make_dvd_filename(DEVICE *dev, POOL_MEM &archive_name);
 
 /* From device.c */
 bool     open_device(DCR *dcr);
 void     close_device(DEVICE *dev);
 void     force_close_device(DEVICE *dev);
-bool     first_open_device(DEVICE *dev);
+bool     first_open_device(DCR *dcr);
 bool     fixup_device_block_write_error(DCR *dcr);
 void     _lock_device(const char *file, int line, DEVICE *dev);
 void     _unlock_device(const char *file, int line, DEVICE *dev);
 
     * List devices
     */
    bnet_fsend(user, _("\nDevice status:\n"));
-// LockRes();
    foreach_res(changer, R_AUTOCHANGER) {
       bnet_fsend(user, _("Autochanger \"%s\" with devices:\n"),
          changer->hdr.name);
          send_blocked_status(jcr, dev);
       }
    }
-// UnlockRes();
    bnet_fsend(user, "====\n\n");
    bnet_fsend(user, "Volume status:\n");
    list_volumes(user);
    DCR *dcr = jcr->dcr;
 
    if (!dev) {
+      bnet_fsend(user, "No DEVICE structure.\n\n");
       return;
    }
    switch (dev->dev_blocked) {
       bnet_fsend(user, "%sALWAYSOPEN ", dev->capabilities & CAP_ALWAYSOPEN ? "" : "!");
       bnet_fsend(user, "\n");
 
-      bnet_fsend(user, _("Device status:\n"));
+      bnet_fsend(user, _("Device state:\n"));
       bnet_fsend(user, "%sOPENED ", dev->is_open() ? "" : "!");
       bnet_fsend(user, "%sTAPE ", dev->is_tape() ? "" : "!");
       bnet_fsend(user, "%sLABEL ", dev->is_labeled() ? "" : "!");
       bnet_fsend(user, "%sSHORT ", dev->state & ST_SHORT ? "" : "!");
       bnet_fsend(user, "%sMOUNTED ", dev->state & ST_MOUNTED ? "" : "!");
       bnet_fsend(user, "\n");
-      bnet_fsend(user, "num_writers=%d JobStatus=%c block=%d\nn", dev->num_writers,
+      bnet_fsend(user, "num_writers=%d JobStatus=%c block=%d\n\n", dev->num_writers,
          jcr->JobStatus, dev->dev_blocked);
 
       bnet_fsend(user, _("Device parameters:\n"));
 
    bool OK = true;
    AUTOCHANGER *changer;
 
-// LockRes();
 
    me = (STORES *)GetNextRes(R_STORAGE, NULL);
    if (!me) {
 void *device_initialization(void *arg)
 {
    DEVRES *device;
+   DCR *dcr;
+   JCR *jcr;
+   DEVICE *dev;
 
    LockRes();
+
    pthread_detach(pthread_self());
+   jcr = new_jcr(sizeof(JCR), stored_free_jcr);
+   jcr->JobType = JT_SYSTEM;
+   /* Initialize FD start condition variable */
+   int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
+   if (errstat != 0) {
+      Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
+   }
 
    foreach_res(device, R_DEVICE) {
       Dmsg1(90, "calling init_dev %s\n", device->device_name);
-      device->dev = init_dev(NULL, device);
+      device->dev = dev = init_dev(NULL, device);
       Dmsg1(10, "SD init done %s\n", device->device_name);
-      if (!device->dev) {
+      if (!dev) {
          Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
          continue;
       }
 
+      dcr = new_dcr(jcr, dev);
+
       if (device->cap_bits & CAP_ALWAYSOPEN) {
-         Dmsg1(20, "calling first_open_device %s\n", device->device_name);
-         if (!first_open_device(device->dev)) {
-            Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), device->device_name);
+         Dmsg1(20, "calling first_open_device %s\n", dev->print_name());
+         if (!first_open_device(dcr)) {
+            Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name());
+            Dmsg1(20, "Could not open device %s\n", dev->print_name());
+            term_dev(dev);
+            device->dev = NULL;
+            free_dcr(dcr);
+            continue;
          }
       }
-      if (device->cap_bits & CAP_AUTOMOUNT && device->dev &&
-          device->dev->is_open()) {
-         JCR *jcr;
-         DCR *dcr;
-         jcr = new_jcr(sizeof(JCR), stored_free_jcr);
-         jcr->JobType = JT_SYSTEM;
-         /* Initialize FD start condition variable */
-         int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
-         if (errstat != 0) {
-            Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
-         }
-         dcr = new_dcr(jcr, device->dev);
+      if (device->cap_bits & CAP_AUTOMOUNT && dev->is_open()) {
          switch (read_dev_volume_label(dcr)) {
          case VOL_OK:
-            memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo));
+            memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
             break;
          default:
-            Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), device->device_name);
+            Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), dev->print_name());
             break;
          }
-         free_jcr(jcr);
       }
+      free_dcr(dcr);
    }
+   free_jcr(jcr); 
    UnlockRes();
    return NULL;
 }
    Dmsg1(200, "In terminate_stored() sig=%d\n", sig);
 
    foreach_res(device, R_DEVICE) {
+      Dmsg1(10, "Term device %s\n", device->device_name);
       if (device->dev) {
          free_volume(device->dev);
          term_dev(device->dev);
+      } else {
+         Dmsg1(10, "No dev structure %s\n", device->device_name);
       }
    }
 
 
    {"blockpositioning",      store_yesno,  ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
    {"usemtiocget",           store_yesno,  ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
    {"checklabels",           store_yesno,  ITEM(res_dev.cap_bits), CAP_CHECKLABELS, ITEM_DEFAULT, 0},
+   {"requiresmount",         store_yesno,  ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
+   {"offlineonunmount",      store_yesno,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
    {"autoselect",            store_yesno,  ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
    {"changerdevice",         store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
    {"changercommand",        store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
    {"maximumopenvolumes",    store_pint,   ITEM(res_dev.max_open_vols), 0, ITEM_DEFAULT, 1},
    {"maximumnetworkbuffersize", store_pint, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
    {"volumepollinterval",    store_time,   ITEM(res_dev.vol_poll_interval), 0, 0, 0},
-   {"offlineonunmount",      store_yesno,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
    {"maximumrewindwait",     store_pint,   ITEM(res_dev.max_rewind_wait), 0, ITEM_DEFAULT, 5 * 60},
    {"minimumblocksize",      store_pint,   ITEM(res_dev.min_block_size), 0, 0, 0},
    {"maximumblocksize",      store_pint,   ITEM(res_dev.max_block_size), 0, 0, 0},
    {"maximumjobspoolsize",   store_size,   ITEM(res_dev.max_job_spool_size), 0, 0, 0},
    {"driveindex",            store_pint,   ITEM(res_dev.drive_index), 0, 0, 0},
    {"maximumpartsize",       store_size,   ITEM(res_dev.max_part_size), 0, ITEM_DEFAULT, 0},
-   {"requiresmount",         store_yesno,  ITEM(res_dev.cap_bits), CAP_REQMOUNT, ITEM_DEFAULT, 0},
    {"mountpoint",            store_strname,ITEM(res_dev.mount_point), 0, 0, 0},
    {"mountcommand",          store_strname,ITEM(res_dev.mount_command), 0, 0, 0},
    {"unmountcommand",        store_strname,ITEM(res_dev.unmount_command), 0, 0, 0},
 void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
 {
    URES *res = (URES *)reshdr;
-   char buf[MAXSTRING];
+   char buf[1000];
    int recurse = 1;
    IPADDR *p;
    if (res == NULL) {
       if (res->res_dev.cap_bits & CAP_CHECKLABELS) {
          bstrncat(buf, "CAP_CHECKLABELS ", sizeof(buf));
       }
+      if (res->res_dev.cap_bits & CAP_REQMOUNT) {
+         bstrncat(buf, "CAP_REQMOUNT ", sizeof(buf));
+      }
+      if (res->res_dev.cap_bits & CAP_OFFLINEUNMOUNT) {
+         bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf));
+      }
       bstrncat(buf, "\n", sizeof(buf));
       sendit(sock, buf);
       break;
 
 /* */
 #undef  VERSION
-#define VERSION "1.37.26"
-#define BDATE   "26 June 2005"
-#define LSMDATE "26Jun05"
+#define VERSION "1.37.28"
+#define BDATE   "29 June 2005"
+#define LSMDATE "29Jun05"
 
 /* Debug flags */
 #undef  DEBUG