]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/dvd.c
Fix automatic labeling of File volumes, which was broken by new
[bacula/bacula] / bacula / src / stored / dvd.c
index 5ee722c81eb256b90f3fd6976f0e297b4aa281dc..8cb740e3c0d15fbcc71de688a54edbed57fd94db 100644 (file)
@@ -8,25 +8,37 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2005-2006 Kern Sibbald
+   Bacula® - The Network Backup Solution
 
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
+   Copyright (C) 2005-2006 Free Software Foundation Europe e.V.
 
-   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 
-   the file LICENSE for additional details.
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
 
- */
+   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., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 
 #include "bacula.h"
 #include "stored.h"
 
 /* Forward referenced functions */
-static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout);
 static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name);
 
 /* 
@@ -53,7 +65,7 @@ static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
 {
    char partnumber[20];
 
-   if (archive_name.c_str()[strlen(archive_name.c_str())-1] != '/') {
+   if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
       pm_strcat(archive_name, "/");
    }
 
@@ -68,190 +80,8 @@ static void add_file_and_part_name(DEVICE *dev, POOL_MEM &archive_name)
                   archive_name.c_str(), dev->part);
 }  
 
-/* Mount the device.
- * If timeout, wait until the mount command returns 0.
- * If !timeout, try to mount the device only once.
- */
-bool mount_dvd(DEVICE* dev, int timeout) 
-{
-   Dmsg0(90, "Enter mount_dvd\n");
-   if (dev->is_mounted()) {
-      return true;
-   } else if (dev->requires_mount()) {
-      return do_mount_dvd(dev, 1, timeout);
-   }       
-   return true;
-}
-
-/* Unmount the device
- * If timeout, wait until the unmount command returns 0.
- * If !timeout, try to unmount the device only once.
- */
-bool unmount_dvd(DEVICE *dev, int timeout) 
-{
-   if (!dev->is_dvd()) {
-      return true;
-   }
-   Dmsg0(90, "Enter unmount_dvd\n");
-   if (dev->is_mounted()) {
-      return do_mount_dvd(dev, 0, timeout);
-   }
-   return true;
-}
-
-/* (Un)mount the device */
-static bool do_mount_dvd(DEVICE* dev, int mount, int dotimeout) 
-{
-   POOL_MEM ocmd(PM_FNAME);
-   POOLMEM *results;
-   char *icmd;
-   int status, timeout;
-   
-   sm_check(__FILE__, __LINE__, false);
-   if (mount) {
-      if (dev->is_mounted()) {
-         Dmsg0(200, "======= DVD mount=1\n");
-         return true;
-      }
-      icmd = dev->device->mount_command;
-   } else {
-      if (!dev->is_mounted()) {
-         Dmsg0(200, "======= DVD mount=0\n");
-         return true;
-      }
-      icmd = dev->device->unmount_command;
-   }
-   
-   dev->edit_mount_codes(ocmd, icmd);
-   
-   Dmsg2(200, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!dev->is_mounted());
-
-   if (dotimeout) {
-      /* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
-      timeout = 1;
-   } else {
-      timeout = 0;
-   }
-   results = get_memory(2000);
-   results[0] = 0;
-   /* If busy retry each second */
-   Dmsg1(20, "Run mount prog=%s\n", ocmd.c_str());
-   while ((status = run_program_full_output(ocmd.c_str(), 
-                       dev->max_open_wait/2, results)) != 0) {
-      Dmsg2(20, "Mount status=%d result=%s\n", status, results);
-      /* Doesn't work with internationalization (This is not a problem) */
-      if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
-         break;
-      }
-      if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
-         break;
-      }
-      if (timeout-- > 0) {
-         /* Sometimes the device cannot be mounted because it is already mounted.
-          * Try to unmount it, then remount it */
-         if (mount) {
-            Dmsg1(400, "Trying to unmount the device %s...\n", dev->print_name());
-            do_mount_dvd(dev, 0, 0);
-         }
-         bmicrosleep(1, 0);
-         continue;
-      }
-      if (status != 0) {
-         berrno be;
-         Dmsg5(40, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", dev->print_name(),
-              (mount ? "" : "un"), status, results, be.strerror(status));
-         Mmsg(dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"), 
-              dev->print_name(), (mount ? "" : "un"), be.strerror(status));
-      } else {
-         Dmsg4(40, "Device %s cannot be %smounted. stat=%d ERR=%s\n", dev->print_name(),
-              (mount ? "" : "un"), status, results);
-         Mmsg(dev->errmsg, _("Device %s cannot be %smounted. ERR=%s\n"), 
-              dev->print_name(), (mount ? "" : "un"), results);
-      }
-      /*
-       * Now, just to be sure it is not mounted, try to read the
-       *  filesystem.
-       */
-      DIR* dp;
-      struct dirent *entry, *result;
-      int name_max;
-      int count;
-      
-      name_max = pathconf(".", _PC_NAME_MAX);
-      if (name_max < 1024) {
-         name_max = 1024;
-      }
-         
-      if (!(dp = opendir(dev->device->mount_point))) {
-         berrno be;
-         dev->dev_errno = errno;
-         Dmsg3(29, "do_mount_dvd: failed to open dir %s (dev=%s), ERR=%s\n", 
-               dev->device->mount_point, dev->print_name(), be.strerror());
-         goto get_out;
-      }
-      
-      entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
-      count = 0;
-      while (1) {
-         if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
-            dev->dev_errno = EIO;
-            Dmsg2(129, "do_mount_dvd: failed to find suitable file in dir %s (dev=%s)\n", 
-                  dev->device->mount_point, dev->print_name());
-            break;
-         }
-         if (strcmp(result->d_name, ".") && strcmp(result->d_name, "..") && 
-             strcmp(result->d_name, ".keep")) {
-            count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
-            Dmsg1(100, "Inc count=%d\n", count);
-            break;
-         } else {
-            Dmsg2(129, "do_mount_dvd: ignoring %s in %s\n", 
-                  result->d_name, dev->device->mount_point);
-         }
-      }
-      free(entry);
-      closedir(dp);
-      
-      Dmsg1(29, "do_mount_dvd: got %d files in the mount point (not counting ., .. and .keep)\n", count);
-      
-      if (count > 0) {
-         /* If we got more than ., .. and .keep */
-         /*   there must be something mounted */
-         if (mount) {
-            Dmsg1(100, "Did Mount by count=%d\n", count);
-            break;
-         } else {
-            /* An unmount request. We failed to unmount - report an error */
-            dev->set_mounted(true);
-            free_pool_memory(results);
-            Dmsg0(200, "== DVD mount=1\n");
-            return false;
-         }
-      }
-get_out:
-      dev->set_mounted(false);
-      sm_check(__FILE__, __LINE__, false);
-      free_pool_memory(results);
-      Dmsg0(200, "== DVD mount=0\n");
-      return false;
-   }
-   Dmsg0(100, "Out of mount/umount loop\n");
-   
-   dev->set_mounted(mount);              /* set/clear mounted flag */
-   free_pool_memory(results);
-   /* Do not check free space when unmounting */
-   if (mount) {
-      Dmsg0(100, "Calling update_free_space\n");
-      if (!update_free_space_dev(dev)) {
-         return false;
-      }
-   }
-   Dmsg1(200, "== DVD mount=%d\n", mount);
-   return true;
-}
-
 /* Update the free space on the device */
