/*
- 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.
*/
/*
*
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)
}
/*
- * 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);
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 */
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 */
{
/* 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;
}
/*
* (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;
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. */
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) {
* 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;
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;
}
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;
}
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 */
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;
}