]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/file_dev.c
Backport from Bacula Enterprise
[bacula/bacula] / bacula / src / stored / file_dev.c
index e5ad02f859b21f6822fcf29970ff176b2aedf0bc..d7166e7f79092f345b450ce48632d8c02cbcbf4f 100644 (file)
@@ -1,17 +1,21 @@
 /*
-   Bacula® - The Network Backup Solution
+   Bacula(R) - The Network Backup Solution
 
+   Copyright (C) 2000-2015 Kern Sibbald
    Copyright (C) 2000-2014 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.
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
 
    You may use this file and others of this release according to the
    license defined in the LICENSE file, which includes the Affero General
    Public License, v3.0 ("AGPLv3") and some additional permissions and
    terms pursuant to its AGPLv3 Section 7.
 
-   Bacula® is a registered trademark of Kern Sibbald.
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  *
@@ -42,7 +46,11 @@ int DEVICE::d_close(int fd)
 
 int DEVICE::d_ioctl(int fd, ioctl_req_t request, char *mt_com)
 {
+#ifdef HAVE_WIN32
+   return -1;
+#else
    return ::ioctl(fd, request, mt_com);
+#endif
 }
 
 ssize_t DEVICE::d_read(int fd, void *buffer, size_t count)
@@ -123,12 +131,12 @@ boffset_t DEVICE::lseek(DCR *dcr, boffset_t offset, int whence)
 }
 
 /*
- * Open a file device. For Aligned type we open both Volumes
+ * Open a file device.
  */
 void DEVICE::open_file_device(DCR *dcr, int omode)
 {
    POOL_MEM archive_name(PM_FNAME);
-   POOL_MEM aligned_name(PM_FNAME);
+   struct stat sp;
 
    get_autochanger_loaded_slot(dcr);
 
@@ -151,10 +159,13 @@ void DEVICE::open_file_device(DCR *dcr, int omode)
          return;
       }
 
-      if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
-         pm_strcat(archive_name, "/");
+      /* If not /dev/null concatenate VolumeName */
+      if (!is_null()) {
+         if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
+            pm_strcat(archive_name, "/");
+         }
+         pm_strcat(archive_name, getVolCatName());
       }
-      pm_strcat(archive_name, getVolCatName());
    }
 
    mount(1);                          /* do mount if required */
@@ -171,19 +182,25 @@ void DEVICE::open_file_device(DCR *dcr, int omode)
       Mmsg3(errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"),
             archive_name.c_str(), mode_to_str(omode), be.bstrerror());
       Dmsg1(40, "open failed: %s", errmsg);
+   } else {
+      Dmsg2(40, "Did open(%s,%s,0640)\n", archive_name.c_str(), mode_to_str(omode));
    }
    if (m_fd >= 0) {
       dev_errno = 0;
       file = 0;
       file_addr = 0;
+
+      /* Refresh the underline device id */
+      if (fstat(m_fd, &sp) == 0) {
+         devno = sp.st_dev;
+      }
    }
    Dmsg1(100, "open dev: disk fd=%d opened\n", m_fd);
 }
 
 
 /*
- * Truncate a volume.  If this is aligned disk, we
- *  truncate both volumes.
+ * Truncate a volume.
  */
 bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
 {
@@ -198,61 +215,65 @@ bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
       /* maybe we should rewind and write and eof ???? */
       return true;                    /* we don't really truncate tapes */
    case B_FILE_DEV:
-      Dmsg1(100, "Truncate fd=%d\n", dev->m_fd);
-      if (ftruncate(dev->m_fd, 0) != 0) {
-         berrno be;
-         Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"),
-               print_name(), be.bstrerror());
-         return false;
-      }
-
-      /*
-       * Check for a successful ftruncate() and issue a work-around for devices
-       * (mostly cheap NAS) that don't support truncation.
-       * Workaround supplied by Martin Schmid as a solution to bug #1011.
-       * 1. close file
-       * 2. delete file
-       * 3. open new file with same mode
-       * 4. change ownership to original
-       */
-
-      if (fstat(dev->m_fd, &st) != 0) {
-         berrno be;
-         Mmsg2(errmsg, _("Unable to stat device %s. ERR=%s\n"),
-               print_name(), be.bstrerror());
-         return false;
-      }
-
-      if (st.st_size != 0) {             /* ftruncate() didn't work */
-         POOL_MEM archive_name(PM_FNAME);
-
-         pm_strcpy(archive_name, dev_name);
-         if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
-            pm_strcat(archive_name, "/");
+      /* Do truncate for 1 or 2 devices */
+      for ( ;; ) {
+         Dmsg1(100, "Truncate fd=%d\n", dev->m_fd);
+         if (ftruncate(dev->m_fd, 0) != 0) {
+            berrno be;
+            Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"),
+                  print_name(), be.bstrerror());
+            return false;
          }
-         pm_strcat(archive_name, dcr->VolumeName);
-
-         Mmsg2(errmsg, _("Device %s doesn't support ftruncate(). Recreating file %s.\n"),
-               print_name(), archive_name.c_str());
 
-         /* Close file and blow it away */
-         ::close(dev->m_fd);
-         ::unlink(archive_name.c_str());
-
-         /* Recreate the file -- of course, empty */
-         dev->set_mode(CREATE_READ_WRITE);
-         if ((dev->m_fd = ::open(archive_name.c_str(), mode, st.st_mode)) < 0) {
+         /*
+          * Check for a successful ftruncate() and issue a work-around for devices
+          * (mostly cheap NAS) that don't support truncation.
+          * Workaround supplied by Martin Schmid as a solution to bug #1011.
+          * 1. close file
+          * 2. delete file
+          * 3. open new file with same mode
+          * 4. change ownership to original
+          */
+
+         if (fstat(dev->m_fd, &st) != 0) {
             berrno be;
-            dev_errno = errno;
-            Mmsg2(errmsg, _("Could not reopen: %s, ERR=%s\n"), archive_name.c_str(),
-                  be.bstrerror());
-            Dmsg1(40, "reopen failed: %s", errmsg);
-            Emsg0(M_FATAL, 0, errmsg);
+            Mmsg2(errmsg, _("Unable to stat device %s. ERR=%s\n"),
+                  print_name(), be.bstrerror());
             return false;
          }
 
-         /* Reset proper owner */
-         chown(archive_name.c_str(), st.st_uid, st.st_gid);
+         if (st.st_size != 0) {             /* ftruncate() didn't work */
+            POOL_MEM archive_name(PM_FNAME);
+
+            pm_strcpy(archive_name, dev_name);
+            if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
+               pm_strcat(archive_name, "/");
+            }
+            pm_strcat(archive_name, dcr->VolumeName);
+
+            Mmsg2(errmsg, _("Device %s doesn't support ftruncate(). Recreating file %s.\n"),
+                  print_name(), archive_name.c_str());
+
+            /* Close file and blow it away */
+            ::close(dev->m_fd);
+            ::unlink(archive_name.c_str());
+
+            /* Recreate the file -- of course, empty */
+            dev->set_mode(CREATE_READ_WRITE);
+            if ((dev->m_fd = ::open(archive_name.c_str(), mode, st.st_mode)) < 0) {
+               berrno be;
+               dev_errno = errno;
+               Mmsg2(errmsg, _("Could not reopen: %s, ERR=%s\n"), archive_name.c_str(),
+                     be.bstrerror());
+               Dmsg1(40, "reopen failed: %s", errmsg);
+               Emsg0(M_FATAL, 0, errmsg);
+               return false;
+            }
+
+            /* Reset proper owner */
+            chown(archive_name.c_str(), st.st_uid, st.st_gid);
+         }
+         break;
       }
       return true;
    }