-bool update_free_space_dev(DEVICE* dev
+bool DEVICE::update_freespace(
 {
    POOL_MEM ocmd(PM_FNAME);
    POOLMEM* results;
@@ -262,30 +92,30 @@ bool update_free_space_dev(DEVICE* dev)
    bool ok = false;
    int status;
 
-   if (!dev->is_dvd() || dev->is_freespace_ok()) {
+   if (!is_dvd() || is_freespace_ok()) {
       return true;
    }
    
    /* The device must be mounted in order to dvd-freespace to work */
-   mount_dvd(dev, 1);
+   mount(1);
    
    sm_check(__FILE__, __LINE__, false);
-   icmd = dev->device->free_space_command;
+   icmd = device->free_space_command;
    
    if (!icmd) {
-      dev->free_space = 0;
-      dev->free_space_errno = 0;
-      dev->clear_freespace_ok();              /* No valid freespace */
-      dev->clear_media();
+      free_space = 0;
+      free_space_errno = 0;
+      clear_freespace_ok();              /* No valid freespace */
+      clear_media();
       Dmsg2(29, "ERROR: update_free_space_dev: free_space=%s, free_space_errno=%d (!icmd)\n", 
-            edit_uint64(dev->free_space, ed1), dev->free_space_errno);
-      Mmsg(dev->errmsg, _("No FreeSpace command defined.\n"));
+            edit_uint64(free_space, ed1), free_space_errno);
+      Mmsg(errmsg, _("No FreeSpace command defined.\n"));
       return false;
    }
    
-   dev->edit_mount_codes(ocmd, icmd);
+   edit_mount_codes(ocmd, icmd);
    
-   Dmsg1(29, "update_free_space_dev: cmd=%s\n", ocmd.c_str());
+   Dmsg1(29, "update_freespace: cmd=%s\n", ocmd.c_str());
 
    results = get_pool_memory(PM_MESSAGE);
    
@@ -295,47 +125,47 @@ bool update_free_space_dev(DEVICE* dev)
    while (1) {
       berrno be;
       Dmsg1(20, "Run freespace prog=%s\n", ocmd.c_str());
-      status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results);
-      Dmsg2(20, "Freespace status=%d result=%s\n", status, results);
+      status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results);
+      Dmsg2(500, "Freespace status=%d result=%s\n", status, results);
       if (status == 0) {
          free = str_to_int64(results);
          Dmsg1(400, "Free space program run: Freespace=%s\n", results);
          if (free >= 0) {
-            dev->free_space = free;
-            dev->free_space_errno = 0;
-            dev->set_freespace_ok();     /* have valid freespace */
-            dev->set_media();
-            Mmsg(dev->errmsg, "");
+            free_space = free;
+            free_space_errno = 0;
+            set_freespace_ok();     /* have valid freespace */
+            set_media();
+            Mmsg(errmsg, "");
             ok = true;
             break;
          }
       }
-      dev->free_space = 0;
-      dev->free_space_errno = EPIPE;
-      dev->clear_freespace_ok();         /* no valid freespace */
-      Mmsg2(dev->errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"), 
+      free_space = 0;
+      free_space_errno = EPIPE;
+      clear_freespace_ok();         /* no valid freespace */
+      Mmsg2(errmsg, _("Cannot run free space command. Results=%s ERR=%s\n"), 
             results, be.strerror(status));
       
       if (--timeout > 0) {
          Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
-            "free_space_errno=%d ERR=%s\n", dev->print_name(), 
-               edit_uint64(dev->free_space, ed1), dev->free_space_errno, 
-               dev->errmsg);
+            "free_space_errno=%d ERR=%s\n", print_name(), 
+               edit_uint64(free_space, ed1), free_space_errno, 
+               errmsg);
          bmicrosleep(1, 0);
          continue;
       }
 
-      dev->dev_errno = dev->free_space_errno;
+      dev_errno = free_space_errno;
       Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
          "free_space_errno=%d ERR=%s\n",
-            dev->print_name(), edit_uint64(dev->free_space, ed1),
-            dev->free_space_errno, dev->errmsg);
+            print_name(), edit_uint64(free_space, ed1),
+            free_space_errno, errmsg);
       break;
    }
    
    free_pool_memory(results);
