*
* Unfortunately, I have had to add more and more complication
* to this code. This was not foreseen as noted above, and as
- * a consequence has lead to something more contored than is
+ * a consequence has lead to something more contorted than is
* really necessary -- KES. Note, this contortion has been
* corrected to a large extent by a rewrite (Apr MMI).
+ *
+ * Version $Id$
*/
/*
Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
*/
/*
- * Handling I/O errors and end of tape conditions is a bit tricky.
+ * Handling I/O errors and end of tape conditions are a bit tricky.
* This is how it is currently done when writting.
* On either an I/O error or end of tape,
* we will stop writing on the physical device (no I/O recovery is
* thus we neither allocate it nor free it. This allows
* the caller to put the packet in shared memory.
*
- * Note, for a tape, the dev_name is the device name
+ * Note, for a tape, the device->device_name is the device name
* (e.g. /dev/nst0), and for a file, the device name
* is the directory in which the file will be placed.
*
*/
DEVICE *
-init_dev(DEVICE *dev, char *dev_name)
+init_dev(DEVICE *dev, DEVRES *device)
{
struct stat statp;
int tape;
int errstat;
/* Check that device is available */
- if (stat(dev_name, &statp) < 0) {
+ if (stat(device->device_name, &statp) < 0) {
if (dev) {
dev->dev_errno = errno;
}
- Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", dev_name, strerror(errno));
+ Emsg2(M_FATAL, 0, "Unable to stat device %s : %s\n", device->device_name,
+ strerror(errno));
return NULL;
}
tape = FALSE;
if (dev) {
dev->dev_errno = ENODEV;
}
- Emsg2(M_FATAL, 0, "%s is an unknown device type. Must be tape or directory. st_mode=%x\n",
+ Emsg2(M_FATAL, 0, _("%s is an unknown device type. Must be tape or directory. st_mode=%x\n"),
dev_name, statp.st_mode);
return NULL;
}
if (tape) {
dev->state |= ST_TAPE;
}
- dev->dev_name = (char *) get_memory(strlen(dev_name)+1);
- strcpy(dev->dev_name, dev_name);
- dev->errmsg = (char *) get_pool_memory(PM_EMSG);
+ /* Copy user supplied device parameters from Resource */
+ dev->dev_name = get_memory(strlen(device->device_name)+1);
+ strcpy(dev->dev_name, device->device_name);
+ dev->capabilities = device->cap_bits;
+ dev->min_block_size = device->min_block_size;
+ dev->max_block_size = device->max_block_size;
+ dev->max_volume_jobs = device->max_volume_jobs;
+ dev->max_volume_files = device->max_volume_files;
+ dev->max_volume_size = device->max_volume_size;
+ dev->max_file_size = device->max_file_size;
+ dev->volume_capacity = device->volume_capacity;
+ dev->max_rewind_wait = device->max_rewind_wait;
+ dev->max_open_wait = device->max_open_wait;
+ dev->device = device;
+
+ if (dev->max_block_size > 1000000) {
+ Emsg3(M_ERROR, 0, _("Block size %u on device %s is too large, using default %u\n"),
+ dev->max_block_size, dev->dev_name, DEFAULT_BLOCK_SIZE);
+ dev->max_block_size = 0;
+ }
+ if (dev->max_block_size % TAPE_BSIZE != 0) {
+ Emsg2(M_WARNING, 0, _("Max block size %u not multiple of device %s block size.\n"),
+ dev->max_block_size, dev->dev_name);
+ }
+
+ dev->errmsg = get_pool_memory(PM_EMSG);
*dev->errmsg = 0;
if ((errstat = pthread_mutex_init(&dev->mutex, NULL)) != 0) {
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"), strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_cond_init(&dev->wait, NULL)) != 0) {
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"), strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
if ((errstat = pthread_cond_init(&dev->wait_next_vol, NULL)) != 0) {
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"), strerror(errstat));
Emsg0(M_FATAL, 0, dev->errmsg);
}
dev->fd = -1;
int
open_dev(DEVICE *dev, char *VolName, int mode)
{
- char *archive_name;
+ POOLMEM *archive_name;
if (dev->state & ST_OPENED) {
/*
return -1;
}
dev->use_count++;
- Mmsg2(&dev->errmsg, "WARNING!!!! device %s opened %d times!!!\n",
+ Mmsg2(&dev->errmsg, _("WARNING!!!! device %s opened %d times!!!\n"),
dev->dev_name, dev->use_count);
Emsg0(M_WARNING, 0, dev->errmsg);
return dev->fd;
dev->dev_name, dev->VolCatInfo.VolCatName);
dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
if (dev->state & ST_TAPE) {
+ int timeout;
Dmsg0(29, "open_dev: device is tape\n");
if (mode == READ_WRITE) {
dev->mode = O_RDWR | O_BINARY;
} else {
dev->mode = O_RDONLY | O_BINARY;
}
- if ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) {
+ timeout = dev->max_open_wait;
+ errno = 0;
+ while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) {
+ if (errno == EBUSY && timeout-- > 0) {
+ Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, strerror(errno));
+ sleep(1);
+ continue;
+ }
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "stored: unable to open device %s: ERR=%s\n",
+ Mmsg2(&dev->errmsg, _("stored: unable to open device %s: ERR=%s\n"),
dev->dev_name, strerror(dev->dev_errno));
Emsg0(M_FATAL, 0, dev->errmsg);
- } else {
+ break;
+ }
+ if (dev->fd >= 0) {
dev->dev_errno = 0;
dev->state |= ST_OPENED;
dev->use_count++;
}
Dmsg1(29, "open_dev: tape %d opened\n", dev->fd);
} else {
- archive_name = (char *) get_pool_memory(PM_FNAME);
+ /*
+ * Handle opening of file
+ */
+ archive_name = get_pool_memory(PM_FNAME);
strcpy(archive_name, dev->dev_name);
if (archive_name[strlen(archive_name)] != '/') {
strcat(archive_name, "/");
}
if ((dev->fd = open(archive_name, dev->mode, MODE_RW)) < 0) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "Could not open: %s, ERR=%s\n", archive_name, strerror(dev->dev_errno));
+ Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name, strerror(dev->dev_errno));
Emsg0(M_FATAL, 0, dev->errmsg);
} else {
dev->dev_errno = 0;
Dmsg0(29, "rewind_dev\n");
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg1(&dev->errmsg, "Bad call to rewind_dev. Device %s not open\n",
+ Mmsg1(&dev->errmsg, _("Bad call to rewind_dev. Device %s not open\n"),
dev->dev_name);
- Emsg0(M_ABORT, 0, dev->errmsg);
+ Emsg0(M_FATAL, 0, dev->errmsg);
return 0;
}
dev->state &= ~(ST_APPEND|ST_READ|ST_EOT | ST_EOF | ST_WEOT); /* remove EOF/EOT flags */
dev->block_num = dev->file = 0;
+ dev->file_addr = 0;
if (dev->state & ST_TAPE) {
mt_com.mt_op = MTREW;
mt_com.mt_count = 1;
sleep(5);
continue;
}
- Mmsg2(&dev->errmsg, "Rewind error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("Rewind error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return 0;
}
break;
}
} else {
- if (lseek(dev->fd, 0, SEEK_SET) < 0) {
+ if (lseek(dev->fd, (off_t)0, SEEK_SET) < 0) {
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 0;
}
struct mtop mt_com;
struct mtget mt_stat;
int stat = 0;
- int32_t pos;
+ off_t pos;
Dmsg0(29, "eod_dev\n");
if (dev->state & ST_EOT) {
}
dev->state &= ~(ST_EOF); /* remove EOF flags */
dev->block_num = dev->file = 0;
+ dev->file_addr = 0;
if (!(dev->state & ST_TAPE)) {
- pos = lseek(dev->fd, 0, SEEK_END);
- if (pos > 0) {
+ pos = lseek(dev->fd, (off_t)0, SEEK_END);
+// Dmsg1(000, "====== Seek to %lld\n", pos);
+ if (pos >= 0) {
update_pos_dev(dev);
dev->state |= ST_EOT;
return 1;
Dmsg1(50, "ioctl error: %s\n", strerror(dev->dev_errno));
clrerror_dev(dev, mt_com.mt_op);
update_pos_dev(dev);
- Mmsg2(&dev->errmsg, "ioctl MTEOM error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTEOM error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return 0;
}
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "ioctl MTIOCGET error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return 0;
}
}
while (!(dev->state & ST_EOT)) {
Dmsg0(200, "Do fsf 1\n");
- if (fsf_dev(dev, 1) < 0) {
- Dmsg0(200, "fsf_dev return < 0\n");
+ if (!fsf_dev(dev, 1)) {
+ Dmsg0(200, "fsf_dev error.\n");
return 0;
}
}
#ifdef xxxx
struct mtget mt_stat;
#endif
- int32_t pos;
+ off_t pos;
int stat = 0;
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad device call. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad device call. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return 0;
}
/* Find out where we are */
if (!(dev->state & ST_TAPE)) {
dev->file = 0;
- pos = lseek(dev->fd, 0, SEEK_CUR);
+ dev->file_addr = 0;
+ pos = lseek(dev->fd, (off_t)0, SEEK_CUR);
if (pos < 0) {
- Dmsg1(200, "Seek error: ERR=%s\n", strerror(dev->dev_errno));
- pos = 0;
+ Dmsg1(000, "Seek error: ERR=%s\n", strerror(dev->dev_errno));
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));
} else {
stat = 1;
+ dev->file_addr = pos;
}
return stat;
}
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
Dmsg1(50, "MTIOCGET error: %s\n", strerror(dev->dev_errno));
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "ioctl MTIOCGET error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
} else {
stat = 1;
Dmsg2(-20," file=%d block=%d\n", dev->file, dev->block_num);
if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) < 0) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "ioctl MTIOCGET error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return 0;
}
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad call to load_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to load_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return 0;
}
#ifndef MTLOAD
Dmsg0(200, "stored: MTLOAD command not available\n");
dev->dev_errno = ENOTTY; /* function not available */
- Mmsg2(&dev->errmsg, "ioctl MTLOAD error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno)); return 0;
return 0;
#else
dev->block_num = dev->file = 0;
+ dev->file_addr = 0;
mt_com.mt_op = MTLOAD;
mt_com.mt_count = 1;
if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "ioctl MTLOAD error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno)); return 0;
}
return 1;
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad call to load_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to load_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return 0;
}
}
dev->block_num = dev->file = 0;
+ dev->file_addr = 0;
+#ifdef MTUNLOCK
+ mt_com.mt_op = MTUNLOCK;
+ mt_com.mt_count = 1;
+ ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
+#endif
mt_com.mt_op = MTOFFL;
mt_com.mt_count = 1;
if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
dev->dev_errno = errno;
- Mmsg2(&dev->errmsg, "ioctl MTOFFL error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
return 0;
}
+ Dmsg1(100, "Offlined device %s\n", dev->dev_name);
return 1;
}
/*
* Foward space a file
+ * Returns: 1 on success
+ * 0 on failure
*/
int
fsf_dev(DEVICE *dev, int num)
{
struct mtop mt_com;
- int stat;
+ int stat = 0;
char rbuf[1024];
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad call to fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
- return -1;
+ return 0;
}
if (!(dev->state & ST_TAPE)) {
- return 0;
+ return 1;
}
if (dev->state & ST_EOT) {
dev->dev_errno = 0;
- Mmsg1(&dev->errmsg, "Device %s at End of Tape.\n", dev->dev_name);
- return -1;
+ Mmsg1(&dev->errmsg, _("Device %s at End of Tape.\n"), dev->dev_name);
+ return 0;
}
if (dev->state & ST_EOF)
Dmsg0(200, "ST_EOF set on entry to FSF\n");
dev->state |= ST_EOT;
clrerror_dev(dev, -1);
Dmsg1(200, "Set ST_EOT read error %d\n", dev->dev_errno);
- Mmsg2(&dev->errmsg, "read error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("read error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
Dmsg1(200, "%s", dev->errmsg);
break;
} else {
dev->state |= ST_EOF;
dev->file++;
+ dev->file_addr = 0;
continue;
}
} else { /* Got data */
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",
+ Mmsg2(&dev->errmsg, _("ioctl MTFSF error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
Dmsg0(200, "Got < 0 for MT_FSF\n");
Dmsg1(200, "%s", dev->errmsg);
} else {
dev->state |= ST_EOF; /* just read EOF */
dev->file++;
+ dev->file_addr = 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);
stat = -1;
} else {
stat = 0;
if (dev->state & ST_EOT)
Dmsg0(200, "ST_EOT set on exit FSF\n");
Dmsg1(200, "Return from FSF file=%d\n", dev->file);
- return stat;
+ return stat == 0 ? 1 : 0;
}
/*
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad call to fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return -1;
}
Dmsg0(29, "bsf_dev\n");
dev->state &= ~(ST_EOT|ST_EOF);
dev->file -= num;
+ dev->file_addr = 0;
mt_com.mt_op = MTBSF;
mt_com.mt_count = num;
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 fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return -1;
}
} else {
dev->state |= ST_EOF; /* assume EOF */
dev->file++;
+ dev->file_addr = 0;
}
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);
/*
* Backward space a record
+ * Returns: 0 on success
+ * -1 on failure
*/
int
bsr_dev(DEVICE *dev, int num)
if (dev->fd < 0) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad call to fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return -1;
}
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 fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return -1;
}
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat == 0) {
dev->file++;
+ dev->file_addr = 0;
} else {
clrerror_dev(dev, MTWEOF);
- Mmsg2(&dev->errmsg, "ioctl MTWEOF error on %s. ERR=%s.\n",
+ Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
}
return stat;
}
if (msg != NULL) {
dev->dev_errno = ENOSYS;
- Mmsg1(&dev->errmsg, "This device does not support %s.\n", msg);
+ Mmsg1(&dev->errmsg, _("This device does not support %s.\n"), msg);
Emsg0(M_ERROR, 0, dev->errmsg);
}
}
static void do_close(DEVICE *dev)
{
+
Dmsg0(29, "really close_dev\n");
close(dev->fd);
/* Clean up device packet so it can be reused */
dev->fd = -1;
dev->state &= ~(ST_OPENED|ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
- dev->block_num = 0;
- dev->file = 0;
- dev->LastBlockNumWritten = 0;
+ dev->file = dev->block_num = 0;
+ dev->file_addr = 0;
+ dev->EndFile = dev->EndBlock = 0;
memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
+ dev->use_count--;
}
/*
close_dev(DEVICE *dev)
{
if (!dev) {
- Mmsg0(&dev->errmsg, "Bad call to fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return;
}
do_close(dev);
} else {
Dmsg0(29, "close_dev but in use so leave open.\n");
+ dev->use_count--;
}
- dev->use_count--;
}
+/*
+ * Used when unmounting the device
+ */
void force_close_dev(DEVICE *dev)
{
if (!dev) {
- Mmsg0(&dev->errmsg, "Bad call to fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return;
}
Dmsg0(29, "really close_dev\n");
do_close(dev);
- dev->use_count--;
+}
+
+int truncate_dev(DEVICE *dev)
+{
+ if (dev->state & ST_TAPE) {
+ return 1;
+ }
+ if (ftruncate(dev->fd, 0) != 0) {
+ Mmsg1(&dev->errmsg, _("Unable to truncate device. ERR=%s\n"), strerror(errno));
+ return 0;
+ }
+ return 1;
}
int
{
if (!dev) {
dev->dev_errno = EBADF;
- Mmsg0(&dev->errmsg, "Bad call to fsf_dev. Archive not open\n");
+ Mmsg0(&dev->errmsg, _("Bad call to fsf_dev. Archive not open\n"));
Emsg0(M_FATAL, 0, dev->errmsg);
return;
}
dev->dev_name = NULL;
}
if (dev->errmsg) {
- free_memory(dev->errmsg);
+ free_pool_memory(dev->errmsg);
dev->errmsg = NULL;
}
+#ifdef NEW_LOCK
+ rwl_destroy(&dev->lock);
+#endif
pthread_mutex_destroy(&dev->mutex);
pthread_cond_destroy(&dev->wait);
pthread_cond_destroy(&dev->wait_next_vol);
if (dev->state & ST_MALLOC) {
- free_memory(dev);
+ free_pool_memory((POOLMEM *)dev);
+ }
+}
+
+
+/* To make following two functions more readable */
+
+#define attached_jcrs ((JCR *)(dev->attached_jcrs))
+
+void attach_jcr_to_device(DEVICE *dev, JCR *jcr)
+{
+ jcr->prev_dev = NULL;
+ jcr->next_dev = attached_jcrs;
+ if (attached_jcrs) {
+ attached_jcrs->prev_dev = jcr;
+ }
+ attached_jcrs = jcr;
+ Dmsg1(100, "Attached Job %s\n", jcr->Job);
+}
+
+void detach_jcr_from_device(DEVICE *dev, JCR *jcr)
+{
+ if (!jcr->prev_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 == NULL) {
+ return attached_jcrs;
}
+ return jcr->next_dev;
}