+ /*
+ * 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_freespace()) {
+ Emsg0(M_FATAL, 0, errmsg);
+ clear_opened();
+ return;
+ }
+ if (have_media()) {
+ Dmsg1(29, "Could not mount device %s, this is not a problem (num_dvd_parts == 0), and have media.\n", print_name());
+ } else {
+ Mmsg(errmsg, _("There is no valid DVD in device %s.\n"), print_name());
+ Emsg0(M_FATAL, 0, errmsg);
+ clear_opened();
+ return;
+ }
+ } else {
+ Mmsg(errmsg, _("Could not mount DVD device %s.\n"), print_name());
+ Emsg0(M_FATAL, 0, errmsg);
+ clear_opened();
+ return;
+ }
+ }
+
+ Dmsg5(29, "open dev: DVD dev=%s mode=%s part=%d npart=%d volcatnparts=%d\n",
+ archive_name.c_str(), mode_to_str(omode),
+ part, num_dvd_parts, dcr->VolCatInfo.VolCatParts);
+ openmode = omode;
+ Dmsg2(100, "openmode=%d %s\n", openmode, mode_to_str(openmode));
+
+
+ /* If creating file, give 0640 permissions */
+ Dmsg3(29, "mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(omode),
+ archive_name.c_str(), mode);
+ /* Use system open() */
+ if ((fd = ::open(archive_name.c_str(), mode, 0640)) < 0) {
+ berrno be;
+ Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(),
+ be.strerror());
+ // Should this be set if we try the create/open below
+ 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 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);
+ }
+ }
+ Dmsg1(100, "after open fd=%d\n", fd);
+ if (is_open()) {
+ if (omode == OPEN_READ_WRITE || omode == CREATE_READ_WRITE) {
+ set_append();