-   Dmsg4(29, "leave update_free_space_dev: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n", 
-      edit_uint64(dev->free_space, ed1), !!dev->is_freespace_ok(), dev->free_space_errno, !!dev->have_media());
+   Dmsg4(29, "leave update_freespace: free_space=%s freespace_ok=%d free_space_errno=%d have_media=%d\n", 
+      edit_uint64(free_space, ed1), !!is_freespace_ok(), free_space_errno, !!have_media());
    sm_check(__FILE__, __LINE__, false);
    return ok;
 }
@@ -357,9 +187,8 @@ bool dvd_write_part(DCR *dcr)
    DEVICE *dev = dcr->dev;
    POOL_MEM archive_name(PM_FNAME);
    
-   dev->clear_freespace_ok();             /* need to update freespace */
-
-   /* Don't write empty part files.
+   /*
+    * Don't write empty part files.
     * This is only useful when growisofs does not support write beyond
     * the 4GB boundary.
     * Example :
@@ -371,7 +200,6 @@ bool dvd_write_part(DCR *dcr)
     *   - Bacula thinks he must finish to write to the device, so it
     *     tries to write the last part (0-byte), but dvd-writepart fails...
     *
-    *  ***FIXME****  we cannot write a blank part!!!!!!!
     * There is one exception: when recycling a volume, we write a blank part
     * file, so, then, we need to accept to write it.
     */