@@ -263,7 +284,7 @@ bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
 /*
  * (Un)mount the device (either a FILE or DVD device)
  */
-bool DEVICE::do_file_mount(int mount, int dotimeout)
+bool DEVICE::mount_file(int mount, int dotimeout)
 {
    POOL_MEM ocmd(PM_FNAME);
    POOLMEM *results;
@@ -283,7 +304,7 @@ bool DEVICE::do_file_mount(int mount, int dotimeout)
    clear_freespace_ok();
    edit_mount_codes(ocmd, icmd);
 
-   Dmsg2(100, "do_file_mount: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
+   Dmsg2(100, "mount_file: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
 
    if (dotimeout) {
       /* Try at most 10 times to (un)mount the device. This should perhaps be configurable. */
@@ -294,7 +315,7 @@ bool DEVICE::do_file_mount(int mount, int dotimeout)
    results = get_memory(4000);
 
    /* If busy retry each second */
-   Dmsg1(100, "do_file_mount run_prog=%s\n", ocmd.c_str());
+   Dmsg1(100, "mount_file run_prog=%s\n", ocmd.c_str());
    while ((status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results)) != 0) {
       /* Doesn't work with internationalization (This is not a problem) */
       if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
@@ -308,7 +329,7 @@ bool DEVICE::do_file_mount(int mount, int dotimeout)
           * Try to unmount it, then remount it */
          if (mount) {
             Dmsg1(400, "Trying to unmount the device %s...\n", print_name());
-            do_file_mount(0, 0);
+            mount_file(0, 0);
          }
          bmicrosleep(1, 0);
          continue;
@@ -329,7 +350,7 @@ bool DEVICE::do_file_mount(int mount, int dotimeout)
       if (!(dp = opendir(device->mount_point))) {
          berrno be;
          dev_errno = errno;
-         Dmsg3(100, "do_file_mount: failed to open dir %s (dev=%s), ERR=%s\n",
+         Dmsg3(100, "mount_file: failed to open dir %s (dev=%s), ERR=%s\n",
                device->mount_point, print_name(), be.bstrerror());
          goto get_out;
       }
@@ -339,7 +360,7 @@ bool DEVICE::do_file_mount(int mount, int dotimeout)
       while (1) {
          if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
             dev_errno = EIO;
-            Dmsg2(129, "do_file_mount: failed to find suitable file in dir %s (dev=%s)\n",
+            Dmsg2(129, "mount_file: failed to find suitable file in dir %s (dev=%s)\n",
                   device->mount_point, print_name());
             break;
          }
@@ -347,13 +368,13 @@ bool DEVICE::do_file_mount(int mount, int dotimeout)
             count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
             break;
          } else {
-            Dmsg2(129, "do_file_mount: ignoring %s in %s\n", result->d_name, device->mount_point);
+            Dmsg2(129, "mount_file: ignoring %s in %s\n", result->d_name, device->mount_point);
          }
       }
       free(entry);
       closedir(dp);
 
-      Dmsg1(100, "do_file_mount: got %d files in the mount point (not counting ., .. and .keep)\n", count);
+      Dmsg1(100, "mount_file: got %d files in the mount point (not counting ., .. and .keep)\n", count);
 
       if (count > 0) {
          /* If we got more than ., .. and .keep */
@@ -379,6 +400,7 @@ get_out:
 
    set_mounted(mount);              /* set/clear mounted flag */
    free_pool_memory(results);
+   /* Do not check free space when unmounting */
    Dmsg1(200, "============ mount=%d\n", mount);
    return true;
 }