-static void reread_last_block(DCR *dcr)
-{
-#define CHECK_LAST_BLOCK
-#ifdef CHECK_LAST_BLOCK
- bool ok = true;
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
- DEV_BLOCK *block = dcr->block;
- /*
- * If the device is a tape and it supports backspace record,
- * we backspace over one or two eof marks depending on
- * how many we just wrote, then over the last record,
- * then re-read it and verify that the block number is
- * correct.
- */
- if (dev->is_tape() && dev_cap(dev, CAP_BSR)) {
- /* Now back up over what we wrote and read the last block */
- if (!bsf_dev(dev, 1)) {
- berrno be;
- ok = false;
- Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"),
- be.strerror(dev->dev_errno));
- }
- if (ok && dev_cap(dev, CAP_TWOEOF) && !bsf_dev(dev, 1)) {
- berrno be;
- ok = false;
- Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"),
- be.strerror(dev->dev_errno));
- }
- /* Backspace over record */
- if (ok && !bsr_dev(dev, 1)) {
- berrno be;
- ok = false;
- Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"),
- be.strerror(dev->dev_errno));
- /*
- * On FreeBSD systems, if the user got here, it is likely that his/her
- * tape drive is "frozen". The correct thing to do is a
- * rewind(), but if we do that, higher levels in cleaning up, will
- * most likely write the EOS record over the beginning of the
- * tape. The rewind *is* done later in mount.c when another
- * tape is requested. Note, the clrerror_dev() call in bsr_dev()
- * calls ioctl(MTCERRSTAT), which *should* fix the problem.
- */
- }
- if (ok) {
- DEV_BLOCK *lblock = new_block(dev);
- /* Note, this can destroy dev->errmsg */
- dcr->block = lblock;
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
- Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"),
- dev->errmsg);
- } else {
- if (lblock->BlockNumber+1 == block->BlockNumber) {
- Jmsg(jcr, M_INFO, 0, _("Re-read of last block succeeded.\n"));
- } else {
- Jmsg(jcr, M_ERROR, 0, _(
-"Re-read of last block failed. Last block=%u Current block=%u.\n"),
- lblock->BlockNumber, block->BlockNumber);
- }
- }
- free_block(lblock);
- dcr->block = block;
- }
- }
-#endif
-}
-
-static bool terminate_writing_volume(DCR *dcr)
-{
- DEVICE *dev = dcr->dev;
- bool ok = true;
-
- /* Create a JobMedia record to indicated end of tape */
- dev->VolCatInfo.VolCatFiles = dev->file;
- if (!dir_create_jobmedia_record(dcr)) {
- Dmsg0(190, "Error from create JobMedia\n");
- dev->dev_errno = EIO;
- Jmsg(dcr->jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- dcr->VolCatInfo.VolCatName, dcr->jcr->Job);
- ok = false;
- goto bail_out;
- }
- dcr->block->write_failed = true;
- if (weof_dev(dev, 1) != 0) { /* end the tape */
- dev->VolCatInfo.VolCatErrors++;
- Jmsg(dcr->jcr, M_ERROR, 0, "Error writing final EOF to tape. This tape may not be readable.\n"
- "%s", dev->errmsg);
- ok = false;
- Dmsg0(100, "WEOF error.\n");
- }
- if (ok) {
- ok = write_ansi_ibm_labels(dcr, ANSI_EOV_LABEL, dev->VolHdr.VolumeName);
- }
- bstrncpy(dev->VolCatInfo.VolCatStatus, "Full", sizeof(dev->VolCatInfo.VolCatStatus));
- dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
- dev->VolCatInfo.VolCatJobs++; /* increment number of jobs */
-
- if (dev->is_dvd()) { /* Write the current (and last) part. */
- open_next_part(dev);
- }
-
- if (!dir_update_volume_info(dcr, false)) {
- ok = false;
- }
- Dmsg1(100, "dir_update_volume_info terminate writing -- %s\n", ok?"OK":"ERROR");
-
- /*
- * Walk through all attached dcrs setting flag to call
- * set_new_file_parameters() when that dcr is next used.
- */
- DCR *mdcr;
- foreach_dlist(mdcr, dev->attached_dcrs) {
- if (mdcr->jcr->JobId == 0) {
- continue;
- }
- mdcr->NewFile = true; /* set reminder to do set_new_file_params */
- }
- /* Set new file/block parameters for current dcr */
- set_new_file_parameters(dcr);
-
- if (ok && dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */
- dev->VolCatInfo.VolCatErrors++;
- /* This may not be fatal since we already wrote an EOF */
- Jmsg(dcr->jcr, M_ERROR, 0, "%s", dev->errmsg);
- }
-bail_out:
- dev->set_ateot(); /* no more writing this tape */
- Dmsg1(100, "Leave terminate_writing_volume -- %s\n", ok?"OK":"ERROR");
- return ok;
-}
-
-/*
- * Do bookkeeping when a new file is created on a Volume. This is
- * also done for disk files to generate the jobmedia records for
- * quick seeking.
- */
-static bool do_new_file_bookkeeping(DCR *dcr)
-{
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
-
- /* Create a JobMedia record so restore can seek */
- if (!dir_create_jobmedia_record(dcr)) {
- Dmsg0(190, "Error from create_job_media.\n");
- dev->dev_errno = EIO;
- Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
- dcr->VolCatInfo.VolCatName, jcr->Job);
- terminate_writing_volume(dcr);
- dev->dev_errno = EIO;
- return false;
- }
- dev->VolCatInfo.VolCatFiles = dev->file;
- if (!dir_update_volume_info(dcr, false)) {
- Dmsg0(190, "Error from update_vol_info.\n");
- terminate_writing_volume(dcr);
- dev->dev_errno = EIO;
- return false;
- }
- Dmsg0(100, "dir_update_volume_info max file size -- OK\n");
-
- /*
- * Walk through all attached dcrs setting flag to call
- * set_new_file_parameters() when that dcr is next used.
- */
- DCR *mdcr;
- foreach_dlist(mdcr, dev->attached_dcrs) {
- if (mdcr->jcr->JobId == 0) {
- continue;
- }
- mdcr->NewFile = true; /* set reminder to do set_new_file_params */
- }
- /* Set new file/block parameters for current dcr */
- set_new_file_parameters(dcr);
- return true;
-}
-
-/*
- * Do all checks for DVD sizes during writing.
- */
-static bool do_dvd_size_checks(DCR *dcr)
-{
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
- DEV_BLOCK *block = dcr->block;
-
- /* Limit maximum part size to value specified by user
- * (not applicable to tapes/fifos)
- */
- if (!(dev->is_tape() || dev->is_fifo()) && dev->max_part_size > 0 &&
- (dev->part_size + block->binbuf) >= dev->max_part_size) {
- if (dev->part < dev->num_parts) {
- Jmsg3(dcr->jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
- dev->part, dev->num_parts, dev->print_name());
- dev->dev_errno = EIO;
- return false;
- }
-
- if (open_next_part(dev) < 0) {
- Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
- dev->print_name(), strerror_dev(dev));
- dev->dev_errno = EIO;
- return false;
- }
-
- dev->VolCatInfo.VolCatParts = dev->num_parts;
-
- if (!dir_update_volume_info(dcr, false)) {
- Dmsg0(190, "Error from update_vol_info.\n");
- dev->dev_errno = EIO;
- return false;
- }
- }
-
- if (dev->free_space_errno < 0) { /* Error while getting free space */
- char ed1[50], ed2[50];
- Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
- Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s "
- "(part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
- dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->print_name(),
- edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
- dev->free_space_errno, dev->errmsg);
- dev->dev_errno = -dev->free_space_errno;
- return false;
- }
-
- if ((dev->free_space_errno > 0 && (dev->part_size + block->binbuf) >= dev->free_space)) {
- char ed1[50], ed2[50];
- Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
- Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s "
- "(part_size=%s, free_space=%s, free_space_errno=%d).\n"),
- dev->VolCatInfo.VolCatName,
- dev->file, dev->block_num, dev->print_name(),
- edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
- dev->free_space_errno);
- terminate_writing_volume(dcr);
- dev->dev_errno = ENOSPC;
- return false;
- }
- return true;
-}
-