+bool dvd_close_job(DCR *dcr)
+{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
+ bool ok = true;
+
+ /*
+ * If the device is a dvd and WritePartAfterJob
+ * is set to yes, open the next part, so, in case of a device
+ * that requires mount, it will be written to the device.
+ */
+ if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
+ Dmsg1(400, "Writing last part=%d write_partafter_job is set.\n",
+ dev->part);
+ if (dev->part < dev->num_dvd_parts+1) {
+ Jmsg3(jcr, M_FATAL, 0, _("Error writing. Current part less than total number of parts (%d/%d, device=%s)\n"),
+ dev->part, dev->num_dvd_parts, dev->print_name());
+ dev->dev_errno = EIO;
+ ok = false;
+ }
+
+ if (ok && !dvd_write_part(dcr)) {
+ Jmsg2(jcr, M_FATAL, 0, _("Unable to write last on %s: ERR=%s\n"),
+ dev->print_name(), dev->bstrerror());
+ dev->dev_errno = EIO;
+ ok = false;
+ }
+ }
+ return ok;
+}
+
+void dvd_remove_empty_part(DCR *dcr)
+{
+ DEVICE *dev = dcr->dev;
+
+ /* Remove the last part file if it is empty */
+ if (dev->is_dvd() && dev->num_dvd_parts > 0) {
+ struct stat statp;
+ uint32_t part_save = dev->part;
+ POOL_MEM archive_name(PM_FNAME);
+ int status;
+
+ dev->part = dev->num_dvd_parts;
+ make_spooled_dvd_filename(dev, archive_name);
+ /* Check that the part file is empty */
+ 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_save, dev->num_dvd_parts, dev->VolCatInfo.VolCatName);
+ Dmsg1(100, "unlink(%s)\n", archive_name.c_str());
+ unlink(archive_name.c_str());
+ if (part_save == dev->part) {
+ dev->set_part_spooled(false); /* no spooled part left */
+ }
+ } else if (status < 0) {
+ if (part_save == dev->part) {
+ dev->set_part_spooled(false); /* spool doesn't exit */
+ }
+ }
+ dev->part = part_save; /* restore part number */
+ }
+}
+
+bool truncate_dvd(DCR *dcr)
+{
+ DEVICE* dev = dcr->dev;
+
+ dev->clear_freespace_ok(); /* need to update freespace */
+ dev->close_part(dcr);
+
+ if (!unmount_dvd(dev, 1)) {
+ Dmsg0(400, "truncate_dvd: Failed to unmount DVD\n");
+ return false;
+ }
+
+ /* If necessary, delete its spool file. */
+ if (dev->is_part_spooled()) {
+ POOL_MEM archive_name(PM_FNAME);
+ /* Delete spool file */
+ make_spooled_dvd_filename(dev, archive_name);
+ unlink(archive_name.c_str());
+ dev->set_part_spooled(false);
+ }
+
+ /* Set num_dvd_parts to zero (on disk) */
+ dev->part = 0;
+ dev->num_dvd_parts = 0;
+ dcr->VolCatInfo.VolCatParts = 0;
+ dev->VolCatInfo.VolCatParts = 0;
+
+ Dmsg0(400, "truncate_dvd: Opening first part (1)...\n");
+
+ dev->truncating = true;
+ /* This creates a zero length spool file and sets part=1 */
+ if (!dvd_open_first_part(dcr, CREATE_READ_WRITE)) {
+ Dmsg0(400, "truncate_dvd: Error while opening first part (1).\n");
+ dev->truncating = false;
+ return false;
+ }
+
+ dev->close_part(dcr);
+
+ Dmsg0(400, "truncate_dvd: Opening first part (2)...\n");
+
+ /*
+ * Now actually truncate the DVD which is done by writing
+ * a zero length part to the DVD/
+ */
+ if (!dvd_write_part(dcr)) {
+ Dmsg0(400, "truncate_dvd: Error while writing to DVD.\n");
+ dev->truncating = false;
+ return false;
+ }
+ dev->truncating = false;
+
+ /* Set num_dvd_parts to zero (on disk) */
+ dev->part = 0;
+ dev->num_dvd_parts = 0;
+ dcr->VolCatInfo.VolCatParts = 0;
+ dev->VolCatInfo.VolCatParts = 0;
+ /* Clear the size of the volume */
+ dev->VolCatInfo.VolCatBytes = 0;
+ dcr->VolCatInfo.VolCatBytes = 0;
+
+ /* Update catalog */
+ if (!dir_update_volume_info(dcr, false)) {
+ return false;
+ }
+
+ return true;
+}