@@ -381,7 +209,7 @@ bool dvd_write_part(DCR *dcr)
       make_spooled_dvd_filename(dev, archive_name);
       unlink(archive_name.c_str());
       dev->set_part_spooled(false);
-      Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
+      Dmsg1(29, "========= unlink(%s)\n", archive_name.c_str());
       sm_check(__FILE__, __LINE__, false);
       return true;
    }
@@ -393,6 +221,8 @@ bool dvd_write_part(DCR *dcr)
    int timeout;
    char ed1[50];
    
+   dev->clear_freespace_ok();             /* need to update freespace */
+
    sm_check(__FILE__, __LINE__, false);
    Dmsg3(29, "dvd_write_part: device is %s, part is %d, is_mounted=%d\n", dev->print_name(), dev->part, dev->is_mounted());
    icmd = dev->device->write_part_command;
@@ -433,7 +263,7 @@ bool dvd_write_part(DCR *dcr)
          dev->part, results.c_str());
       Mmsg1(dev->errmsg, _("Error while writing current part to the DVD: %s"), 
             results.c_str());
-      Dmsg1(000, "%s\n", dev->errmsg);
+      Dmsg1(100, "%s\n", dev->errmsg);
       dev->dev_errno = EIO;
       if (!dev->truncating) {
          mark_volume_in_error(dcr);
@@ -448,18 +278,18 @@ bool dvd_write_part(DCR *dcr)
    dev->num_dvd_parts++;            /* there is now one more part on DVD */
    dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
    dcr->VolCatInfo.VolCatParts = dev->num_dvd_parts;
-   Dmsg1(000, "Update num_parts=%d\n", dev->num_dvd_parts);
+   Dmsg1(100, "Update num_parts=%d\n", dev->num_dvd_parts);
 
    /* Delete spool file */
    make_spooled_dvd_filename(dev, archive_name);
    unlink(archive_name.c_str());
    dev->set_part_spooled(false);
-   Dmsg1(29, "unlink(%s)\n", archive_name.c_str());
+   Dmsg1(29, "========= unlink(%s)\n", archive_name.c_str());
    sm_check(__FILE__, __LINE__, false);
    
    /* growisofs umounted the device, so remount it (it will update the free space) */
    dev->clear_mounted();
-   mount_dvd(dev, 1);
+   dev->mount(1);
    Jmsg(dcr->jcr, M_INFO, 0, _("Remaining free space %s on %s\n"), 
       edit_uint64_with_commas(dev->free_space, ed1), dev->print_name());
    sm_check(__FILE__, __LINE__, false);
@@ -480,7 +310,7 @@ int dvd_open_next_part(DCR *dcr)
       dev->part, dev->num_dvd_parts, dev->print_name(),
          dev->VolCatInfo.VolCatName, dev->openmode, dev->file_addr);
    if (!dev->is_dvd()) {
-      Dmsg1(000, "Device %s is not dvd!!!!\n", dev->print_name()); 
+      Dmsg1(100, "Device %s is not dvd!!!!\n", dev->print_name()); 
       return -1;
    }
    
@@ -570,7 +400,7 @@ int dvd_open_next_part(DCR *dcr)
  *  - Close the fd
  *  - Reopen the device
  */
-int dvd_open_first_part(DCR *dcr, int mode)
+static bool dvd_open_first_part(DCR *dcr, int mode)
 {
    DEVICE *dev = dcr->dev;
 
@@ -588,21 +418,21 @@ int dvd_open_first_part(DCR *dcr, int mode)
 
    if (dev->open(dcr, mode) < 0) {
       Dmsg0(400, "open dev() failed\n");
-      return -1;
+      return false;
    }
    Dmsg2(400, "Leave open_first_part state=%s append=%d\n", dev->is_open()?"open":"not open", dev->can_append());
    
-   return dev->fd;
+   return true;
 }
 
 
 /* 
  * Do an lseek on a DVD handling all the different parts
  */
