* Version $Id$
*/
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2002-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
if (dev->state & ST_READ) {
dev->state &= ~ST_READ; /* clear read bit */
- if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN)) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
close_dev(dev);
Dmsg0(200, "dir_update_vol_info. Release0\n");
dir_update_volume_info(jcr, &dev->VolCatInfo, 0); /* send Volume info to Director */
- if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN)) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
close_dev(dev);
strcpy(jcr->VolumeName, vol->VolCatName); /* set desired VolumeName */
Dmsg2(200, "do_reqest_vol_info got slot=%d Volume=%s\n",
- vol->Slot, vol->VolCatName);
+ vol->Slot, vol->VolCatName);
return 1;
}
* removable media, return now, otherwise wait
* for the operator to mount the media.
*/
- if (jcr->VolumeName[0] && !(dev->capabilities & CAP_REM) &&
- dev->capabilities & CAP_LABEL) {
+ if (jcr->VolumeName[0] && !dev_cap(dev, CAP_REM) && dev_cap(dev, CAP_LABEL)) {
Dmsg0(190, "Return 1 from mount without wait.\n");
return 1;
}
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
* then re-read it and verify that the block number is
* correct.
*/
- if (dev->state & ST_TAPE && dev->capabilities & CAP_BSR) {
+ if (dev->state & ST_TAPE && dev_cap(dev, CAP_BSR)) {
/* Now back up over what we wrote and read the last block */
if (bsf_dev(dev, 1) != 0 || bsf_dev(dev, 1) != 0) {
* Version $Id$
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
dev->use_count++;
Mmsg2(&dev->errmsg, _("WARNING!!!! device %s opened %d times!!!\n"),
dev->dev_name, dev->use_count);
- Emsg0(M_WARNING, 0, dev->errmsg);
+ Emsg1(M_WARNING, 0, "%s", dev->errmsg);
return dev->fd;
}
if (VolName) {
if (dev->state & (ST_TAPE|ST_FIFO)) {
int timeout;
Dmsg0(29, "open_dev: device is tape\n");
- if (mode == READ_WRITE) {
+ if (mode == OPEN_READ_WRITE) {
dev->mode = O_RDWR | O_BINARY;
- } else {
+ } else if (mode == OPEN_READ_ONLY) {
dev->mode = O_RDONLY | O_BINARY;
+ } else if (mode == OPEN_WRITE_ONLY) {
+ dev->mode = O_WRONLY | O_BINARY;
+ } else {
+ Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
}
timeout = dev->max_open_wait;
errno = 0;
+ /* If busy retry each second for max_open_wait seconds */
while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) {
+ if (errno == EAGAIN) {
+ continue;
+ }
if (errno == EBUSY && timeout-- > 0) {
Dmsg2(100, "Device %s busy. ERR=%s\n", dev->dev_name, strerror(errno));
sleep(1);
}
pm_strcat(&archive_name, VolName);
Dmsg1(29, "open_dev: device is disk %s\n", archive_name);
- if (mode == READ_WRITE) {
+ if (mode == OPEN_READ_WRITE) {
dev->mode = O_CREAT | O_RDWR | O_BINARY;
- } else {
+ } else if (mode == OPEN_READ_ONLY) {
dev->mode = O_RDONLY | O_BINARY;
+ } else if (mode == OPEN_WRITE_ONLY) {
+ dev->mode = O_WRONLY | O_BINARY;
+ } else {
+ Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
}
if ((dev->fd = open(archive_name, dev->mode, MODE_RW)) < 0) {
dev->dev_errno = errno;
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/* #define NEW_LOCK 1 */
-#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
+#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
#define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state))
-#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
+#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
#define lock_device(d) _lock_device(__FILE__, __LINE__, (d))
#define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d))
/* Arguments to open_dev() */
#define READ_WRITE 0
#define READ_ONLY 1
+#define OPEN_READ_WRITE 0
+#define OPEN_READ_ONLY 1
+#define OPEN_WRITE_ONLY 2
/* Generic status bits returned from status_dev() */
-#define MT_TAPE (1<<0) /* is tape device */
-#define MT_EOF (1<<1) /* just read EOF */
-#define MT_BOT (1<<2) /* at beginning of tape */
-#define MT_EOT (1<<3) /* end of tape reached */
-#define MT_SM (1<<4) /* DDS setmark */
-#define MT_EOD (1<<5) /* DDS at end of data */
-#define MT_WR_PROT (1<<6) /* tape write protected */
-#define MT_ONLINE (1<<7) /* tape online */
-#define MT_DR_OPEN (1<<8) /* tape door open */
-#define MT_IM_REP_EN (1<<9) /* immediate report enabled */
+#define MT_TAPE (1<<0) /* is tape device */
+#define MT_EOF (1<<1) /* just read EOF */
+#define MT_BOT (1<<2) /* at beginning of tape */
+#define MT_EOT (1<<3) /* end of tape reached */
+#define MT_SM (1<<4) /* DDS setmark */
+#define MT_EOD (1<<5) /* DDS at end of data */
+#define MT_WR_PROT (1<<6) /* tape write protected */
+#define MT_ONLINE (1<<7) /* tape online */
+#define MT_DR_OPEN (1<<8) /* tape door open */
+#define MT_IM_REP_EN (1<<9) /* immediate report enabled */
+/* Test capabilities */
+#define dev_cap(dev, cap) ((dev)->capabilities & (cap))
+
/* Bits for device capabilities */
-#define CAP_EOF 0x0001 /* has MTWEOF */
-#define CAP_BSR 0x0002 /* has MTBSR */
-#define CAP_BSF 0x0004 /* has MTBSF */
-#define CAP_FSR 0x0008 /* has MTFSR */
-#define CAP_FSF 0x0010 /* has MTFSF */
-#define CAP_EOM 0x0020 /* has MTEOM */
-#define CAP_REM 0x0040 /* is removable media */
-#define CAP_RACCESS 0x0080 /* is random access device */
-#define CAP_AUTOMOUNT 0x0100 /* Read device at start to see what is there */
-#define CAP_LABEL 0x0200 /* Label blank tapes */
-#define CAP_ANONVOLS 0x0400 /* Mount without knowing volume name */
-#define CAP_ALWAYSOPEN 0x0800 /* always keep device open */
+#define CAP_EOF 0x0001 /* has MTWEOF */
+#define CAP_BSR 0x0002 /* has MTBSR */
+#define CAP_BSF 0x0004 /* has MTBSF */
+#define CAP_FSR 0x0008 /* has MTFSR */
+#define CAP_FSF 0x0010 /* has MTFSF */
+#define CAP_EOM 0x0020 /* has MTEOM */
+#define CAP_REM 0x0040 /* is removable media */
+#define CAP_RACCESS 0x0080 /* is random access device */
+#define CAP_AUTOMOUNT 0x0100 /* Read device at start to see what is there */
+#define CAP_LABEL 0x0200 /* Label blank tapes */
+#define CAP_ANONVOLS 0x0400 /* Mount without knowing volume name */
+#define CAP_ALWAYSOPEN 0x0800 /* always keep device open */
#define CAP_AUTOCHANGER 0x1000 /* AutoChanger */
#define CAP_OFFLINEUNMOUNT 0x2000 /* Offline before unmount */
-#define CAP_STREAM 0x4000 /* Stream device */
+#define CAP_STREAM 0x4000 /* Stream device */
+/* Test state */
+#define dev_state(dev, state) ((dev)->state & (state))
/* Device state bits */
-#define ST_OPENED 0x0001 /* set when device opened */
-#define ST_TAPE 0x0002 /* is a tape device */
-#define ST_FILE 0x0004 /* is a file device */
-#define ST_FIFO 0x0008 /* is a fifo device */
-#define ST_PROG 0x0010 /* is a program device */
-#define ST_LABEL 0x0020 /* label found */
+#define ST_OPENED 0x0001 /* set when device opened */
+#define ST_TAPE 0x0002 /* is a tape device */
+#define ST_FILE 0x0004 /* is a file device */
+#define ST_FIFO 0x0008 /* is a fifo device */
+#define ST_PROG 0x0010 /* is a program device */
+#define ST_LABEL 0x0020 /* label found */
#define ST_MALLOC 0x0040 /* dev packet malloc'ed in init_dev() */
-#define ST_APPEND 0x0080 /* ready for Bacula append */
-#define ST_READ 0x0100 /* ready for Bacula read */
-#define ST_EOT 0x0200 /* at end of tape */
-#define ST_WEOT 0x0400 /* Got EOT on write */
-#define ST_EOF 0x0800 /* Read EOF i.e. zero bytes */
-#define ST_NEXTVOL 0x1000 /* Start writing on next volume */
-#define ST_SHORT 0x2000 /* Short block read */
+#define ST_APPEND 0x0080 /* ready for Bacula append */
+#define ST_READ 0x0100 /* ready for Bacula read */
+#define ST_EOT 0x0200 /* at end of tape */
+#define ST_WEOT 0x0400 /* Got EOT on write */
+#define ST_EOF 0x0800 /* Read EOF i.e. zero bytes */
+#define ST_NEXTVOL 0x1000 /* Start writing on next volume */
+#define ST_SHORT 0x2000 /* Short block read */
/* dev_blocked states (mutually exclusive) */
#define BST_NOT_BLOCKED 0 /* not blocked */
-#define BST_UNMOUNTED 1 /* User unmounted device */
+#define BST_UNMOUNTED 1 /* User unmounted device */
#define BST_WAITING_FOR_SYSOP 2 /* Waiting for operator to mount tape */
#define BST_DOING_ACQUIRE 3 /* Opening/validating/moving tape */
#define BST_WRITING_LABEL 4 /* Labeling a tape */
/* Volume Catalog Information structure definition */
typedef struct s_volume_catalog_info {
/* Media info for the current Volume */
- uint32_t VolCatJobs; /* number of jobs on this Volume */
- uint32_t VolCatFiles; /* Number of files */
- uint32_t VolCatBlocks; /* Number of blocks */
- uint64_t VolCatBytes; /* Number of bytes written */
- uint32_t VolCatMounts; /* Number of mounts this volume */
- uint32_t VolCatErrors; /* Number of errors this volume */
- uint32_t VolCatWrites; /* Number of writes this volume */
- uint32_t VolCatReads; /* Number of reads this volume */
- uint32_t VolCatRecycles; /* Number of recycles this volume */
- int32_t Slot; /* Slot in changer */
- uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */
- uint32_t VolCatMaxFiles; /* Maximum files to write to volume */
- uint64_t VolCatMaxBytes; /* Max bytes to write to volume */
+ uint32_t VolCatJobs; /* number of jobs on this Volume */
+ uint32_t VolCatFiles; /* Number of files */
+ uint32_t VolCatBlocks; /* Number of blocks */
+ uint64_t VolCatBytes; /* Number of bytes written */
+ uint32_t VolCatMounts; /* Number of mounts this volume */
+ uint32_t VolCatErrors; /* Number of errors this volume */
+ uint32_t VolCatWrites; /* Number of writes this volume */
+ uint32_t VolCatReads; /* Number of reads this volume */
+ uint32_t VolCatRecycles; /* Number of recycles this volume */
+ int32_t Slot; /* Slot in changer */
+ uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */
+ uint32_t VolCatMaxFiles; /* Maximum files to write to volume */
+ uint64_t VolCatMaxBytes; /* Max bytes to write to volume */
uint64_t VolCatCapacityBytes; /* capacity estimate */
- char VolCatStatus[20]; /* Volume status */
+ char VolCatStatus[20]; /* Volume status */
char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */
} VOLUME_CAT_INFO;
typedef struct s_steal_lock {
- pthread_t no_wait_id; /* id of no wait thread */
- int dev_blocked; /* state */
+ pthread_t no_wait_id; /* id of no wait thread */
+ int dev_blocked; /* state */
} bsteal_lock_t;
/* Device structure definition */
typedef struct s_device {
- struct s_device *next; /* pointer to next open device */
- void *attached_jcrs; /* attached JCR list */
+ struct s_device *next; /* pointer to next open device */
+ void *attached_jcrs; /* attached JCR list */
#ifdef NEW_LOCK
- brwlock_t lock; /* new device locking mechanism */
+ brwlock_t lock; /* new device locking mechanism */
#endif
- pthread_mutex_t mutex; /* access control */
- pthread_cond_t wait; /* thread wait variable */
+ pthread_mutex_t mutex; /* access control */
+ pthread_cond_t wait; /* thread wait variable */
pthread_cond_t wait_next_vol; /* wait for tape to be mounted */
- pthread_t no_wait_id; /* this thread must not wait */
- int dev_blocked; /* set if we must wait (i.e. change tape) */
- int num_waiting; /* number of threads waiting */
- int num_writers; /* number of writing threads */
- int use_count; /* usage count on this device */
- int fd; /* file descriptor */
- int capabilities; /* capabilities mask */
- int state; /* state mask */
- int dev_errno; /* Our own errno */
- int mode; /* read/write modes */
- char *dev_name; /* device name */
- char *errmsg; /* nicely edited error message */
- uint32_t block_num; /* current block number base 0 */
- uint32_t file; /* current file number base 0 */
- uint64_t file_addr; /* Current file read/write address */
- uint32_t EndBlock; /* last block written */
- uint32_t EndFile; /* last file written */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
- uint64_t max_volume_files; /* max files to put on one volume */
- uint64_t max_volume_size; /* max bytes to put on one volume */
- uint64_t max_file_size; /* max file size to put in one file on volume */
- uint64_t volume_capacity; /* advisory capacity */
- uint32_t max_rewind_wait; /* max secs to allow for rewind */
- uint32_t max_open_wait; /* max secs to allow for open */
- void *device; /* pointer to Device Resource */
-
- VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
- VOLUME_LABEL VolHdr; /* Actual volume label */
+ pthread_t no_wait_id; /* this thread must not wait */
+ int dev_blocked; /* set if we must wait (i.e. change tape) */
+ int num_waiting; /* number of threads waiting */
+ int num_writers; /* number of writing threads */
+ int use_count; /* usage count on this device */
+ int fd; /* file descriptor */
+ int capabilities; /* capabilities mask */
+ int state; /* state mask */
+ int dev_errno; /* Our own errno */
+ int mode; /* read/write modes */
+ char *dev_name; /* device name */
+ char *errmsg; /* nicely edited error message */
+ uint32_t block_num; /* current block number base 0 */
+ uint32_t file; /* current file number base 0 */
+ uint64_t file_addr; /* Current file read/write address */
+ uint32_t EndBlock; /* last block written */
+ uint32_t EndFile; /* last file written */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ uint64_t max_volume_files; /* max files to put on one volume */
+ uint64_t max_volume_size; /* max bytes to put on one volume */
+ uint64_t max_file_size; /* max file size to put in one file on volume */
+ uint64_t volume_capacity; /* advisory capacity */
+ uint32_t max_rewind_wait; /* max secs to allow for rewind */
+ uint32_t max_open_wait; /* max secs to allow for open */
+ void *device; /* pointer to Device Resource */
+
+ VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
+ VOLUME_LABEL VolHdr; /* Actual volume label */
} DEVICE;
* dependent. Arrgggg!
*/
#ifndef MTEOM
-#ifdef MTSEOD
+#ifdef MTSEOD
#define MTEOM MTSEOD
#endif
#ifdef MTEOD
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
} else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
dev->dev_blocked);
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
force_close_dev(dev);
} else { /* device not being used */
Dmsg0(90, "Device not in use, unmounting\n");
block_device(dev, BST_UNMOUNTED);
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
force_close_dev(dev);
* Version $Id$
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#include "stored.h" /* pull in Storage Deamon headers */
/* Forward referenced functions */
-static int create_volume_label(DEVICE *dev, char *VolName);
static void create_volume_label_record(JCR *jcr, DEVICE *dev, DEV_RECORD *rec);
extern char my_name[];
/* Unserialize the record into the Volume Header */
rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
ser_begin(rec->data, SER_LENGTH_Volume_Label);
-#define Fld(x) (dev->VolHdr.x)
- unser_string(Fld(Id));
+ unser_string(dev->VolHdr.Id);
+ unser_uint32(dev->VolHdr.VerNum);
- unser_uint32(Fld(VerNum));
-
- if (Fld(VerNum) >= 11) {
- unser_btime(Fld(label_btime));
- unser_btime(Fld(write_btime));
+ if (dev->VolHdr.VerNum >= 11) {
+ unser_btime(dev->VolHdr.label_btime);
+ unser_btime(dev->VolHdr.write_btime);
} else { /* old way */
- unser_float64(Fld(label_date));
- unser_float64(Fld(label_time));
+ unser_float64(dev->VolHdr.label_date);
+ unser_float64(dev->VolHdr.label_time);
}
- unser_float64(Fld(write_date)); /* Unused with VerNum >= 11 */
- unser_float64(Fld(write_time)); /* Unused with VerNum >= 11 */
+ unser_float64(dev->VolHdr.write_date); /* Unused with VerNum >= 11 */
+ unser_float64(dev->VolHdr.write_time); /* Unused with VerNum >= 11 */
- unser_string(Fld(VolName));
- unser_string(Fld(PrevVolName));
- unser_string(Fld(PoolName));
- unser_string(Fld(PoolType));
- unser_string(Fld(MediaType));
+ unser_string(dev->VolHdr.VolName);
+ unser_string(dev->VolHdr.PrevVolName);
+ unser_string(dev->VolHdr.PoolName);
+ unser_string(dev->VolHdr.PoolType);
+ unser_string(dev->VolHdr.MediaType);
- unser_string(Fld(HostName));
- unser_string(Fld(LabelProg));
- unser_string(Fld(ProgVersion));
- unser_string(Fld(ProgDate));
+ unser_string(dev->VolHdr.HostName);
+ unser_string(dev->VolHdr.LabelProg);
+ unser_string(dev->VolHdr.ProgVersion);
+ unser_string(dev->VolHdr.ProgDate);
ser_end(rec->data, SER_LENGTH_Volume_Label);
-#undef Fld
Dmsg0(90, "ser_read_vol\n");
if (debug_level >= 90) {
dump_volume_label(dev);
rec->data = check_pool_memory_size(rec->data, SER_LENGTH_Volume_Label);
ser_begin(rec->data, SER_LENGTH_Volume_Label);
-#define Fld(x) (dev->VolHdr.x)
- ser_string(Fld(Id));
+ ser_string(dev->VolHdr.Id);
- ser_uint32(Fld(VerNum));
+ ser_uint32(dev->VolHdr.VerNum);
- if (Fld(VerNum >= 11)) {
- ser_btime(Fld(label_btime));
- Fld(write_btime) = get_current_btime();
- ser_btime(Fld(write_btime));
- Fld(write_date) = 0;
- Fld(write_time) = 0;
+ if (dev->VolHdr.VerNum >= 11) {
+ ser_btime(dev->VolHdr.label_btime);
+ dev->VolHdr.write_btime = get_current_btime();
+ ser_btime(dev->VolHdr.write_btime);
+ dev->VolHdr.write_date = 0;
+ dev->VolHdr.write_time = 0;
} else {
/* OLD WAY DEPRECATED */
- ser_float64(Fld(label_date));
- ser_float64(Fld(label_time));
+ ser_float64(dev->VolHdr.label_date);
+ ser_float64(dev->VolHdr.label_time);
get_current_time(&dt);
- Fld(write_date) = dt.julian_day_number;
- Fld(write_time) = dt.julian_day_fraction;
+ dev->VolHdr.write_date = dt.julian_day_number;
+ dev->VolHdr.write_time = dt.julian_day_fraction;
}
- ser_float64(Fld(write_date)); /* 0 if VerNum >= 11 */
- ser_float64(Fld(write_time)); /* 0 if VerNum >= 11 */
+ ser_float64(dev->VolHdr.write_date); /* 0 if VerNum >= 11 */
+ ser_float64(dev->VolHdr.write_time); /* 0 if VerNum >= 11 */
- ser_string(Fld(VolName));
- ser_string(Fld(PrevVolName));
- ser_string(Fld(PoolName));
- ser_string(Fld(PoolType));
- ser_string(Fld(MediaType));
+ ser_string(dev->VolHdr.VolName);
+ ser_string(dev->VolHdr.PrevVolName);
+ ser_string(dev->VolHdr.PoolName);
+ ser_string(dev->VolHdr.PoolType);
+ ser_string(dev->VolHdr.MediaType);
- ser_string(Fld(HostName));
- ser_string(Fld(LabelProg));
- ser_string(Fld(ProgVersion));
- ser_string(Fld(ProgDate));
+ ser_string(dev->VolHdr.HostName);
+ ser_string(dev->VolHdr.LabelProg);
+ ser_string(dev->VolHdr.ProgVersion);
+ ser_string(dev->VolHdr.ProgDate);
ser_end(rec->data, SER_LENGTH_Volume_Label);
rec->data_len = ser_length(rec->data);
- rec->FileIndex = Fld(LabelType);
+ rec->FileIndex = dev->VolHdr.LabelType;
rec->VolSessionId = jcr->VolSessionId;
rec->VolSessionTime = jcr->VolSessionTime;
rec->Stream = jcr->NumVolumes;
Dmsg2(100, "Created Vol label rec: FI=%s len=%d\n", FI_to_ascii(rec->FileIndex),
rec->data_len);
-#undef Fld
}
* Returns: 0 on error
* 1 on success
*/
-static int create_volume_label(DEVICE *dev, char *VolName)
+void create_volume_label(DEVICE *dev, char *VolName)
{
struct date_time dt;
DEVRES *device = (DEVRES *)dev->device;
if (debug_level >= 90) {
dump_volume_label(dev);
}
- return 1;
}
/*
Dmsg0(99, "write_volume_label()\n");
- if (!create_volume_label(dev, VolName)) {
- return 0;
- }
+ create_volume_label(dev, VolName);
strcpy(dev->VolHdr.MediaType, device->media_type);
bstrncpy(dev->VolHdr.VolName, VolName, sizeof(dev->VolHdr.VolName));
bstrncpy(dev->VolHdr.PoolName, PoolName, sizeof(dev->VolHdr.PoolName));
if (label->VerNum >= 11) {
unser_btime(label->write_btime);
} else {
- unser_float64(label->write_date);
+ unser_float64(label->write_date);
}
unser_float64(label->write_time);
unser_string(label->PoolName);
bstrftime(dt, sizeof(dt), btime_to_unix(label.write_btime));
Pmsg1(-1, _("Date written : %s\n"), dt);
} else {
- dt.julian_day_number = label.write_date;
- dt.julian_day_fraction = label.write_time;
- tm_decode(&dt, &tm);
+ dt.julian_day_number = label.write_date;
+ dt.julian_day_fraction = label.write_time;
+ tm_decode(&dt, &tm);
Pmsg5(-1, _("\
Date written : %04d-%02d-%02d at %02d:%02d\n"),
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min);
dev->state &= ~ST_LABEL; /* label not yet read */
jcr->VolumeName[0] = 0;
- if (!dev_is_tape(dev) || !(dev->capabilities & CAP_ALWAYSOPEN)) {
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN)) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
close_dev(dev);
/* If we have not closed the device, then at least rewind the tape */
if (dev->state & ST_OPENED) {
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
if (!rewind_dev(dev)) {
Dmsg0(100, "did not find next volume. Must ask.\n");
}
Dmsg2(100, "After find_next_append. Vol=%s Slot=%d\n",
- jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
+ jcr->VolCatInfo.VolCatName, jcr->VolCatInfo.Slot);
release = 1; /* release if we "recurse" */
/*
jcr->VolFirstFile = jcr->JobFiles; /* first update of Vol FileIndex */
for ( ;; ) {
+ int vol_label_status;
autochanger = autoload_device(jcr, dev, 1, NULL);
if (autochanger) {
ask = 0; /* if autochange no need to ask sysop */
/* Open device */
for ( ; !(dev->state & ST_OPENED); ) {
- if (open_dev(dev, jcr->VolCatInfo.VolCatName, READ_WRITE) < 0) {
- if (dev->dev_errno == EAGAIN || dev->dev_errno == EBUSY) {
- sleep(30);
- }
+ int mode;
+ if (dev_cap(dev, CAP_STREAM)) {
+ mode = OPEN_WRITE_ONLY;
+ } else {
+ mode = OPEN_READ_WRITE;
+ }
+ if (open_dev(dev, jcr->VolCatInfo.VolCatName, mode) < 0) {
Jmsg2(jcr, M_FATAL, 0, _("Unable to open device %s. ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
return 0;
* Now make sure we have the right tape mounted
*/
read_volume:
- switch (read_dev_volume_label(jcr, dev, block)) {
+ /*
+ * If we are writing to a stream device, ASSUME the volume label
+ * is correct.
+ */
+ if (dev_cap(dev, CAP_STREAM)) {
+ vol_label_status = VOL_OK;
+ create_volume_label(dev, jcr->VolumeName);
+ dev->VolHdr.LabelType = PRE_LABEL;
+ } else {
+ vol_label_status = read_dev_volume_label(jcr, dev, block);
+ }
+ switch (vol_label_status) {
case VOL_OK:
Dmsg1(100, "Vol OK name=%s\n", jcr->VolumeName);
memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(jcr->VolCatInfo));
case VOL_IO_ERROR:
Dmsg1(500, "Vol NO_LABEL or IO_ERROR name=%s\n", jcr->VolumeName);
/* If permitted, create a label */
- if (dev->capabilities & CAP_LABEL) {
+ if (dev_cap(dev, CAP_LABEL)) {
Dmsg0(100, "Create volume label\n");
if (!write_volume_label_to_dev(jcr, (DEVRES *)dev->device, jcr->VolumeName,
jcr->pool_name)) {
dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
write_volume_label_to_block(jcr, dev, block);
/*
- * Write the block now to ensure we have write permission.
+ * If we are not dealing with a streaming device,
+ * write the block now to ensure we have write permission.
* It is better to find out now rather than later.
*/
- dev->VolCatInfo.VolCatBytes = 0;
- if (!rewind_dev(dev)) {
- Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s. ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- }
- if (recycle) {
- if (!truncate_dev(dev)) {
- Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device %s. ERR=%s\n"),
+ if (!dev_cap(dev, CAP_STREAM)) {
+ dev->VolCatInfo.VolCatBytes = 0;
+ if (!rewind_dev(dev)) {
+ Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device %s. ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
}
- }
- /* Attempt write to check write permission */
- if (!write_block_to_dev(jcr, dev, block)) {
- Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s. ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- goto mount_next_vol;
- }
- if (!rewind_dev(dev)) {
- Jmsg2(jcr, M_ERROR, 0, _("Unable to rewind device %s. ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- goto mount_next_vol;
- }
+ if (recycle) {
+ if (!truncate_dev(dev)) {
+ Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device %s. ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ }
+ }
+ /* Attempt write to check write permission */
+ if (!write_block_to_dev(jcr, dev, block)) {
+ Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s. ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ goto mount_next_vol;
+ }
+ if (!rewind_dev(dev)) {
+ Jmsg2(jcr, M_ERROR, 0, _("Unable to rewind device %s. ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ goto mount_next_vol;
+ }
- /* Recreate a correct volume label and return it in the block */
- write_volume_label_to_block(jcr, dev, block);
+ /* Recreate a correct volume label and return it in the block */
+ write_volume_label_to_block(jcr, dev, block);
+ }
/* Set or reset Volume statistics */
dev->VolCatInfo.VolCatJobs = 0;
dev->VolCatInfo.VolCatFiles = 0;
* Handle autoloaders here. If we cannot autoload it, we
* will return FALSE to ask the sysop.
*/
- if (writing && dev->capabilities && CAP_AUTOCHANGER && slot <= 0) {
+ if (writing && dev_cap(dev, CAP_AUTOCHANGER) && slot <= 0) {
if (dir) {
return 0; /* For user, bail out right now */
}
/* If bad status or tape we want is not loaded, load it. */
if (status != 0 || loaded != slot) {
- if (dev->capabilities & CAP_OFFLINEUNMOUNT) {
+ if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) {
offline_dev(dev);
}
/* We are going to load a new tape, so close the device */
uint32_t new_VolSessionId();
/* From acquire.c */
-int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int release_device(JCR *jcr, DEVICE *dev);
+int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int release_device(JCR *jcr, DEVICE *dev);
/* From askdir.c */
-int dir_get_volume_info(JCR *jcr, int writing);
-int dir_find_next_appendable_volume(JCR *jcr);
-int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel);
-int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
-int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
-int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
-int dir_send_job_status(JCR *jcr);
-int dir_create_jobmedia_record(JCR *jcr);
+int dir_get_volume_info(JCR *jcr, int writing);
+int dir_find_next_appendable_volume(JCR *jcr);
+int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel);
+int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
+int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
+int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
+int dir_send_job_status(JCR *jcr);
+int dir_create_jobmedia_record(JCR *jcr);
/* authenticate.c */
-int authenticate_director(JCR *jcr);
-int authenticate_filed(JCR *jcr);
+int authenticate_director(JCR *jcr);
+int authenticate_filed(JCR *jcr);
/* From block.c */
-void dump_block(DEV_BLOCK *b, char *msg);
+void dump_block(DEV_BLOCK *b, char *msg);
DEV_BLOCK *new_block(DEVICE *dev);
-void init_block_write(DEV_BLOCK *block);
-void empty_block(DEV_BLOCK *block);
-void free_block(DEV_BLOCK *block);
-int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
-int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
+void init_block_write(DEV_BLOCK *block);
+void empty_block(DEV_BLOCK *block);
+void free_block(DEV_BLOCK *block);
+int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
+int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
/* From butil.c -- utilities for SD tool programs */
-void print_ls_output(char *fname, char *link, int type, struct stat *statp);
+void print_ls_output(char *fname, char *link, int type, struct stat *statp);
JCR *setup_jcr(char *name, char *device, BSR *bsr);
DEVICE *setup_to_access_device(JCR *jcr, int read_access);
-void display_error_status(DEVICE *dev);
+void display_error_status(DEVICE *dev);
DEVRES *find_device_res(char *device_name, int read_access);
/* From dev.c */
-DEVICE *init_dev(DEVICE *dev, DEVRES *device);
-int open_dev(DEVICE *dev, char *VolName, int mode);
-void close_dev(DEVICE *dev);
-void force_close_dev(DEVICE *dev);
-int truncate_dev(DEVICE *dev);
-void term_dev(DEVICE *dev);
-char * strerror_dev(DEVICE *dev);
-void clrerror_dev(DEVICE *dev, int func);
-int update_pos_dev(DEVICE *dev);
-int rewind_dev(DEVICE *dev);
-int load_dev(DEVICE *dev);
-int offline_dev(DEVICE *dev);
-int flush_dev(DEVICE *dev);
-int weof_dev(DEVICE *dev, int num);
-int write_block(DEVICE *dev);
-int write_dev(DEVICE *dev, char *buf, size_t len);
-int read_dev(DEVICE *dev, char *buf, size_t len);
-int status_dev(DEVICE *dev, uint32_t *status);
-int eod_dev(DEVICE *dev);
-int fsf_dev(DEVICE *dev, int num);
-int fsr_dev(DEVICE *dev, int num);
-int bsf_dev(DEVICE *dev, int num);
-int bsr_dev(DEVICE *dev, int num);
-void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
-void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
-JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
+DEVICE *init_dev(DEVICE *dev, DEVRES *device);
+int open_dev(DEVICE *dev, char *VolName, int mode);
+void close_dev(DEVICE *dev);
+void force_close_dev(DEVICE *dev);
+int truncate_dev(DEVICE *dev);
+void term_dev(DEVICE *dev);
+char * strerror_dev(DEVICE *dev);
+void clrerror_dev(DEVICE *dev, int func);
+int update_pos_dev(DEVICE *dev);
+int rewind_dev(DEVICE *dev);
+int load_dev(DEVICE *dev);
+int offline_dev(DEVICE *dev);
+int flush_dev(DEVICE *dev);
+int weof_dev(DEVICE *dev, int num);
+int write_block(DEVICE *dev);
+int write_dev(DEVICE *dev, char *buf, size_t len);
+int read_dev(DEVICE *dev, char *buf, size_t len);
+int status_dev(DEVICE *dev, uint32_t *status);
+int eod_dev(DEVICE *dev);
+int fsf_dev(DEVICE *dev, int num);
+int fsr_dev(DEVICE *dev, int num);
+int bsf_dev(DEVICE *dev, int num);
+int bsr_dev(DEVICE *dev, int num);
+void attach_jcr_to_device(DEVICE *dev, JCR *jcr);
+void detach_jcr_from_device(DEVICE *dev, JCR *jcr);
+JCR *next_attached_jcr(DEVICE *dev, JCR *jcr);
/* Get info about device */
-char * dev_name(DEVICE *dev);
-char * dev_vol_name(DEVICE *dev);
+char * dev_name(DEVICE *dev);
+char * dev_vol_name(DEVICE *dev);
uint32_t dev_block(DEVICE *dev);
uint32_t dev_file(DEVICE *dev);
-int dev_is_tape(DEVICE *dev);
+int dev_is_tape(DEVICE *dev);
/* From device.c */
-int open_device(DEVICE *dev);
-int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int open_device(DEVICE *dev);
+int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
void _lock_device(char *file, int line, DEVICE *dev);
void _unlock_device(char *file, int line, DEVICE *dev);
void _block_device(char *file, int line, DEVICE *dev, int state);
void new_return_device_lock(DEVICE *dev, brwsteal_t *hold);
/* From dircmd.c */
-void connection_request(void *arg);
+void connection_request(void *arg);
/* From fd_cmds.c */
-void run_job(JCR *jcr);
+void run_job(JCR *jcr);
/* From fdmsg.c */
-int bget_msg(BSOCK *sock);
+int bget_msg(BSOCK *sock);
/* From job.c */
-void stored_free_jcr(JCR *jcr);
-void connection_from_filed(void *arg);
-void handle_filed_connection(BSOCK *fd, char *job_name);
+void stored_free_jcr(JCR *jcr);
+void connection_from_filed(void *arg);
+void handle_filed_connection(BSOCK *fd, char *job_name);
/* From label.c */
-int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
-int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
-int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void dump_volume_label(DEVICE *dev);
-void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-int unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
+void create_volume_label(DEVICE *dev, char *VolName);
+int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
+int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
+int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void dump_volume_label(DEVICE *dev);
+void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+int unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
/* From match_bsr.c */
int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
- SESSION_LABEL *sesrec);
+ SESSION_LABEL *sesrec);
/* From mount.c */
-int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
-int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
+int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
+int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
/* From parse_bsr.c */
/* From record.c */
char *FI_to_ascii(int fi);
char *stream_to_ascii(int stream, int fi);
-int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
-void free_record(DEV_RECORD *rec);
+void free_record(DEV_RECORD *rec);
/* From read_record.c */
int read_records(JCR *jcr, DEVICE *dev,
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/* */
#define VERSION "1.29"
#define VSTRING "1"
-#define DATE "17 January 2003"
-#define LSMDATE "17Jan03"
+#define DATE "18 January 2003"
+#define LSMDATE "18Jan03"
/* Debug flags */
#define DEBUG 1