detach_dcr_from_dev(dcr);
}
/* Use job spoolsize prior to device spoolsize */
- if (jcr->spool_size) {
+ if (jcr && jcr->spool_size) {
dcr->max_job_spool_size = jcr->spool_size;
} else {
dcr->max_job_spool_size = dev->device->max_job_spool_size;
stream_to_ascii(buf1, rec.Stream,rec.FileIndex),
rec.data_len);
- while (!write_record_to_block(dcr->block, &rec)) {
+ while (!write_record_to_block(dcr, &rec)) {
Dmsg2(850, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
rec.remainder);
- if (!write_block_to_device(dcr)) {
+ if (!dcr->write_block_to_device()) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev->print_name(), dev->bstrerror());
ok = false;
jcr->setJobStatus(JS_ErrorTerminated);
ok = false;
}
- if (dev->VolCatInfo.VolCatName[0] == 0) {
- Pmsg0(000, _("NULL Volume name. This shouldn't happen!!!\n"));
- Dmsg0(000, _("NULL Volume name. This shouldn't happen!!!\n"));
- }
Dmsg0(90, "back from write_end_session_label()\n");
/* Flush out final partial block of this session */
- if (!write_block_to_device(dcr)) {
+ if (!dcr->write_block_to_device()) {
/* Print only if ok and not cancelled to avoid spurious messages */
if (ok && !jcr->is_job_canceled()) {
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
*
* Kern E. Sibbald, October 2002
*
- *
- * Version $Id$
*/
#include "bacula.h"
ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume);
if (ok || out_dev->can_write()) {
- if (!write_block_to_device(out_jcr->dcr)) {
+ if (!out_jcr->dcr->write_block_to_device()) {
Pmsg0(000, _("Write of last block failed.\n"));
}
}
/* Skipping record, because does not match BSR filter */
return true;
}
- while (!write_record_to_block(out_block, rec)) {
+ while (!write_record_to_block(out_jcr->dcr, rec)) {
Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
rec->remainder);
- if (!write_block_to_device(out_jcr->dcr)) {
+ if (!out_jcr->dcr->write_block_to_device()) {
Dmsg2(90, "Got write_block_to_dev error on device %s: ERR=%s\n",
out_dev->print_name(), out_dev->bstrerror());
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
return false;
}
}
- if (!write_block_to_device(out_jcr->dcr)) {
+ if (!out_jcr->dcr->write_block_to_device()) {
Dmsg2(90, "Got write_block_to_dev error on device %s: ERR=%s\n",
out_dev->print_name(), out_dev->bstrerror());
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
return true;
}
records++;
- while (!write_record_to_block(out_block, rec)) {
+ while (!write_record_to_block(out_jcr->dcr, rec)) {
Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec->data_len,
rec->remainder);
- if (!write_block_to_device(out_jcr->dcr)) {
+ if (!out_jcr->dcr->write_block_to_device()) {
Dmsg2(90, "Got write_block_to_dev error on device %s: ERR=%s\n",
out_dev->print_name(), out_dev->bstrerror());
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
* : false on failure
*
*/
-bool write_block_to_device(DCR *dcr)
+bool DCR::write_block_to_device()
{
bool stat = true;
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
+ DCR *dcr = this;
if (dcr->spooling) {
stat = write_block_to_spool_file(dcr);
}
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
if (job_canceled(jcr) || jcr->getJobType() == JT_SYSTEM) {
stat = false;
} else {
* Returns: true on success or EOT
* false on hard error
*/
-bool write_block_to_dev(DCR *dcr)
+bool DCR::write_block_to_dev()
{
ssize_t stat = 0;
uint32_t wlen; /* length to write */
int hit_max1, hit_max2;
bool ok = true;
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
- DEV_BLOCK *block = dcr->block;
+ DCR *dcr = this;
#ifdef NO_TAPE_WRITE_TEST
empty_block(block);
DEV_BLOCK *lblock = new_block(dev);
/* Note, this can destroy dev->errmsg */
dcr->block = lblock;
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"),
dev->errmsg);
} else {
* Read block with locking
*
*/
-bool read_block_from_device(DCR *dcr, bool check_block_numbers)
+bool DCR::read_block_from_device(bool check_block_numbers)
{
bool ok;
- DEVICE *dev = dcr->dev;
+
Dmsg0(250, "Enter read_block_from_device\n");
dev->r_dlock();
- ok = read_block_from_dev(dcr, check_block_numbers);
+ ok = read_block_from_dev(check_block_numbers);
dev->dunlock();
Dmsg0(250, "Leave read_block_from_device\n");
return ok;
* the block header. For a file, the block may be partially
* or completely in the current buffer.
*/
-bool read_block_from_dev(DCR *dcr, bool check_block_numbers)
+bool DCR::read_block_from_dev(bool check_block_numbers)
{
ssize_t stat;
int looping;
int retry;
- JCR *jcr = dcr->jcr;
- DEVICE *dev = dcr->dev;
- DEV_BLOCK *block = dcr->block;
+ DCR *dcr = this;
if (job_canceled(jcr)) {
return false;
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
#define WRITE_RECHDR_LENGTH RECHDR2_LENGTH
/* Tape label and version definitions */
-#define BaculaId "Bacula 1.0 immortal\n"
-#define OldBaculaId "Bacula 0.9 mortal\n"
-#define BaculaTapeVersion 11
+#define BaculaId "Bacula 1.0 immortal\n"
+#define OldBaculaId "Bacula 0.9 mortal\n"
+#define BaculaTapeVersion 11
#define OldCompatibleBaculaTapeVersion1 10
#define OldCompatibleBaculaTapeVersion2 9
-
/*
* This is the Media structure for a block header
* Note, when written, it is serialized.
DEV_BLOCK *block = dcr->block;
char buf1[100], buf2[100];
for ( ;; ) {
- if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (dev->at_eot()) {
if (!mount_next_read_volume(dcr)) {
/* Read and discard Volume label */
DEV_RECORD *record;
record = new_record();
- read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK);
+ dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK);
read_record_from_block(dcr, block, record);
get_session_record(dev, record, &sessrec);
free_record(record);
*/
static void rectestcmd()
{
- DEV_BLOCK *block;
+ DEV_BLOCK *save_block;
DEV_RECORD *rec;
int i, blkno = 0;
}
Dsm_check(200);
- block = new_block(dev);
+ save_block = dcr->block;
+ dcr->block = new_block(dev);
rec = new_record();
for (i=1; i<500000; i++) {
memset(rec->data, i & 0xFF, i);
rec->data_len = i;
Dsm_check(200);
- if (write_record_to_block(block, rec)) {
- empty_block(block);
+ if (write_record_to_block(dcr, rec)) {
+ empty_block(dcr->block);
blkno++;
Pmsg2(0, _("Block %d i=%d\n"), blkno, i);
} else {
Dsm_check(200);
}
free_record(rec);
- free_block(block);
+ free_block(dcr->block);
+ dcr->block = save_block; /* restore block to dcr */
Dsm_check(200);
}
rec->data = check_pool_memory_size(rec->data, block->buf_len);
len = rec->data_len = block->buf_len-100;
memset(rec->data, 1, rec->data_len);
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg1(0, _("Wrote first record of %d bytes.\n"), rec->data_len);
}
memset(rec->data, 2, rec->data_len);
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg1(0, _("Wrote second record of %d bytes.\n"), rec->data_len);
}
memset(rec->data, 3, rec->data_len);
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
goto bail_out;
}
Pmsg0(0, _("Backspace record OK.\n"));
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
Pmsg1(0, _("Read block failed! ERR=%s\n"), be.bstrerror(dev->dev_errno));
goto bail_out;
init_speed();
for ( ; written < nb_gb; ) {
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("\nError writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("\nError writing block to device.\n"));
goto bail_out;
}
for (j=0; j<len; j++) {
*p++ = i;
}
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
for (j=0; j<len; j++) {
*p++ = i;
}
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
/* Now read it back */
for (i=1; i<=2*num_recs; i++) {
read_again:
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
if (dev_state(dev, ST_EOF)) {
Pmsg0(-1, _("Got EOF on tape.\n"));
goto bail_out;
}
read_again:
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
if (dev_state(dev, ST_EOF)) {
Pmsg0(-1, _("Got EOF on tape.\n"));
static void rbcmd()
{
dev->open(dcr, OPEN_READ_ONLY);
- read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK);
+ dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK);
}
/*
memset(rec->data, i & 0xFF, i);
rec->data_len = i;
Dsm_check(200);
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
dev->update_pos(dcr);
tot_files = dev->file;
for (;;) {
- if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror());
if (dev->state & ST_EOT) {
if (blocks > 0) {
stream_to_ascii(buf1, rec.Stream, rec.FileIndex),
rec.data_len);
- while (!write_record_to_block(block, &rec)) {
+ while (!write_record_to_block(dcr, &rec)) {
/*
* When we get here we have just filled a block
*/
exit_code = 1;
}
/* Write out final block of this session */
- if (!write_block_to_device(dcr)) {
+ if (!dcr->write_block_to_device()) {
Pmsg0(-1, _("Set ok=false after write_block_to_device.\n"));
ok = false;
exit_code = 1;
goto bail_out;
}
Pmsg1(-1, _("Reading block %u.\n"), last_block_num);
- if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
- if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
goto bail_out;
}
Pmsg1(-1, _("Reading block %d.\n"), dev->block_num);
- if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) {
Pmsg1(-1, _("Error reading block: ERR=%s\n"), dev->bstrerror());
goto bail_out;
}
/* Copy block */
this_file = dev->file;
this_block_num = dev->block_num;
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg3(000, _("Last block at: %u:%u this_dev_block_num=%d\n"),
last_file, last_block_num, this_block_num);
if (vol_num == 1) {
printf("+");
fflush(stdout);
}
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
void set_os_device_parameters(DCR *dcr);
static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat);
static const char *mode_to_str(int mode);
+static DEVICE *m_init_dev(JCR *jcr, DEVRES *device, bool new_init);
/*
* Allocate and initialize the DEVICE structure
*/
DEVICE *
init_dev(JCR *jcr, DEVRES *device)
+{
+ DEVICE *dev = m_init_dev(jcr, device, false);
+ return dev;
+}
+
+static DEVICE *
+m_init_dev(JCR *jcr, DEVRES *device, bool new_init)
{
struct stat statp;
int errstat;
dev->drive_index = device->drive_index;
dev->autoselect = device->autoselect;
dev->dev_type = device->dev_type;
+ dev->device = device;
if (dev->is_tape()) { /* No parts on tapes */
dev->max_part_size = 0;
} else {
if (dev->vol_poll_interval && dev->vol_poll_interval < 60) {
dev->vol_poll_interval = 60;
}
- /* Link the dev and device structures together */
- dev->device = device;
device->dev = dev;
if (dev->is_fifo()) {
}
/*
- * Open a file device
+ * Open a file device.
*/
void DEVICE::open_file_device(DCR *dcr, int omode)
{
{
#ifdef MTLOCK
struct mtop mt_com;
+ if (!is_tape()) return;
mt_com.mt_op = MTLOCK;
mt_com.mt_count = 1;
d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
{
#ifdef MTUNLOCK
struct mtop mt_com;
+ if (!is_tape()) return;
mt_com.mt_op = MTUNLOCK;
mt_com.mt_count = 1;
d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
return fsr(rblock-block_num);
} else {
while (rblock > block_num) {
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
berrno be;
dev_errno = errno;
Dmsg2(30, "Failed to find requested block on %s: ERR=%s",
return -1;
}
-
+/*
+ * Truncate a volume.
+ */
bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
{
struct stat st;
+ DEVICE *dev = this;
Dmsg1(100, "truncate %s\n", print_name());
switch (dev_type) {
/* maybe we should rewind and write and eof ???? */
return true; /* we don't really truncate tapes */
case B_FILE_DEV:
- if (ftruncate(m_fd, 0) != 0) {
- berrno be;
- Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"),
- print_name(), be.bstrerror());
- return false;
- }
-
- /*
- * Check for a successful ftruncate() and issue a work-around for devices
- * (mostly cheap NAS) that don't support truncation.
- * Workaround supplied by Martin Schmid as a solution to bug #1011.
- * 1. close file
- * 2. delete file
- * 3. open new file with same mode
- * 4. change ownership to original
- */
-
- if (fstat(m_fd, &st) != 0) {
- berrno be;
- Mmsg2(errmsg, _("Unable to stat device %s. ERR=%s\n"),
- print_name(), be.bstrerror());
- return false;
- }
-
- if (st.st_size != 0) { /* ftruncate() didn't work */
- POOL_MEM archive_name(PM_FNAME);
-
- pm_strcpy(archive_name, dev_name);
- if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
- pm_strcat(archive_name, "/");
+ for ( ;; ) {
+ if (ftruncate(dev->m_fd, 0) != 0) {
+ berrno be;
+ Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"),
+ print_name(), be.bstrerror());
+ return false;
}
- pm_strcat(archive_name, dcr->VolumeName);
-
- Mmsg2(errmsg, _("Device %s doesn't support ftruncate(). Recreating file %s.\n"),
- print_name(), archive_name.c_str());
- /* Close file and blow it away */
- ::close(m_fd);
- ::unlink(archive_name.c_str());
-
- /* Recreate the file -- of course, empty */
- set_mode(CREATE_READ_WRITE);
- if ((m_fd = ::open(archive_name.c_str(), mode, st.st_mode)) < 0) {
+ /*
+ * Check for a successful ftruncate() and issue a work-around for devices
+ * (mostly cheap NAS) that don't support truncation.
+ * Workaround supplied by Martin Schmid as a solution to bug #1011.
+ * 1. close file
+ * 2. delete file
+ * 3. open new file with same mode
+ * 4. change ownership to original
+ */
+
+ if (fstat(dev->m_fd, &st) != 0) {
berrno be;
- dev_errno = errno;
- Mmsg2(errmsg, _("Could not reopen: %s, ERR=%s\n"), archive_name.c_str(),
- be.bstrerror());
- Dmsg1(100, "reopen failed: %s", errmsg);
- Emsg0(M_FATAL, 0, errmsg);
+ Mmsg2(errmsg, _("Unable to stat device %s. ERR=%s\n"),
+ print_name(), be.bstrerror());
return false;
}
+
+ if (st.st_size != 0) { /* ftruncate() didn't work */
+ POOL_MEM archive_name(PM_FNAME);
- /* Reset proper owner */
- chown(archive_name.c_str(), st.st_uid, st.st_gid);
+ pm_strcpy(archive_name, dev_name);
+ if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
+ pm_strcat(archive_name, "/");
+ }
+ pm_strcat(archive_name, dcr->VolumeName);
+
+ Mmsg2(errmsg, _("Device %s doesn't support ftruncate(). Recreating file %s.\n"),
+ print_name(), archive_name.c_str());
+
+ /* Close file and blow it away */
+ ::close(dev->m_fd);
+ ::unlink(archive_name.c_str());
+
+ /* Recreate the file -- of course, empty */
+ dev->set_mode(CREATE_READ_WRITE);
+ if ((dev->m_fd = ::open(archive_name.c_str(), mode, st.st_mode)) < 0) {
+ berrno be;
+ dev_errno = errno;
+ Mmsg2(errmsg, _("Could not reopen: %s, ERR=%s\n"), archive_name.c_str(),
+ be.bstrerror());
+ Dmsg1(100, "reopen failed: %s", errmsg);
+ Emsg0(M_FATAL, 0, errmsg);
+ return false;
+ }
+
+ /* Reset proper owner */
+ chown(archive_name.c_str(), st.st_uid, st.st_gid);
+ }
+ break;
}
-
return true;
}
return false;
*/
void DEVICE::term(void)
{
+ DEVICE *dev = NULL;
Dmsg1(900, "term dev: %s\n", print_name());
close();
if (dev_name) {
device->dev = NULL;
}
delete this;
+ if (dev) {
+ dev->term();
+ }
}
/*
int is_tape() const { return (dev_type == B_TAPE_DEV ||
dev_type == B_VTAPE_DEV); }
int is_ftp() const { return dev_type == B_FTP_DEV; }
- int is_file() const { return dev_type == B_FILE_DEV; }
+ int is_file() const { return (dev_type == B_FILE_DEV); }
int is_fifo() const { return dev_type == B_FIFO_DEV; }
int is_dvd() const { return dev_type == B_DVD_DEV; }
int is_vtl() const { return dev_type == B_VTL_DEV; }
inline const char *DEVICE::archive_name() const { return dev_name; }
inline const char *DEVICE::print_name() const { return prt_name; }
+
+#define CHECK_BLOCK_NUMBERS true
+#define NO_BLOCK_NUMBER_CHECK false
+
/*
* Device Context (or Control) Record.
* There is one of these records for each Job that is using
bool do_unload();
bool do_load(bool is_writing);
bool is_tape_position_ok();
+
+ /* Methods in block.c */
+ bool write_block_to_device();
+ bool write_block_to_dev();
+ bool read_block_from_device(bool check_block_numbers);
+ bool read_block_from_dev(bool check_block_numbers);
+
+ /* Methods in label.c */
+ bool rewrite_volume_label(bool recycle);
+
};
/*
* empty label_blk, and nothing will be written.
*/
Dmsg0(190, "write label block to dev\n");
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
berrno be;
Pmsg1(0, _("write_block_to_device Volume label failed. ERR=%s"),
be.bstrerror(dev->dev_errno));
/* Write overflow block to device */
Dmsg0(190, "Write overflow block to dev\n");
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
berrno be;
Dmsg1(0, _("write_block_to_device overflow block failed. ERR=%s"),
be.bstrerror(dev->dev_errno));
case VOL_IO_ERROR:
case VOL_NO_LABEL:
if (!write_new_volume_label_to_dev(dcr, newname, poolname,
- relabel, true /* write dvd now */)) {
+ relabel, true /* write dvd now */)) {
dir->fsend(_("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
break;
}
#include "stored.h" /* pull in Storage Deamon headers */
/* Forward referenced functions */
-static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec);
+static void create_volume_label_record(DCR *dcr, DEVICE *dev, DEV_RECORD *rec);
/*
* Read the volume label
empty_block(block);
Dmsg0(130, "Big if statement in read_volume_label\n");
- if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+ if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) {
Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bacula "
"labeled Volume, because: ERR=%s"), NPRT(VolName),
dev->print_name(), dev->print_errmsg());
* Returns: false on failure
* true on success
*/
-bool write_volume_label_to_block(DCR *dcr)
+static bool write_volume_label_to_block(DCR *dcr)
{
- DEV_RECORD rec;
DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
DEV_BLOCK *block = dcr->block;
+ DEV_RECORD rec;
+ JCR *jcr = dcr->jcr;
Dmsg0(130, "write Label in write_volume_label_to_block()\n");
+
memset(&rec, 0, sizeof(rec));
rec.data = get_memory(SER_LENGTH_Volume_Label);
empty_block(block); /* Volume label always at beginning */
- create_volume_label_record(dcr, &rec);
+ create_volume_label_record(dcr, dev, &rec);
block->BlockNumber = 0;
- if (!write_record_to_block(block, &rec)) {
+ if (!write_record_to_block(dcr, &rec)) {
free_pool_memory(rec.data);
Jmsg1(jcr, M_FATAL, 0, _("Cannot write Volume label to block for device %s\n"),
dev->print_name());
* This routine should be used only when labeling a blank tape.
*/
bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName,
- const char *PoolName, bool relabel, bool dvdnow)
+ const char *PoolName, bool relabel, bool dvdnow)
{
- DEVICE * volatile dev = dcr->dev;
-
+ DEVICE *dev = dcr->dev;
+ DEV_BLOCK *block = dcr->block;
Dmsg0(150, "write_volume_label()\n");
- empty_block(dcr->block);
if (*VolName == 0) {
Pmsg0(0, "=== ERROR: write_new_volume_label_to_dev called with NULL VolName\n");
goto bail_out;
}
}
Dmsg1(150, "Label type=%d\n", dev->label_type);
- if (!dev->rewind(dcr)) {
- Dmsg2(130, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->print_errmsg());
- if (!forge_on) {
- goto bail_out;
+
+ for ( ;; ) {
+ empty_block(block);
+ if (!dev->rewind(dcr)) {
+ Dmsg2(130, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->print_errmsg());
+ if (!forge_on) {
+ goto bail_out;
+ }
}
- }
- /* Temporarily mark in append state to enable writing */
- dev->set_append();
+ /* Temporarily mark in append state to enable writing */
+ dev->set_append();
- /* Create PRE_LABEL or VOL_LABEL if DVD */
- create_volume_label(dev, VolName, PoolName, dvdnow);
+ /* Create PRE_LABEL or VOL_LABEL if DVD */
+ create_volume_label(dev, VolName, PoolName, dvdnow);
- /*
- * If we have already detected an ANSI label, re-read it
- * to skip past it. Otherwise, we write a new one if
- * so requested.
- */
- if (dev->label_type != B_BACULA_LABEL) {
- if (read_ansi_ibm_label(dcr) != VOL_OK) {
- dev->rewind(dcr);
+ /*
+ * If we have already detected an ANSI label, re-read it
+ * to skip past it. Otherwise, we write a new one if
+ * so requested.
+ */
+ if (dev->label_type != B_BACULA_LABEL) {
+ if (read_ansi_ibm_label(dcr) != VOL_OK) {
+ dev->rewind(dcr);
+ goto bail_out;
+ }
+ } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
goto bail_out;
}
- } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) {
- goto bail_out;
- }
-
- create_volume_label_record(dcr, dcr->rec);
- dcr->rec->Stream = 0;
- dcr->rec->maskedStream = 0;
- if (!write_record_to_block(dcr->block, dcr->rec)) {
- Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
- goto bail_out;
- } else {
- Dmsg2(130, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev->print_name());
- }
+ create_volume_label_record(dcr, dev, dcr->rec);
+ dcr->rec->Stream = 0;
+ dcr->rec->maskedStream = 0;
- Dmsg0(130, "Call write_block_to_dev()\n");
- if (!write_block_to_dev(dcr)) {
- Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
- goto bail_out;
- }
+ if (!write_record_to_block(dcr, dcr->rec)) {
+ Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
+ goto bail_out;
+ } else {
+ Dmsg2(130, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev->print_name());
+ }
- /* Now commit block to DVD if we should write now */
- if (dev->is_dvd() && dvdnow) {
- Dmsg1(150, "New VolName=%s\n", dev->VolCatInfo.VolCatName);
- if (!dvd_write_part(dcr)) {
- Dmsg2(130, "Bad DVD write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
+ Dmsg0(130, "Call write_block_to_dev()\n");
+ if (!dcr->write_block_to_dev()) {
+ Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
goto bail_out;
}
+ break;
}
+ dev = dcr->dev;
+
Dmsg0(130, " Wrote block to device\n");
* Returns: true if OK
* false if unable to write it
*/
-bool rewrite_volume_label(DCR *dcr, bool recycle)
+bool DCR::rewrite_volume_label(bool recycle)
{
- DEVICE *dev = dcr->dev;
- JCR *jcr = dcr->jcr;
+ DCR *dcr = this;
if (!dev->open(dcr, OPEN_READ_WRITE)) {
Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
}
if (recycle) {
Dmsg1(150, "Doing recycle. Vol=%s\n", dcr->VolumeName);
-// volume_unused(dcr); /* mark volume unused */
if (!dev->truncate(dcr)) {
Jmsg2(jcr, M_FATAL, 0, _("Truncate error on device %s: ERR=%s\n"),
dev->print_name(), dev->print_errmsg());
/* Attempt write to check write permission */
Dmsg1(200, "Attempt to write to device fd=%d.\n", dev->fd());
- if (!write_block_to_dev(dcr)) {
+ if (!dcr->write_block_to_dev()) {
Jmsg2(jcr, M_ERROR, 0, _("Unable to write device %s: ERR=%s\n"),
dev->print_name(), dev->print_errmsg());
Dmsg0(200, "===ERROR write block to dev\n");
* Assumes that the dev->VolHdr structure is properly
* initialized.
*/
-static void create_volume_label_record(DCR *dcr, DEV_RECORD *rec)
+static void create_volume_label_record(DCR *dcr, DEVICE *dev, DEV_RECORD *rec)
{
ser_declare;
struct date_time dt;
- DEVICE *dev = dcr->dev;
JCR *jcr = dcr->jcr;
char buf[100];
ser_string(dev->VolHdr.LabelProg);
ser_string(dev->VolHdr.ProgVersion);
ser_string(dev->VolHdr.ProgDate);
-
+
ser_end(rec->data, SER_LENGTH_Volume_Label);
bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
rec->data_len = ser_length(rec->data);
*/
if (!can_write_record_to_block(block, rec)) {
Dmsg0(150, "Cannot write session label to block.\n");
- if (!write_block_to_device(dcr)) {
+ if (!dcr->write_block_to_device()) {
Dmsg0(130, "Got session label write_block_to_dev error.\n");
free_record(rec);
return false;
}
}
- if (!write_record_to_block(block, rec)) {
+ if (!write_record_to_block(dcr, rec)) {
free_record(rec);
return false;
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2006-2011 Free Software Foundation Europe e.V.
+ Copyright (C) 2006-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
Dmsg1(100, "ok=%d\n", ok);
if (ok || dev->can_write()) {
/* Flush out final partial block of this session */
- if (!write_block_to_device(jcr->dcr)) {
+ if (!jcr->dcr->write_block_to_device()) {
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
dev->print_name(), dev->bstrerror());
Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
jcr->JobId,
FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len);
- while (!write_record_to_block(jcr->dcr->block, rec)) {
+ while (!write_record_to_block(jcr->dcr, rec)) {
Dmsg4(200, "!write_record_to_block blkpos=%u:%u len=%d rem=%d\n",
dev->file, dev->block_num, rec->data_len, rec->remainder);
- if (!write_block_to_device(jcr->dcr)) {
+ if (!jcr->dcr->write_block_to_device()) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev->print_name(), dev->bstrerror());
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
*/
recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
- if (!rewrite_volume_label(dcr, recycle)) {
+ if (!dcr->rewrite_volume_label(recycle)) {
mark_volume_in_error();
goto mount_next_vol;
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
void init_block_write(DEV_BLOCK *block);
void empty_block(DEV_BLOCK *block);
void free_block(DEV_BLOCK *block);
-bool write_block_to_device(DCR *dcr);
-bool write_block_to_dev(DCR *dcr);
void print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
void ser_block_header(DEV_BLOCK *block);
-#define CHECK_BLOCK_NUMBERS true
-#define NO_BLOCK_NUMBER_CHECK false
-bool read_block_from_device(DCR *dcr, bool check_block_numbers);
-bool read_block_from_dev(DCR *dcr, bool check_block_numbers);
-
/* From butil.c -- utilities for SD tool programs */
void print_ls_output(const char *fname, const char *link, int type, struct stat *statp);
JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr,
int read_dvd_volume_label(DCR *dcr, bool write);
void create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName, bool dvdnow);
-bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName,
- const char *PoolName, bool relabel, bool dvdnow);
#define ANSI_VOL_LABEL 0
#define ANSI_EOF_LABEL 1
#define ANSI_EOV_LABEL 2
bool write_ansi_ibm_labels(DCR *dcr, int type, const char *VolName);
int read_ansi_ibm_label(DCR *dcr);
bool write_session_label(DCR *dcr, int label);
-bool write_volume_label_to_block(DCR *dcr);
-bool rewrite_volume_label(DCR *dcr, bool recycle);
void dump_volume_label(DEVICE *dev);
void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName,
+ const char *PoolName, bool relabel, bool dvdnow);
/* From locks.c */
void _lock_device(const char *file, int line, DEVICE *dev);
/* From record.c */
const char *FI_to_ascii(char *buf, int fi);
const char *stream_to_ascii(char *buf, int stream, int fi);
-bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool write_record_to_block(DCR *dcr, DEV_RECORD *rec);
bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
ok = false;
break;
}
- if (!read_block_from_device(dcr, CHECK_BLOCK_NUMBERS)) {
+ if (!dcr->read_block_from_device(CHECK_BLOCK_NUMBERS)) {
if (dev->at_eot()) {
DEV_RECORD *trec = new_record();
Jmsg(jcr, M_INFO, 0, _("End of Volume at file %u on device %s, Volume \"%s\"\n"),
* and pass it off to the callback routine, then continue
* most likely reading the previous record.
*/
- read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK);
+ dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK);
read_record_from_block(dcr, block, trec);
handle_session_record(dev, trec, &sessrec);
ok = record_cb(dcr, trec);
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
* non-zero), and 2. The remaining bytes to write may not
* all fit into the block.
*/
-bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
+bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
{
ser_declare;
uint32_t remlen;
char buf1[100], buf2[100];
+ DEV_BLOCK *block;
+
+ block = dcr->block;
remlen = block->buf_len - block->binbuf;
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
char LabelProg[50]; /* Label program name */
char ProgVersion[50]; /* Program version */
char ProgDate[50]; /* Program build date/time */
+
};
#define SER_LENGTH_Volume_Label 1024 /* max serialised length of volume label */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2004-2011 Free Software Foundation Europe e.V.
+ Copyright (C) 2004-2012 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
ok = false;
break;
}
- ok = write_block_to_device(dcr);
+ ok = dcr->write_block_to_device();
if (!ok) {
Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
dcr->dev->print_name(), dcr->dev->bstrerror());