pm_strcpy(archive_name, dev_name);
/*
* If this is a virtual autochanger (i.e. changer_res != NULL)
- * we simply use the deviced name, assuming it has been
+ * we simply use the device name, assuming it has been
* appropriately setup by the "autochanger".
*/
if (!device->changer_res) {
if (num_dvd_parts != VolCatInfo.VolCatParts) {
num_dvd_parts = VolCatInfo.VolCatParts;
}
+
+ /*
+ * If we are not trying to access the last part, set mode to
+ * OPEN_READ_ONLY as writing would be an error.
+ */
+ Dmsg2(29, "open DVD part=%d num_dvd_parts=%d\n", part, num_dvd_parts);
+ if (part <= num_dvd_parts) {
+ omode = OPEN_READ_ONLY;
+ make_mounted_dvd_filename(this, archive_name);
+ set_part_spooled(false);
+ } else {
+ omode = OPEN_READ_WRITE;
+ make_spooled_dvd_filename(this, archive_name);
+ set_part_spooled(true);
+ }
+ set_mode(omode);
+
// Clear any previous truncated_dvd status - we will recalculate it here
truncated_dvd = false;
if (mount_dvd(this, 1)) {
Dmsg0(99, "DVD device mounted.\n");
- if ((num_dvd_parts == 0) && (!truncating)) {
+ if (num_dvd_parts == 0 && !truncating) {
/*
* If we can mount the device, and we are not truncating the DVD,
* we usually want to abort. There is one exception, if there is
openmode = omode;
Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode));
- /*
- * If we are not trying to access the last part, set mode to
- * OPEN_READ_ONLY as writing would be an error.
- */
- Dmsg2(29, "open DVD part=%d num_dvd_parts=%d\n", part, num_dvd_parts);
- if (part <= num_dvd_parts) {
- omode = OPEN_READ_ONLY;
- make_mounted_dvd_filename(this, archive_name);
- } else {
- make_spooled_dvd_filename(this, archive_name);
- }
- set_mode(omode);
/* If creating file, give 0640 permissions */
Dmsg3(29, "mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(omode),
dev_errno = EIO; /* Interpreted as no device present by acquire.c:acquire_device_for_read(). */
Dmsg1(29, "open failed: %s", errmsg);
+ /* Previous open failed. See if we can recover */
if ((omode == OPEN_READ_ONLY || omode == OPEN_READ_WRITE) &&
(part > num_dvd_parts)) {
- /* If the last part (on spool), doesn't exists when accessing,
+ /* If the last part (on spool), doesn't exist when accessing,
* create it. In read/write mode a write will be allowed (higher
* level software thinks that we are extending a pre-existing
* media. Reads for READ_ONLY will report immediately an EOF
* Sometimes it is better to finish with an EOF than with an error. */
Dmsg1(29, "Creating last part on spool: %s\n", archive_name.c_str());
+ omode = CREATE_READ_WRITE;
set_mode(CREATE_READ_WRITE);
fd = ::open(archive_name.c_str(), mode, 0640);
set_mode(omode);
}
-
- /* We don't need it. Only the last part is on spool */
- /*if (omode == OPEN_READ_ONLY) {
- make_spooled_dvd_filename(this, archive_name);
- fd = ::open(archive_name.c_str(), mode, 0640); // try on spool
- }*/
}
Dmsg1(100, "after open fd=%d\n", fd);
if (fd >= 0) {
+ if (omode == OPEN_READ_WRITE || omode == CREATE_READ_WRITE) {
+ set_append();
+ }
/* Get size of file */
if (fstat(fd, &filestat) < 0) {
berrno be;
part_size = filestat.st_size;
dev_errno = 0;
update_pos_dev(this); /* update position */
-
- /* NB: It seems this code is wrong... part number is incremented in open_next_part, not here */
-
- /* Check if just created Volume part */
-/*
- * if (omode == OPEN_READ_WRITE && (part == 0 || part_size == 0)) {
- * part++;
- * num_dvd_parts = part;
- * VolCatInfo.VolCatParts = num_dvd_parts;
- * } else {
- * if (part == 0) { // we must have opened the first part
- * part++;
- * }
- * }
- */
-
}
}
}
bool first = true;
Dmsg3(400, "rewind res=%d fd=%d %s\n", reserved_device, fd, print_name());
+ state &= ~(ST_EOT|ST_EOF|ST_WEOT); /* remove EOF/EOT flags */
+ block_num = file = 0;
+ file_size = 0;
+ file_addr = 0;
if (fd < 0) {
if (!is_dvd()) { /* In case of major error, the fd is not open on DVD, so we don't want to abort. */
dev_errno = EBADF;
}
return false;
}
- state &= ~(ST_EOT|ST_EOF|ST_WEOT); /* remove EOF/EOT flags */
- block_num = file = 0;
- file_size = 0;
- file_addr = 0;
if (is_tape()) {
mt_com.mt_op = MTREW;
mt_com.mt_count = 1;
/* Remove the last part file if it is empty */
if (num_dvd_parts > 0) {
struct stat statp;
- int part_save = part;
+ uint32_t part_save = part;
POOL_MEM archive_name(PM_FNAME);
+ int status;
part = num_dvd_parts;
- Dmsg3(100, "Remove empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n",
- part, num_dvd_parts, VolCatInfo.VolCatName);
make_spooled_dvd_filename(this, archive_name);
/* Check that the part file is empty */
- if ((stat(archive_name.c_str(), &statp) == 0) && (statp.st_size == 0)) {
+ status = stat(archive_name.c_str(), &statp);
+ if (status == 0 && statp.st_size == 0) {
+ Dmsg3(100, "Unlink empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n",
+ part, num_dvd_parts, VolCatInfo.VolCatName);
Dmsg1(100, "unlink(%s)\n", archive_name.c_str());
unlink(archive_name.c_str());
- }
+ if (part_save == part) {
+ set_part_spooled(false); /* no spooled part left */
+ }
+ } else if (status < 0) {
+ if (part_save == part) {
+ set_part_spooled(false); /* spool doesn't exit */
+ }
+ }
part = part_save; /* restore part number */
}
openmode = 0;
}
+/*
+ * This call closes the device, but it is used in DVD handling
+ * where we close one part and then open the next part. The
+ * difference between close_part() and close() is that close_part()
+ * saves the state information of the device (e.g. the Volume lable,
+ * the Volume Catalog record, ... This permits opening and closing
+ * the Volume parts multiple times without losing track of what the
+ * main Volume parameters are.
+ */
+void DEVICE::close_part(DCR *dcr)
+{
+ VOLUME_LABEL saveVolHdr;
+ VOLUME_CAT_INFO saveVolCatInfo; /* Volume Catalog Information */
+
+
+ memcpy(&saveVolHdr, &VolHdr, sizeof(saveVolHdr));
+ memcpy(&saveVolCatInfo, &VolCatInfo, sizeof(saveVolCatInfo));
+ close(); /* close current part */
+ memcpy(&VolHdr, &saveVolHdr, sizeof(VolHdr));
+ memcpy(&VolCatInfo, &saveVolCatInfo, sizeof(VolCatInfo));
+ memcpy(&dcr->VolCatInfo, &saveVolCatInfo, sizeof(dcr->VolCatInfo));
+}
+
+
bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
}
results = get_memory(2000);
results[0] = 0;
+
/* If busy retry each second */
+ Dmsg1(20, "do_mount 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 internationalisation (This is not a problem) */
+ /* Doesn't work with internationalization (This is not a problem) */
if (fnmatch("*is already mounted on", results, 0) == 0) {
break;
}