#include "stored.h"
/* Forward referenced functions */
+void set_os_device_parameters(DEVICE *dev);
/*
* Allocate and initialize the DEVICE structure
/* Check that device is available */
if (stat(device->device_name, &statp) < 0) {
+ berrno be;
if (dev) {
dev->dev_errno = errno;
}
Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name,
- strerror(errno));
+ be.strerror());
return NULL;
}
tape = false;
*dev->errmsg = 0;
if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_cond_init(&dev->wait, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init cond variable: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_mutex_init(&dev->spool_mutex, NULL)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = rwl_init(&dev->lock)) != 0) {
+ berrno be;
dev->dev_errno = errstat;
- Mmsg1(&dev->errmsg, _("Unable to init mutex: ERR=%s\n"), strerror(errstat));
+ Mmsg1(dev->errmsg, _("Unable to init mutex: ERR=%s\n"), be.strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
dev->state |= ST_OPENED;
dev->use_count = 1;
update_pos_dev(dev); /* update position */
+ set_os_device_parameters(dev); /* do system dependent stuff */
}
/* Stop any open() timer we started */
if (dev->tid) {
return -1;
}
archive_name = get_pool_memory(PM_FNAME);
- pm_strcpy(&archive_name, dev->dev_name);
+ pm_strcpy(archive_name, dev->dev_name);
if (archive_name[strlen(archive_name)] != '/') {
- pm_strcat(&archive_name, "/");
+ pm_strcat(archive_name, "/");
}
- pm_strcat(&archive_name, VolName);
+ pm_strcat(archive_name, VolName);
Dmsg1(29, "open_dev: device is disk %s\n", archive_name);
if (mode == OPEN_READ_WRITE) {
dev->mode = O_CREAT | O_RDWR | O_BINARY;
Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num);
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 &&
mt_stat.mt_fileno >= 0) {
- Dmsg2(000, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
+ Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
dev->file = mt_stat.mt_fileno;
}
stat = 0;
}
if (dev->state & ST_EOT) {
dev->dev_errno = 0;
- Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
return false;
}
if (dev->state & ST_EOF) {
mt_com.mt_count = num;
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0 || ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
+ berrno be;
dev->state |= ST_EOT;
Dmsg0(200, "Set ST_EOT\n");
clrerror_dev(dev, MTFSF);
- Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
- dev->dev_name, strerror(dev->dev_errno));
+ Mmsg2(dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
+ dev->dev_name, be.strerror());
Dmsg1(200, "%s", dev->errmsg);
return false;
}
if (errno == ENOMEM) { /* tape record exceeds buf len */
stat = rbuf_len; /* This is OK */
} else {
+ berrno be;
dev->state |= ST_EOT;
clrerror_dev(dev, -1);
Dmsg2(200, "Set ST_EOT read errno=%d. ERR=%s\n", dev->dev_errno,
- strerror(dev->dev_errno));
- Mmsg2(&dev->errmsg, _("read error on %s. ERR=%s.\n"),
- dev->dev_name, strerror(dev->dev_errno));
+ be.strerror());
+ Mmsg2(dev->errmsg, _("read error on %s. ERR=%s.\n"),
+ dev->dev_name, be.strerror(dev->dev_errno));
Dmsg1(200, "%s", dev->errmsg);
break;
}
}
if (dev->state & ST_EOT) {
dev->dev_errno = 0;
- Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
stat = -1;
} else {
stat = 0;
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to bsf_dev. Archive device not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
if (!(dev_state(dev, ST_TAPE))) {
- Mmsg1(&dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"),
+ Mmsg1(dev->errmsg, _("Device %s cannot BSF because it is not a tape.\n"),
dev->dev_name);
return false;
}
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0) {
clrerror_dev(dev, MTBSF);
- Mmsg2(&dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTBSF error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
update_pos_dev(dev);
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to fsr_dev. Archive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to fsr_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
return false;
}
if (!dev_cap(dev, CAP_FSR)) {
- Mmsg1(&dev->errmsg, _("ioctl MTFSR not permitted on %s.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("ioctl MTFSR not permitted on %s.\n"), dev->dev_name);
return false;
}
}
}
clrerror_dev(dev, MTFSR);
- Mmsg2(&dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
update_pos_dev(dev);
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to bsr_dev. Archive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to bsr_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
}
if (!dev_cap(dev, CAP_BSR)) {
- Mmsg1(&dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->dev_name);
+ Mmsg1(dev->errmsg, _("ioctl MTBSR not permitted on %s.\n"), dev->dev_name);
return false;
}
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat < 0) {
clrerror_dev(dev, MTBSR);
- Mmsg2(&dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("ioctl MTBSR error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
update_pos_dev(dev);
{
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to reposition_dev. Archive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to reposition_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return false;
}
Dmsg1(100, "===== lseek to %d\n", (int)pos);
if (lseek(dev->fd, pos, SEEK_SET) == (off_t)-1) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
+ Mmsg2(dev->errmsg, _("lseek error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return false;
}
bsf_dev(dev, 1);
fsf_dev(dev, 1);
}
- if (block > dev->block_num) {
+ if (dev_cap(dev, CAP_POSITIONBLOCKS) && block > dev->block_num) {
/* Ignore errors as Bacula can read to the correct block */
Dmsg1(100, "fsr %d\n", block-dev->block_num);
return fsr_dev(dev, block-dev->block_num);
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n"));
+ Mmsg0(dev->errmsg, _("Bad call to weof_dev. Archive drive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return -1;
}
dev->file += num;
dev->file_addr = 0;
} else {
+ berrno be;
clrerror_dev(dev, MTWEOF);
if (stat == -1) {
- Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
- dev->dev_name, strerror(dev->dev_errno));
+ Mmsg2(dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
+ dev->dev_name, be.strerror());
}
}
return stat;
clrerror_dev(DEVICE *dev, int func)
{
const char *msg = NULL;
+ struct mtget mt_stat;
dev->dev_errno = errno; /* save errno */
if (errno == EIO) {
Emsg0(M_ERROR, 0, dev->errmsg);
}
}
+ /* On some systems such as NetBSD, this clears all errors */
+ ioctl(dev->fd, MTIOCGET, (char *)&mt_stat);
+
/* Found on Linux */
#ifdef MTIOCLRERR
{
ioctl(dev->fd, MTIOCERRSTAT, (char *)&mt_errstat);
}
#endif
+
+/* Clear Subsystem Exception OSF1 */
+#ifdef MTCSE
+{
+ struct mtop mt_com;
+ mt_com.mt_op = MTCSE;
+ mt_com.mt_count = 1;
+ /* Clear any error condition on the tape */
+ ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
+ Dmsg0(200, "Did MTCSE\n");
+}
+#endif
}
/*
}
}
-#ifdef xxxx
-/*
- * We attach a jcr to the device so that when
- * the Volume is full during writing, a
- * JobMedia record will be created for this
- * Job.
- */
-void attach_jcr_to_device(DEVICE *dev, JCR *jcr)
-{
- jcr->prev_dev = (JCR *)NULL;
- jcr->next_dev = dev->attached_jcrs;
- if (dev->attached_jcrs) {
- dev->attached_jcrs->prev_dev = jcr;
- }
- dev->attached_jcrs = jcr;
- Dmsg1(100, "Attached Job %s\n", jcr->Job);
-}
-
-void detach_jcr_from_device(DEVICE *dev, JCR *jcr)
-{
- if (!jcr->prev_dev) {
- dev->attached_jcrs = jcr->next_dev;
- } else {
- jcr->prev_dev->next_dev = jcr->next_dev;
- }
- if (jcr->next_dev) {
- jcr->next_dev->prev_dev = jcr->prev_dev;
- }
- jcr->next_dev = jcr->prev_dev = NULL;
- Dmsg1(100, "Detached Job %s\n", jcr->Job);
-}
-
-JCR *next_attached_jcr(DEVICE *dev, JCR *jcr)
-{
- if (jcr == (JCR *)NULL) {
- return dev->attached_jcrs;
- }
- return jcr->next_dev;
-}
-#endif
-
/*
* This routine initializes the device wait timers
*/
}
return true;
}
+
+void set_os_device_parameters(DEVICE *dev)
+{
+#ifdef HAVE_LINUX_OS
+ struct mtop mt_com;
+ if (dev->min_block_size == dev->max_block_size &&
+ dev->min_block_size == 0) { /* variable block mode */
+ mt_com.mt_op = MTSETBLK;
+ mt_com.mt_count = 0;
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ clrerror_dev(dev, MTSETBLK);
+ }
+ mt_com.mt_op = MTSETDRVBUFFER;
+ mt_com.mt_count = MT_ST_CLEARBOOLEANS;
+ if (!dev_cap(dev, CAP_TWOEOF)) {
+ mt_com.mt_count |= MT_ST_TWO_FM;
+ }
+ if (dev_cap(dev, CAP_EOM)) {
+ mt_com.mt_count |= MT_ST_FAST_MTEOM;
+ }
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ clrerror_dev(dev, MTSETBLK);
+ }
+ }
+ return;
+#endif
+
+#ifdef HAVE_NETBSD_OS
+ struct mtop mt_com;
+ if (dev->min_block_size == dev->max_block_size &&
+ dev->min_block_size == 0) { /* variable block mode */
+ mt_com.mt_op = MTSETBSIZ;
+ mt_com.mt_count = 0;
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ clrerror_dev(dev, MTSETBSIZ);
+ }
+ /* Get notified at logical end of tape */
+ mt_com.mt_op = MTEWARN;
+ mt_com.mt_count = 1;
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ clrerror_dev(dev, MTEWARN);
+ }
+ }
+ return;
+#endif
+
+#if HAVE_FREEBSD_OS || HAVE_OPENBSD_OS
+ struct mtop mt_com;
+ if (dev->min_block_size == dev->max_block_size &&
+ dev->min_block_size == 0) { /* variable block mode */
+ mt_com.mt_op = MTSETBSIZ;
+ mt_com.mt_count = 0;
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ clrerror_dev(dev, MTSETBSIZ);
+ }
+ }
+ return;
+#endif
+
+#ifdef HAVE_SUN_OS
+ struct mtop mt_com;
+ if (dev->min_block_size == dev->max_block_size &&
+ dev->min_block_size == 0) { /* variable block mode */
+ mt_com.mt_op = MTSRSZ;
+ mt_com.mt_count = 0;
+ if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
+ clrerror_dev(dev, MTSRSZ);
+ }
+ }
+ return;
+#endif
+
+}