* On either an I/O error or end of tape,
* we will stop writing on the physical device (no I/O recovery is
* attempted at least in this daemon). The state flag will be sent
- * to include ST_EOT, which is ephimeral, and ST_WEOT, which is
+ * to include ST_EOT, which is ephemeral, and ST_WEOT, which is
* persistent. Lots of routines clear ST_EOT, but ST_WEOT is
* cleared only when the problem goes away. Now when ST_WEOT
* is set all calls to write_block_to_device() call the fix_up
/*
* Handle opening of DVD Volume
*/
- Dmsg3(29, "Enter: open_dvd_dev: %s dev=%s mode=%s\n", is_dvd()?"DVD":"disk",
- archive_name.c_str(), mode_to_str(omode));
+ Dmsg2(29, "Enter: open_dvd_dev: DVD vol=%s mode=%s\n",
+ &dcr->VolCatInfo, mode_to_str(omode));
/*
* For a DVD we must always pull the state info from dcr->VolCatInfo
* OPEN_READ_ONLY as writing would be an error.
*/
Dmsg2(29, "open DVD part=%d num_dvd_parts=%d\n", part, num_dvd_parts);
+ /* Now find the name of the part that we want to access */
if (part <= num_dvd_parts) {
omode = OPEN_READ_ONLY;
make_mounted_dvd_filename(this, archive_name);
Dmsg3(99, "open_dvd_device: part=%d num_dvd_parts=%d, VolCatInfo.VolCatParts=%d\n",
part, num_dvd_parts, dcr->VolCatInfo.VolCatParts);
- if (mount_dvd(this, 1)) {
+ if (mount(1)) {
Dmsg0(99, "DVD device mounted.\n");
if (num_dvd_parts == 0 && !truncating) {
/*
if (!check_can_write_on_non_blank_dvd(dcr)) {
Mmsg(errmsg, _("The DVD in device %s contains data, please blank it before writing.\n"), print_name());
Emsg0(M_FATAL, 0, errmsg);
- unmount_dvd(this, 1); /* Unmount the device, so the operator can change it. */
+ unmount(1); /* Unmount the device, so the operator can change it. */
clear_opened();
return;
}
blank_dvd = true;
+ } else {
+ /*
+ * Ensure that we have the correct DVD loaded by looking for part1.
+ * We only succeed the open if it exists. Failure to do this could
+ * leave us trying to add a part to a different DVD!
+ */
+ uint32_t oldpart = part;
+ struct stat statp;
+ POOL_MEM part1_name(PM_FNAME);
+ part = 1;
+ make_mounted_dvd_filename(this, part1_name);
+ part = oldpart;
+ if (stat(part1_name.c_str(), &statp) < 0) {
+ berrno be;
+ Mmsg(errmsg, _("Unable to stat DVD part 1 file %s: ERR=%s\n"),
+ part1_name.c_str(), be.strerror());
+ Emsg0(M_FATAL, 0, errmsg);
+ clear_opened();
+ return;
+ }
+ if (!S_ISREG(statp.st_mode)) {
+ /* It is not a regular file */
+ Mmsg(errmsg, _("DVD part 1 is not a regular file %s.\n"),
+ part1_name.c_str());
+ Emsg0(M_FATAL, 0, errmsg);
+ clear_opened();
+ return;
+ }
}
} else {
Dmsg0(99, "DVD device mount failed.\n");
/* We cannot mount the device */
if (num_dvd_parts == 0) {
/* Run free space, check there is a media. */
- if (!update_free_space_dev(this)) {
+ if (!update_freespace()) {
Emsg0(M_FATAL, 0, errmsg);
clear_opened();
return;
*/
bool DEVICE::unmount(int timeout)
{
- Dmsg0(90, "Enter unmount_dvd\n");
+ Dmsg0(90, "Enter unmount\n");
if (is_mounted()) {
return do_mount(0, timeout);
}
icmd = device->unmount_command;
}
+ clear_freespace_ok();
edit_mount_codes(ocmd, icmd);
- Dmsg2(100, "do_mount_dvd: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
+ Dmsg2(100, "do_mount: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
if (dotimeout) {
/* Try at most 1 time to (un)mount the device. This should perhaps be configurable. */
} else {
timeout = 0;
}
- results = get_memory(2000);
+ results = get_memory(4000);
results[0] = 0;
/* If busy retry each second */
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 (fnmatch("*is already mounted on", results, 0) == 0) {
+ if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
+ break;
+ }
+ if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
break;
}
if (timeout-- > 0) {
bmicrosleep(1, 0);
continue;
}
- Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", print_name(), results);
- Mmsg(errmsg, _("Device %s cannot be mounted. ERR=%s\n"),
- print_name(), results);
+ if (status != 0) {
+ berrno be;
+ Dmsg5(40, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", print_name(),
+ (mount ? "" : "un"), status, results, be.strerror(status));
+ Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
+ print_name(), (mount ? "" : "un"), be.strerror(status));
+ } else {
+ Dmsg4(40, "Device %s cannot be %smounted. stat=%d ERR=%s\n", print_name(),
+ (mount ? "" : "un"), status, results);
+ Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
+ print_name(), (mount ? "" : "un"), results);
+ }
/*
* Now, just to be sure it is not mounted, try to read the
* filesystem.
Dmsg1(29, "do_mount: got %d files in the mount point (not counting ., .. and .keep)\n", count);
if (count > 0) {
- mount = 1; /* If we got more than ., .. and .keep */
- break; /* there must be something mounted */
+ /* 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 */
+ set_mounted(true);
+ free_pool_memory(results);
+ Dmsg0(200, "== error mount=1 wanted unmount\n");
+ return false;
+ }
}
get_out:
set_mounted(false);
set_mounted(mount); /* set/clear mounted flag */
free_pool_memory(results);
+ /* Do not check free space when unmounting */
+ if (mount && !update_freespace()) {
+ return false;
+ }
Dmsg1(200, "============ mount=%d\n", mount);
return true;
}
#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);
/*
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->clear_freespace_ok();
- 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;
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);
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);
+ 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;
}
/* 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);
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;
}