#
-#
-# Copyright (C) 2000-2016 Kern Sibbald
+# Copyright (C) 2000-2018 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#
@MCOMMON@
$(INSTALL_SCRIPT) bacula_config $(DESTDIR)$(scriptdir)/bacula_config
$(INSTALL_SCRIPT) bacula $(DESTDIR)$(sbindir)/bacula
$(INSTALL_SCRIPT) tapealert $(DESTDIR)$(scriptdir)/tapealert
+ $(INSTALL_SCRIPT) isworm $(DESTDIR)$(scriptdir)/isworm
$(INSTALL_SCRIPT) bacula-ctl-dir $(DESTDIR)$(scriptdir)/bacula-ctl-dir
$(INSTALL_SCRIPT) bacula-ctl-fd $(DESTDIR)$(scriptdir)/bacula-ctl-fd
$(INSTALL_SCRIPT) bacula-ctl-sd $(DESTDIR)$(scriptdir)/bacula-ctl-sd
--- /dev/null
+#!/bin/sh
+#
+# Copyright (C) 2000-2018 Kern Sibbald
+# License: BSD 2-Clause; see file LICENSE-FOSS
+#
+# Bacula interface to get worm status of tape
+#
+# isworm %l (control device name)
+#
+# Typical output:
+# sdparm --page=0x1D -f /dev/sg0
+# /dev/st0: HP Ultrium 5-SCSI I5AW [tape]
+# Medium configuration (SSC) mode page:
+# WORMM 1 [cha: n, def: 1, sav: 1]
+# WMLR 1 [cha: n, def: 1, sav: 1]
+# WMFR 2 [cha: n, def: 2, sav: 2]
+#
+# Where WORMM is worm mode
+# WMLR is worm mode label restrictions
+# 0 - No blocks can be overwritten
+# 1 - Some types of format labels may not be overwritten
+# 2 - All format labels can be overwritten
+# WMFR is worm mode filemark restrictions
+# 0-1 - Reserved
+# 2 - Any number of filemarks immediately preceding EOD can be
+# overwritten except file mark closest to BOP (beginning of
+# partition).
+# 3 - Any number of filemarks immediately preceding the EOD
+# can be overwritten
+# 4-FF - Reserved
+#
+
+if [ x$1 = x ] ; then
+ echo "First argument missing. Must be device control name."
+ exit 1
+fi
+
+sdparm=`which sdparm`
+if [ x${sdparm} = x ] ; then
+ echo "sdparm program not found, but is required."
+ exit 0
+fi
+
+#
+# This should be the correct way to determine if the tape is WORM
+# but it does not work for mhvtl. Comment out the next 5 lines
+# and the code that follows will detect correctly on mhtvl.
+#
+worm=`$sdparm --page=0x1D -f $1 |grep " *WORMM"|cut -b12-16|sed "s:^ *::"`
+if [ $? = 0 ] ; then
+ echo $worm
+ exit 0
+fi
+
+tapeinfo=`which tapeinfo`
+if [ x${tapeinfo} = x ] ; then
+ echo "tapeinfo program not found, but is required."
+ exit 1
+fi
+
+#
+# Unfortunately IBM and HP handle the Medium Type differently,
+# so we detect the vendor and get the appropriate Worm flag.
+#
+vendor=`$tapeinfo -f $1|grep "^Vendor ID:"|cut -b13-15`
+if [ x$vendor = xHP ] ; then
+ worm=`$tapeinfo -f $1|grep "^Medium Type: 0x"|cut -b16-16`
+ echo $worm
+ exit 0
+fi
+
+if [ x$vendor = xIBM ] ; then
+ worm=`$tapeinfo -f $1|grep "^Medium Type: 0x"|cut -b17-17`
+ if [ x$worm = xc ]; then
+ echo "1"
+ exit 0
+ fi
+ if [ x$worm = xC ]; then
+ echo "1"
+ exit 0
+ fi
+fi
+echo "0"
+exit 0
" VolErrors=%u VolWrites=%lld MaxVolBytes=%lld EndTime=%lld VolStatus=%10s"
" Slot=%d relabel=%d InChanger=%d VolReadTime=%lld VolWriteTime=%lld"
" VolFirstWritten=%lld VolType=%u VolParts=%d VolCloudParts=%d"
- " LastPartBytes=%lld Enabled=%d\n";
+ " LastPartBytes=%lld Enabled=%d Recycle=%d\n";
static char Create_jobmedia[] = "CatReq JobId=%ld CreateJobMedia\n";
" MaxVolJobs=%u MaxVolFiles=%u InChanger=%d VolReadTime=%s"
" VolWriteTime=%s EndFile=%u EndBlock=%u VolType=%u LabelType=%d"
" MediaId=%s ScratchPoolId=%s VolParts=%d VolCloudParts=%d"
- " LastPartBytes=%lld Enabled=%d\n";
+ " LastPartBytes=%lld Enabled=%d Recycle=%d\n";
static char OK_create[] = "1000 OK CreateJobMedia\n";
mr->VolParts,
mr->VolCloudParts,
mr->LastPartBytes,
- mr->Enabled);
+ mr->Enabled,
+ mr->Recycle);
unbash_spaces(mr->VolumeName);
Dmsg2(100, "Vol Info for %s: %s", jcr->Job, sd->msg);
return stat;
utime_t VolFirstWritten;
utime_t VolLastWritten;
int n;
- int Enabled;
+ int Enabled, Recycle;
JobId_t JobId = 0;
memset(&sdmr, 0, sizeof(sdmr));
&VolLastWritten, &sdmr.VolStatus, &sdmr.Slot, &label, &sdmr.InChanger,
&sdmr.VolReadTime, &sdmr.VolWriteTime, &VolFirstWritten,
&sdmr.VolType, &sdmr.VolParts, &sdmr.VolCloudParts,
- &sdmr.LastPartBytes, &Enabled);
- if (n == 26) {
+ &sdmr.LastPartBytes, &Enabled, &Recycle);
+ if (n == 27) {
db_lock(jcr->db);
Dmsg3(400, "Update media %s oldStat=%s newStat=%s\n", sdmr.VolumeName,
mr.VolStatus, sdmr.VolStatus);
mr.VolCloudParts = sdmr.VolCloudParts;
mr.LastPartBytes = sdmr.LastPartBytes;
mr.Enabled = Enabled; /* byte assignment */
+ mr.Recycle = Recycle; /* byte assignment */
bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus));
if (sdmr.VolReadTime >= 0) {
mr.VolReadTime = sdmr.VolReadTime;
#
-# Copyright (C) 2000-2017 Kern Sibbald
+# Copyright (C) 2000-2018 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#
@MCOMMON@
init_dev.c label.c lock.c match_bsr.c mount.c \
null_dev.c os.c parse_bsr.c read.c read_records.c \
record_read.c record_util.c record_write.c reserve.c \
- scan.c sd_plugins.c spool.c tape_alert.c vol_mgr.c wait.c \
+ scan.c sd_plugins.c spool.c tape_alert.c tape_worm.c vol_mgr.c wait.c \
fifo_dev.c file_dev.c tape_dev.c vtape_dev.c
LIBBACSD_OBJS = $(LIBBACSD_SRCS:.c=.o)
" VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%s VolStatus=%s"
" Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s"
" VolFirstWritten=%s VolType=%u VolParts=%d VolCloudParts=%d"
- " LastPartBytes=%lld Enabled=%d\n";
+ " LastPartBytes=%lld Enabled=%d Recycle=%d\n";
static char Create_jobmedia[] = "CatReq JobId=%ld CreateJobMedia\n";
static char FileAttributes[] = "UpdCat JobId=%ld FileAttributes ";
" Slot=%ld MaxVolJobs=%lu MaxVolFiles=%lu InChanger=%ld"
" VolReadTime=%lld VolWriteTime=%lld EndFile=%lu EndBlock=%lu"
" VolType=%lu LabelType=%ld MediaId=%lld ScratchPoolId=%lld"
- " VolParts=%d VolCloudParts=%d LastPartBytes=%lld Enabled=%d\n";
+ " VolParts=%d VolCloudParts=%d LastPartBytes=%lld Enabled=%d"
+ " Recycle=%d\n";
static char OK_create[] = "1000 OK CreateJobMedia\n";
#ifdef needed
+Note: if you turn this on, be sure to add the Recycle Flag
+
static char Device_update[] = "DevUpd JobId=%ld device=%s "
"append=%d read=%d num_writers=%d "
"open=%d labeled=%d offline=%d "
BSOCK *dir = jcr->dir_bsock;
VOLUME_CAT_INFO vol;
int n;
- int32_t Enabled;
+ int32_t Enabled, Recycle;
int32_t InChanger;
dcr->setVolCatInfo(false);
&vol.EndFile, &vol.EndBlock, &vol.VolCatType,
&vol.LabelType, &vol.VolMediaId, &vol.VolScratchPoolId,
&vol.VolCatParts, &vol.VolCatCloudParts,
- &vol.VolLastPartBytes, &Enabled);
+ &vol.VolLastPartBytes, &Enabled, &Recycle);
Dmsg2(dbglvl, "<dird n=%d %s", n, dir->msg);
- if (n != 30) {
+ if (n != 31) {
Dmsg1(dbglvl, "get_volume_info failed: ERR=%s", dir->msg);
/*
* Note, we can get an error here either because there is
}
vol.InChanger = InChanger; /* bool in structure */
vol.VolEnabled = Enabled; /* bool in structure */
+ vol.VolRecycle = Recycle; /* bool in structure */
vol.is_valid = true;
vol.VolCatBytes = vol.VolCatAmetaBytes + vol.VolCatAdataBytes;
unbash_spaces(vol.VolCatName);
DEVICE *dev = dcr->ameta_dev;
VOLUME_CAT_INFO vol;
char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50], ed7[50], ed8[50];
- int InChanger;
+ int InChanger, Enabled, Recycle;
bool ok = false;
POOL_MEM VolumeName;
// if (update_LastWritten) {
vol.VolLastWritten = time(NULL);
// }
+ /* worm cannot be recycled, ensure catalog correct */
+ if (dev->is_worm() && vol.VolRecycle) {
+ Jmsg(jcr, M_INFO, 0, _("WORM cassette detected: setting Recycle=No on Volume=\"%s\"\n"));
+ vol.VolRecycle = false;
+ }
pm_strcpy(VolumeName, vol.VolCatName);
bash_spaces(VolumeName);
InChanger = vol.InChanger;
+ Enabled = vol.VolEnabled;
+ Recycle = vol.VolRecycle;
/* Insanity test */
if (vol.VolCatHoleBytes > (((uint64_t)2)<<60)) {
Pmsg1(010, "VolCatHoleBytes too big: %lld. Reset to zero.\n",
vol.VolCatParts,
vol.VolCatCloudParts,
vol.VolLastPartBytes,
- vol.VolEnabled);
+ Enabled,
+ Recycle);
Dmsg1(100, ">dird %s", dir->msg);
/* Do not lock device here because it may be locked from label */
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
{
return 0;
}
+
+bool DEVICE::get_tape_worm(DCR *dcr)
+{
+ return false;
+}
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
bool InChanger; /* Set if vol in current magazine */
bool is_valid; /* set if this data is valid */
bool VolEnabled; /* set if volume enabled */
+ bool VolRecycle; /* set if volume can be recycled */
char VolCatStatus[20]; /* Volume status */
char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */
};
bool autoselect; /* Autoselect in autochanger */
bool read_only; /* Device is read only */
bool initiated; /* set when init_dev() called */
+ bool m_is_worm; /* set for worm tape */
bool m_shstore; /* Shares storage can be used */
bool m_shstore_lock; /* set if shared lock set */
bool m_shstore_user_lock; /* set if user set shared lock */
int has_cap(int cap) const { return capabilities & cap; }
void clear_cap(int cap) { capabilities &= ~cap; }
void set_cap(int cap) { capabilities |= cap; }
+ void set_worm(bool is_worm) { m_is_worm = is_worm; }
bool do_checksum() const { return (capabilities & CAP_BLOCKCHECKSUM) != 0; }
int is_autochanger() const { return capabilities & CAP_AUTOCHANGER; }
int requires_mount() const { return capabilities & CAP_REQMOUNT; }
bool is_fifo() const { return dev_type == B_FIFO_DEV; }
bool is_vtl() const { return dev_type == B_VTL_DEV; }
bool is_vtape() const { return dev_type == B_VTAPE_DEV; }
+ bool is_worm() const { return m_is_worm; }
bool is_open() const { return m_fd >= 0; }
int is_offline() const { return state & ST_OFFLINE; }
int is_labeled() const { return state & ST_LABEL; }
virtual char *print_addr(char *buf, int32_t maxlen, boffset_t addr);
virtual bool do_size_checks(DCR *dcr, DEV_BLOCK *block); /* in dev.c */
+ virtual bool get_tape_worm(DCR *dcr);
virtual bool get_tape_alerts(DCR *dcr);
virtual void show_tape_alerts(DCR *dcr, alert_list_type type,
alert_list_which which, alert_cb alert_callback);
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
block->adata, num_reserved(), print_name(), VolName,
VolHdr.VolumeName[0]?VolHdr.VolumeName:"*NULL*");
+
if (!is_open()) {
if (!open_device(dcr, OPEN_READ_ONLY)) {
Leave(dbglvl);
clear_append();
clear_read();
label_type = B_BACULA_LABEL;
+ set_worm(get_tape_worm(dcr));
+ Dmsg1(dbglvl, "==== worm=%d ====\n", is_worm());
if (!rewind(dcr)) {
Mmsg(jcr->errmsg, _("Couldn't rewind %s device %s: ERR=%s\n"),
Enter(100);
ASSERT2(dcr->VolumeName[0], "Empty Volume name");
ASSERT(!dcr->block->adata);
+ if (is_worm()) {
+ Jmsg3(jcr, M_FATAL, 0, _("Cannot relabel worm %s device %s Volume \"%s\"\n"),
+ print_type(), print_name(), dcr->VolumeName);
+ Leave(100);
+ return false;
+ }
if (!open_device(dcr, OPEN_READ_WRITE)) {
Jmsg4(jcr, M_WARNING, 0, _("Open %s device %s Volume \"%s\" failed: ERR=%s\n"),
print_type(), print_name(), dcr->VolumeName, bstrerror());
bstrncpy(dev->VolHdr.Id, BaculaS3CloudId, sizeof(dev->VolHdr.Id));
dev->VolHdr.VerNum = BaculaS3CloudVersion;
dev->VolHdr.BlockSize = dev->max_block_size;
+ dev->VolHdr.MaxPartSize = dev->max_part_size;
} else {
bstrncpy(dev->VolHdr.Id, BaculaId, sizeof(dev->VolHdr.Id));
dev->VolHdr.VerNum = BaculaTapeVersion;
dev->VolHdr.BlockSize = dev->max_block_size;
}
- if (dev->has_cap(CAP_STREAM) && no_prelabel) {
+ if ((dev->has_cap(CAP_STREAM) && no_prelabel) || dev->is_worm()) {
/* We do not want to re-label so write VOL_LABEL now */
dev->VolHdr.LabelType = VOL_LABEL;
} else {
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
uint32_t BlockSize; /* Basic block size */
/* For Cloud */
- uint64_t ChunkSize; /* Basic chunk size */
+ uint64_t MaxPartSize; /* Maximum Part Size */
};
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
list_volumes(sendit, (void *)sp);
if (!sp->api) sendit("====\n\n", 6, sp);
-
list_spool_stats(sendit, (void *)sp);
-
if (!sp->api) sendit("====\n\n", 6, sp);
if (chk_dbglvl(10)) {
len = Mmsg(msg, _("Device state:\n"));
sendit(msg, len, sp);
- len = Mmsg(msg, " %sOPENED %sTAPE %sLABEL %sMALLOC %sAPPEND %sREAD %sEOT %sWEOT %sEOF %sNEXTVOL %sSHORT %sMOUNTED\n",
+ len = Mmsg(msg, " %sOPENED %sTAPE %sLABEL %sAPPEND %sREAD %sEOT %sWEOT %sEOF %sWORM %sNEXTVOL %sSHORT %sMOUNTED %sMALLOC\n",
dev->is_open() ? "" : "!",
dev->is_tape() ? "" : "!",
dev->is_labeled() ? "" : "!",
- dev->state & ST_MALLOC ? "" : "!",
dev->can_append() ? "" : "!",
dev->can_read() ? "" : "!",
dev->at_eot() ? "" : "!",
dev->state & ST_WEOT ? "" : "!",
dev->at_eof() ? "" : "!",
- dev->state & ST_NEXTVOL ? "" : "!",
- dev->state & ST_SHORT ? "" : "!",
- dev->state & ST_MOUNTED ? "" : "!");
+ dev->is_worm() ? "" : "!",
+ dev->state & ST_NEXTVOL ? "" : "!",
+ dev->state & ST_SHORT ? "" : "!",
+ dev->state & ST_MOUNTED ? "" : "!",
+ dev->state & ST_MALLOC ? "" : "!");
sendit(msg, len, sp);
+
len = Mmsg(msg, _(" Writers=%d reserves=%d blocked=%d enabled=%d usage=%s\n"), dev->num_writers,
dev->num_reserved(), dev->blocked(), dev->enabled,
edit_uint64_with_commas(dev->usage, b1));
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
{"ChangerCommand", store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
{"AlertCommand", store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
{"LockCommand", store_strname,ITEM(res_dev.lock_command), 0, 0, 0},
+ {"WormCommand", store_strname,ITEM(res_dev.worm_command), 0, 0, 0},
{"MaximumChangerWait", store_time, ITEM(res_dev.max_changer_wait), 0, ITEM_DEFAULT, 5 * 60},
{"MaximumOpenWait", store_time, ITEM(res_dev.max_open_wait), 0, ITEM_DEFAULT, 5 * 60},
{"MaximumNetworkBufferSize", store_pint32, ITEM(res_dev.max_network_buffer_size), 0, 0, 0},
sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
sendit(sock, " max_spool_size=%lld max_job_spool_size=%lld\n",
res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
+ if (res->res_dev.worm_command) {
+ sendit(sock, " worm command=%s\n", res->res_dev.worm_command);
+ }
if (res->res_dev.changer_res) {
sendit(sock, " changer=%p\n", res->res_dev.changer_res);
}
if (res->res_dev.alert_command) {
free(res->res_dev.alert_command);
}
+ if (res->res_dev.worm_command) {
+ free(res->res_dev.worm_command);
+ }
if (res->res_dev.lock_command) {
free(res->res_dev.lock_command);
}
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
char *changer_command; /* Changer command -- external program */
char *alert_command; /* Alert command -- external program */
char *lock_command; /* Share storage lock command -- external program */
+ char *worm_command; /* Worm detection command -- external program */
char *spool_directory; /* Spool file directory */
uint32_t dev_type; /* device type */
uint32_t label_type; /* label type */
/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2017 Kern Sibbald
+ Copyright (C) 2000-2018 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
bool end_of_volume(DCR *dcr);
char *print_addr(char *buf, int32_t buf_len);
char *print_addr(char *buf, int32_t maxlen, boffset_t addr);
+ bool get_tape_worm(DCR *dcr);
bool get_tape_alerts(DCR *dcr);
void show_tape_alerts(DCR *dcr, alert_list_type type,
alert_list_which which, alert_cb alert_callback);
--- /dev/null
+/*
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2018 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
+*/
+/*
+ *
+ * Routines for getting tape worm status
+ *
+ * Written by Kern Sibbald, September MMXVIII
+ *
+ */
+
+#include "bacula.h" /* pull in global headers */
+#include "stored.h" /* pull in Storage Deamon headers */
+
+
+static const int dbglvl = 50;
+
+
+bool tape_dev::get_tape_worm(DCR *dcr)
+{
+ JCR *jcr = dcr->jcr;
+
+ if (!job_canceled(jcr) && dcr->device->worm_command &&
+ dcr->device->control_name) {
+ POOLMEM *wormcmd;
+ int status = 1;
+ bool is_worm = false;
+ int worm_val = 0;
+ BPIPE *bpipe;
+ char line[MAXSTRING];
+ const char *fmt = " %d";
+
+ wormcmd = get_pool_memory(PM_FNAME);
+ wormcmd = edit_device_codes(dcr, wormcmd, dcr->device->worm_command, "");
+ /* Wait maximum 5 minutes */
+ bpipe = open_bpipe(wormcmd, 60 * 5, "r");
+ if (bpipe) {
+ while (fgets(line, (int)sizeof(line), bpipe->rfd)) {
+ is_worm = false;
+ if (bsscanf(line, fmt, &worm_val) == 1) {
+ if (worm_val > 0) {
+ is_worm = true;
+ }
+ }
+ }
+ status = close_bpipe(bpipe);
+ free_pool_memory(wormcmd);
+ return is_worm;
+ } else {
+ status = errno;
+ }
+ if (status != 0) {
+ berrno be;
+ Jmsg(jcr, M_WARNING, 0, _("3997 Bad worm command status: %s: ERR=%s.\n"),
+ wormcmd, be.bstrerror(status));
+ Dmsg2(dbglvl, _("3997 Bad worm command status: %s: ERR=%s.\n"),
+ wormcmd, be.bstrerror(status));
+ }
+
+ Dmsg1(400, "worm script status=%d\n", status);
+ free_pool_memory(wormcmd);
+ } else {
+ if (!dcr->device->worm_command) {
+ Dmsg1(dbglvl, "Cannot get tape worm status: no Worm Command specified for device %s\n",
+ print_name());
+ Dmsg1(dbglvl, "Cannot get tape worm status: no Worm Command specified for device %s\n",
+ print_name());
+
+ }
+ if (!dcr->device->control_name) {
+ Dmsg1(dbglvl, "Cannot get tape worm status: no Control Device specified for device %s\n",
+ print_name());
+ Dmsg1(dbglvl, "Cannot get tape worm status: no Control Device specified for device %s\n",
+ print_name());
+ }
+ }
+ return false;
+}
len = Mmsg(msg, "Reserved volume: %s on %s device %s\n", vol->vol_name,
dev->print_type(), dev->print_name());
sendit(msg.c_str(), len, arg);
- len = Mmsg(msg, " Reader=%d writers=%d reserves=%d volinuse=%d\n",
+ len = Mmsg(msg, " Reader=%d writers=%d reserves=%d volinuse=%d worm=%d\n",
dev->can_read()?1:0, dev->num_writers, dev->num_reserved(),
- vol->is_in_use());
+ vol->is_in_use(), dev->is_worm());
sendit(msg.c_str(), len, arg);
} else {
len = Mmsg(msg, "Volume %s no device. volinuse=%d\n", vol->vol_name,