-off_t lseek_dvd(DCR *dcr, off_t offset, int whence)
+boffset_t lseek_dvd(DCR *dcr, boffset_t offset, int whence)
 {
    DEVICE *dev = dcr->dev;
-   off_t pos;
+   boffset_t pos;
    char ed1[50], ed2[50];
    
    Dmsg5(400, "Enter lseek_dvd fd=%d off=%s w=%d part=%d nparts=%d\n", dev->fd,
@@ -616,7 +446,12 @@ off_t lseek_dvd(DCR *dcr, off_t offset, int whence)
          if ((uint64_t)offset == dev->part_start || 
              (uint64_t)offset < dev->part_start+dev->part_size) {
             /* We are staying in the current part, just seek */
-            if ((pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET)) < 0) {
+#if defined(HAVE_WIN32)
+            pos = _lseeki64(dev->fd, offset-dev->part_start, SEEK_SET);
+#else
+            pos = lseek(dev->fd, offset-dev->part_start, SEEK_SET);
+#endif
+            if (pos < 0) {
                return pos;
             } else {
                return pos + dev->part_start;
@@ -640,7 +475,7 @@ off_t lseek_dvd(DCR *dcr, off_t offset, int whence)
           * until the right one is loaded
           */
          Dmsg0(100, "lseek open first part\n");
-         if (dvd_open_first_part(dcr, dev->openmode) < 0) {
+         if (!dvd_open_first_part(dcr, dev->openmode)) {
             Dmsg0(400, "lseek_dvd failed while trying to open the first part\n");
             return -1;
          }
@@ -699,7 +534,7 @@ off_t lseek_dvd(DCR *dcr, off_t offset, int whence)
           * (useful for DVDs) 
           */
          int modesave = dev->openmode;
-         if (dvd_open_first_part(dcr, OPEN_READ_ONLY) < 0) {
+         if (!dvd_open_first_part(dcr, OPEN_READ_ONLY)) {
             Dmsg0(400, "lseek_dvd failed while trying to open the first part\n");
             return -1;
          }
@@ -793,14 +628,25 @@ bool truncate_dvd(DCR *dcr)
 {
    DEVICE* dev = dcr->dev;
 
+   dev->clear_freespace_ok();             /* need to update freespace */
    dev->close_part(dcr);
 
-   if (!unmount_dvd(dev, 1)) {
+   if (!dev->unmount(1)) {
       Dmsg0(400, "truncate_dvd: Failed to unmount DVD\n");
       return false;
    }
 
+   /* If necessary, delete its spool file. */
+   if (dev->is_part_spooled()) {
+      POOL_MEM archive_name(PM_FNAME);
+      /* Delete spool file */
+      make_spooled_dvd_filename(dev, archive_name);
+      unlink(archive_name.c_str());
+      dev->set_part_spooled(false);
+   }
+
    /* Set num_dvd_parts to zero (on disk) */
+   dev->part = 0;
    dev->num_dvd_parts = 0;
    dcr->VolCatInfo.VolCatParts = 0;
    dev->VolCatInfo.VolCatParts = 0;
@@ -808,31 +654,20 @@ bool truncate_dvd(DCR *dcr)
    Dmsg0(400, "truncate_dvd: Opening first part (1)...\n");
    
    dev->truncating = true;
-   if (dvd_open_first_part(dcr, CREATE_READ_WRITE) < 0) {
+   /* This creates a zero length spool file and sets part=1 */
+   if (!dvd_open_first_part(dcr, CREATE_READ_WRITE)) {
       Dmsg0(400, "truncate_dvd: Error while opening first part (1).\n");
       dev->truncating = false;
       return false;
    }
 
-   Dmsg0(400, "truncate_dvd: Truncating...\n");
-
-   /* If necessary, truncate it spool file. */
-   if (ftruncate(dev->fd, 0) != 0) {
-      berrno be;
-      Mmsg2(dev->errmsg, _("Unable to truncate device %s. ERR=%s\n"), 
-         dev->print_name(), be.strerror());
-      dev->truncating = false;
-      return false;
-   }
-   
    dev->close_part(dcr);
    
    Dmsg0(400, "truncate_dvd: Opening first part (2)...\n");
    
    /* 
-    * Now actually truncate the DVD
-    *  This is really kludgy, why not an argument or a separate
-    *  subroutine?  KES
+    * Now actually truncate the DVD which is done by writing
+    *  a zero length part to the DVD/
     */
    if (!dvd_write_part(dcr)) {
       Dmsg0(400, "truncate_dvd: Error while writing to DVD.\n");
@@ -842,6 +677,7 @@ bool truncate_dvd(DCR *dcr)
    dev->truncating = false;
    
    /* Set num_dvd_parts to zero (on disk) */
+   dev->part = 0;
    dev->num_dvd_parts = 0;
    dcr->VolCatInfo.VolCatParts = 0;
    dev->VolCatInfo.VolCatParts = 0;
@@ -849,30 +685,22 @@ bool truncate_dvd(DCR *dcr)
    dev->VolCatInfo.VolCatBytes = 0;
    dcr->VolCatInfo.VolCatBytes = 0;
 
-#ifdef xxx
    /* Update catalog */
    if (!dir_update_volume_info(dcr, false)) {
       return false;
    }
-#endif
    
-   if (dvd_open_first_part(dcr, OPEN_READ_WRITE) < 0) {
-      Dmsg0(400, "truncate_dvd: Error while opening first part (2).\n");
-      return false;
-   }
-
    return true;
 }
 
-/* Checks if we can write on a non-blank DVD: meaning that it just have been
- * truncated (there is only one zero-sized file on the DVD, with the right
- * volume name).   
+/*
+ * Checks if we can write on a non-blank DVD: meaning that it just have been
+ * truncated (there is only one zero-sized file on the DVD).
  *  
  * Note!  Normally if we can mount the device, which should be the case
  *   when we get here, it is not a blank DVD.  Hence we check if
- *   there is a zero length file with the right name, in which case
- *   we allow it.
- * This seems terribly kludgie to me.  KES
+ *   if all files are of zero length (i.e. no data), in which case we allow it.
+ *
  */
 bool check_can_write_on_non_blank_dvd(DCR *dcr) 
 {
@@ -880,9 +708,8 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr)
    DIR* dp;
    struct dirent *entry, *result;
    int name_max;
-   int count = 0;
-   bool matched = true;
    struct stat filestat;
+   bool ok = true;
       
    name_max = pathconf(".", _PC_NAME_MAX);
    if (name_max < 1024) {
@@ -898,7 +725,7 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr)
    }
    
    entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
-   while (1) {
+   for ( ;; ) {
       if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
          dev->dev_errno = EIO;
          Dmsg2(129, "check_can_write_on_non_blank_dvd: no more files in dir %s (dev=%s)\n", 
@@ -907,39 +734,37 @@ bool check_can_write_on_non_blank_dvd(DCR *dcr)
       } else {
          Dmsg2(99, "check_can_write_on_non_blank_dvd: found %s (versus %s)\n", 
                result->d_name, dev->VolCatInfo.VolCatName);
-         if (strcmp(result->d_name, dev->VolCatInfo.VolCatName) == 0) {
-            /* Found the file, checking it is empty */
+         if (strcmp(result->d_name, ".") && strcmp(result->d_name, "..") &&
+             strcmp(result->d_name, ".keep")) {
+            /* Found a file, checking it is empty */
             POOL_MEM filename(PM_FNAME);
             pm_strcpy(filename, dev->device->mount_point);
-            if (filename.c_str()[strlen(filename.c_str())-1] != '/') {
+            if (!IsPathSeparator(filename.c_str()[strlen(filename.c_str())-1])) {
                pm_strcat(filename, "/");
             }
-            pm_strcat(filename, dev->VolCatInfo.VolCatName);
+            pm_strcat(filename, result->d_name);
             if (stat(filename.c_str(), &filestat) < 0) {
                berrno be;
                dev->dev_errno = errno;
                Dmsg2(29, "check_can_write_on_non_blank_dvd: cannot stat file (file=%s), ERR=%s\n", 
                   filename.c_str(), be.strerror());
-               return false;
+               ok = false;
+               break;
             }
             Dmsg2(99, "check_can_write_on_non_blank_dvd: size of %s is %lld\n", 
                filename.c_str(), filestat.st_size);
-            matched = filestat.st_size == 0;
+            if (filestat.st_size != 0) {
+               ok = false;
+               break;
+            }
          }
       }
-      count++;
    }
    free(entry);
    closedir(dp);
    
-   if (count > 3) {
-      /* There are more than 3 files (., .., and the volume file) */
-      Dmsg1(29, "Cannot write on blank DVD too many files %d greater than 3\n", count);
-      return false;
-   }
-   
-   Dmsg2(29, "OK  can_write_on_non_blank_dvd: got %d files in the mount point (matched=%d)\n", count, matched);
-   return matched;
+   Dmsg1(29, "OK  can_write_on_non_blank_dvd: OK=%d\n", ok);
+   return ok;
 }
 
 /*