AC_MSG_CHECKING(for MySQL support)
AC_ARG_WITH(mysql,
[
-Which DBMS do you want to use (please select only one):
--with-mysql[=DIR] Include MySQL support. DIR is the MySQL base
install directory, default is to search through
a number of common places for the MySQL files.],
AC_ARG_WITH(embedded-mysql,
[
-Which DBMS do you want to use (please select only one):
--with-embedded-mysql[=DIR] Include MySQL support. DIR is the MySQL base
install directory, default is to search through
a number of common places for the MySQL files.],
AC_MSG_CHECKING(for SQLite support)
AC_ARG_WITH(sqlite,
[
-Which DBMS do you want to use (please select only one):
--with-sqlite[=DIR] Include SQLite support. DIR is the SQLite base
install directory, default is to search through
a number of common places for the SQLite files.],
AC_MSG_CHECKING(for Berkeley DB support)
AC_ARG_WITH(berkeleydb,
[
-Which DBMS do you want to use (please select only one):
--with-berkeleydb[=DIR] Include Berkeley DB support. DIR is the Berkeley DB base
install directory, default is to search through
a number of common places for the DB files.],
Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
"MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
- "Recycle,Slot,FirstWritten,LastWritten "
+ "Recycle,Slot,FirstWritten,LastWritten,InChanger "
"FROM Media WHERE VolumeName='%s'", mr->VolumeName);
}
static void sigintcatcher(int sig)
{
brkflg++;
+ if (brkflg > 1) {
+ exit(1);
+ }
signal(SIGINT, sigintcatcher);
}
askdir.c authenticate.c \
block.c butil.c dev.c \
device.c dircmd.c fd_cmds.c job.c \
- label.c match_bsr.c parse_bsr.c \
- read.c read_record.c \
- record.c status.c stored_conf.c mount.c
+ label.c match_bsr.c mount.c parse_bsr.c \
+ read.c read_record.c record.c \
+ spool.c status.c stored_conf.c
SVROBJS = stored.o autochanger.o acquire.o append.o \
askdir.o authenticate.o \
block.o butil.o dev.o \
device.o dircmd.o fd_cmds.o job.o \
label.o match_bsr.o mount.o parse_bsr.o \
- read.o read_record.o \
- record.o status.o stored_conf.o
+ read.o read_record.o record.o \
+ spool.o status.o stored_conf.o
# btape
TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \
acquire.c mount.c record.c read_record.c \
- stored_conf.c match_bsr.c parse_bsr.o
+ stored_conf.c match_bsr.c parse_bsr.c spool.c
TAPEOBJS = btape.o block.o butil.o dev.o device.o label.o \
autochanger.o acquire.o mount.o record.o read_record.o \
- stored_conf.o match_bsr.o parse_bsr.o
+ stored_conf.o match_bsr.o parse_bsr.o spool.o
# bls
BLSOBJS = bls.o block.o butil.o device.o dev.o label.o match_bsr.o \
autochanger.o acquire.o mount.o parse_bsr.o record.o \
- read_record.o stored_conf.o
+ read_record.o stored_conf.o spool.o
# bextract
BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \
autochanger.o acquire.o mount.o match_bsr.o parse_bsr.o butil.o \
- read_record.o stored_conf.o
+ read_record.o stored_conf.o spool.o
# bscan
SCNOBJS = bscan.o block.o device.o dev.o label.o \
autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
- butil.o read_record.o stored_conf.o
+ butil.o read_record.o stored_conf.o spool.o
# bcopy
COPYOBJS = bcopy.o block.o device.o dev.o label.o \
autochanger.o acquire.o mount.o record.o match_bsr.o parse_bsr.o \
- butil.o read_record.o stored_conf.o
+ butil.o read_record.o stored_conf.o spool.o
static char OK_data[] = "3000 OK data\n";
/* Forward referenced functions */
-static bool are_attributes_spooled(JCR *jcr);
-static int begin_attribute_spool(JCR *jcr);
-static int discard_attribute_spool(JCR *jcr);
-static int commit_attribute_spool(JCR *jcr);
-static int open_data_spool_file(JCR *jcr);
-static int close_data_spool_file(JCR *jcr);
-static int begin_data_spool(JCR *jcr);
-static int discard_data_spool(JCR *jcr);
-static int commit_data_spool(JCR *jcr);
-
/*
* Append Data sent from File daemon
while (!write_record_to_block(block, &rec)) {
Dmsg2(150, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
rec.remainder);
- if (!write_block_to_device(jcr, dev, block)) {
+ if (!write_block_to_device(jcr->dcr, block)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(dev), strerror_dev(dev));
Jmsg(jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
}
Dmsg0(90, "back from write_end_session_label()\n");
/* Flush out final partial block of this session */
- if (!write_block_to_device(jcr, dev, block)) {
+ if (!write_block_to_device(jcr->dcr, block)) {
Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
set_jcr_job_status(jcr, JS_ErrorTerminated);
ok = false;
Dmsg1(100, "return from do_append_data() stat=%d\n", ok);
return ok ? 1 : 0;
}
-
-
-static int begin_data_spool(JCR *jcr)
-{
- if (jcr->dcr->spool_data) {
- return open_data_spool_file(jcr);
- }
- return 1;
-}
-
-static int discard_data_spool(JCR *jcr)
-{
- if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
- return close_data_spool_file(jcr);
- }
- return 1;
-}
-
-static int commit_data_spool(JCR *jcr)
-{
- if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
-// despool_data(jcr);
- return close_data_spool_file(jcr);
- }
- return 1;
-}
-
-static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name)
-{
- Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name,
- jcr->Job, jcr->device->hdr.name);
-}
-
-
-static int open_data_spool_file(JCR *jcr)
-{
- POOLMEM *name = get_pool_memory(PM_MESSAGE);
- int spool_fd;
-
- make_unique_data_spool_filename(jcr, &name);
- if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) {
- jcr->dcr->spool_fd = spool_fd;
- jcr->spool_attributes = true;
- } else {
- Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno));
- free_pool_memory(name);
- return 0;
- }
- free_pool_memory(name);
- return 1;
-}
-
-static int close_data_spool_file(JCR *jcr)
-{
- POOLMEM *name = get_pool_memory(PM_MESSAGE);
-
- make_unique_data_spool_filename(jcr, &name);
- close(jcr->dcr->spool_fd);
- jcr->dcr->spool_fd = -1;
- unlink(name);
- free_pool_memory(name);
- return 1;
-}
-
-
-static bool are_attributes_spooled(JCR *jcr)
-{
- return jcr->spool_attributes && jcr->dir_bsock->spool_fd;
-}
-
-static int begin_attribute_spool(JCR *jcr)
-{
- if (!jcr->no_attributes && jcr->spool_attributes) {
- return open_spool_file(jcr, jcr->dir_bsock);
- }
- return 1;
-}
-
-static int discard_attribute_spool(JCR *jcr)
-{
- if (are_attributes_spooled(jcr)) {
- return close_spool_file(jcr, jcr->dir_bsock);
- }
- return 1;
-}
-
-static int commit_attribute_spool(JCR *jcr)
-{
- if (are_attributes_spooled(jcr)) {
- bnet_despool_to_bsock(jcr->dir_bsock);
- return close_spool_file(jcr, jcr->dir_bsock);
- }
- return 1;
-}
out_block = out_jcr->dcr->block;
read_records(in_jcr, in_dev, record_cb, mount_next_read_volume);
- if (!write_block_to_device(out_jcr, out_dev, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr, out_block)) {
Pmsg0(000, _("Write of last block failed.\n"));
}
while (!write_record_to_block(out_block, 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, out_dev, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr, out_block)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
strerror_dev(out_dev));
}
}
- if (!write_block_to_device(out_jcr, out_dev, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr, out_block)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
while (!write_record_to_block(out_block, 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, out_dev, out_block)) {
+ if (!write_block_to_device(out_jcr->dcr, out_block)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
* in the buffer should have already been reserved by
* init_block.
*/
-static void ser_block_header(DEV_BLOCK *block)
+void ser_block_header(DEV_BLOCK *block)
{
ser_declare;
uint32_t CheckSum = 0;
* : 0 on failure
*
*/
-int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+int write_block_to_device(DCR *dcr, DEV_BLOCK *block)
{
int stat = 1;
- DCR *dcr = jcr->dcr;
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
lock_device(dev);
+ if (dcr->spooling) {
+ stat = write_block_to_spool_file(dcr, block);
+ unlock_device(dev);
+ return stat;
+ }
+
/*
* If a new volume has been mounted since our last write
* Create a JobMedia record for the previous volume written,
}
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(dcr, block)) {
stat = fixup_device_block_write_error(jcr, dev, block);
}
* Returns: 1 on success or EOT
* 0 on hard error
*/
-int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+int write_block_to_dev(DCR *dcr, DEV_BLOCK *block)
{
ssize_t stat = 0;
uint32_t wlen; /* length to write */
int hit_max1, hit_max2;
bool ok;
- DCR *dcr = jcr->dcr;
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
#ifdef NO_TAPE_WRITE_TEST
empty_block(block);
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
} else {
ok = FALSE;
}
/* Write out final block of this session */
- if (!write_block_to_device(jcr, dev, block)) {
+ if (!write_block_to_device(jcr->dcr, block)) {
Pmsg0(-1, _("Set ok=FALSE after write_block_to_device.\n"));
ok = FALSE;
}
/* Copy block */
this_file = dev->file;
this_block_num = dev->block_num;
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
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) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
}
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg0(0, _("Error writing block to device.\n"));
goto bail_out;
}
*p = block_num;
block->binbuf = block->buf_len;
block->bufp = block->buf + block->binbuf;
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
break;
}
if ((block_num++ % 100) == 0) {
DEV_BLOCK *block; /* pointer to block */
DEV_RECORD *record; /* pointer to record */
bool spool_data; /* set to spool data */
+ bool spooling; /* set when actually spooling */
int spool_fd; /* fd if spooling */
bool NewVol; /* set if new Volume mounted */
bool WroteVol; /* set if Volume written */
* empty label_blk, and nothing will be written.
*/
Dmsg0(190, "write label block to dev\n");
- if (!write_block_to_dev(jcr, dev, label_blk)) {
+ if (!write_block_to_dev(jcr->dcr, label_blk)) {
Pmsg1(0, "write_block_to_device Volume label failed. ERR=%s",
strerror_dev(dev));
free_block(label_blk);
/* Write overflow block to device */
Dmsg0(190, "Write overflow block to dev\n");
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Pmsg1(0, "write_block_to_device overflow block failed. ERR=%s",
strerror_dev(dev));
unblock_device(dev);
}
free_pool_memory(rec.data);
- Dmsg0(99, "Call write_block_to_device()\n");
- if (!write_block_to_dev(jcr, dev, block)) {
+ Dmsg0(99, "Call write_block_to_dev()\n");
+ if (!write_block_to_dev(jcr->dcr, block)) {
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
Dmsg2(30, "Bad Label write on %s. ERR=%s\n", dev_name(dev), strerror_dev(dev));
stat = 9;
*/
if (!can_write_record_to_block(block, rec)) {
Dmsg0(100, "Cannot write session label to block.\n");
- if (!write_block_to_device(jcr, dev, block)) {
+ if (!write_block_to_device(jcr->dcr, block)) {
Dmsg0(90, "Got session label write_block_to_dev error.\n");
Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
dev_vol_name(dev), strerror(errno));
}
}
/* Attempt write to check write permission */
- if (!write_block_to_dev(jcr, dev, block)) {
+ if (!write_block_to_dev(jcr->dcr, block)) {
Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"),
dev_name(dev), strerror_dev(dev));
goto mount_next_vol;
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 write_block_to_device(DCR *dcr, DEV_BLOCK *block);
+int write_block_to_dev(DCR *dcr, DEV_BLOCK *block);
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
int read_records(JCR *jcr, DEVICE *dev,
int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
int mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block));
+
+/* From spool.c */
+int begin_data_spool(JCR *jcr);
+int discard_data_spool(JCR *jcr);
+int commit_data_spool(JCR *jcr);
+bool are_attributes_spooled(JCR *jcr);
+int begin_attribute_spool(JCR *jcr);
+int discard_attribute_spool(JCR *jcr);
+int commit_attribute_spool(JCR *jcr);
+bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block);
--- /dev/null
+/*
+ * Spooling code
+ *
+ * Kern Sibbald, March 2004
+ *
+ * Version $Id$
+ */
+/*
+ Copyright (C) 2000-2004 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
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "stored.h"
+
+/* Forward referenced subroutines */
+static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name);
+static int open_data_spool_file(JCR *jcr);
+static int close_data_spool_file(JCR *jcr);
+static bool despool_data(DCR *dcr);
+
+
+int begin_data_spool(JCR *jcr)
+{
+ if (jcr->dcr->spool_data) {
+ return open_data_spool_file(jcr);
+ }
+ return 1;
+}
+
+int discard_data_spool(JCR *jcr)
+{
+ if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
+ return close_data_spool_file(jcr);
+ }
+ return 1;
+}
+
+int commit_data_spool(JCR *jcr)
+{
+ bool stat;
+ if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
+ lock_device(jcr->dcr->dev);
+ stat = despool_data(jcr->dcr);
+ unlock_device(jcr->dcr->dev);
+ if (!stat) {
+ close_data_spool_file(jcr);
+ return 0;
+ }
+ return close_data_spool_file(jcr);
+ }
+ return 1;
+}
+
+static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name)
+{
+ Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name,
+ jcr->Job, jcr->device->hdr.name);
+}
+
+
+static int open_data_spool_file(JCR *jcr)
+{
+ POOLMEM *name = get_pool_memory(PM_MESSAGE);
+ int spool_fd;
+
+ make_unique_data_spool_filename(jcr, &name);
+ if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) {
+ jcr->dcr->spool_fd = spool_fd;
+ jcr->spool_attributes = true;
+ } else {
+ Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno));
+ free_pool_memory(name);
+ return 0;
+ }
+ free_pool_memory(name);
+ return 1;
+}
+
+static int close_data_spool_file(JCR *jcr)
+{
+ POOLMEM *name = get_pool_memory(PM_MESSAGE);
+
+ make_unique_data_spool_filename(jcr, &name);
+ close(jcr->dcr->spool_fd);
+ jcr->dcr->spool_fd = -1;
+ unlink(name);
+ free_pool_memory(name);
+ return 1;
+}
+
+static bool despool_data(DCR *dcr)
+{
+ DEVICE *sdev;
+ DCR *sdcr;
+ dcr->spooling = false;
+ bool ok = true;
+ DEV_BLOCK *block = dcr->block;
+ JCR *jcr = dcr->jcr;
+
+ /* Set up a dev structure to read */
+ sdev = (DEVICE *)malloc(sizeof(DEVICE));
+ memset(sdev, 0, sizeof(DEVICE));
+ sdev->fd = dcr->spool_fd;
+ lseek(sdev->fd, 0, SEEK_SET); /* rewind */
+ sdcr = new_dcr(jcr, sdev);
+ for ( ; ok; ) {
+ if (job_canceled(jcr)) {
+ ok = false;
+ break;
+ }
+ if (!read_block_from_dev(jcr, sdev, block, CHECK_BLOCK_NUMBERS)) {
+ if (dev_state(sdev, ST_EOT)) {
+ break;
+ }
+ ok = false;
+ break;
+ }
+ if (!write_block_to_dev(dcr, block)) {
+ ok = false;
+ break;
+ }
+ }
+ lseek(sdev->fd, 0, SEEK_SET); /* rewind */
+ if (ftruncate(sdev->fd, 0) != 0) {
+ ok = false;
+ }
+ return ok;
+}
+
+/*
+ * Write a block to the spool file
+ *
+ * Returns: true on success or EOT
+ * false on hard error
+ */
+bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block)
+{
+ ssize_t stat = 0;
+ uint32_t wlen; /* length to write */
+ DEVICE *dev = dcr->dev;
+ int retry = 0;
+
+ ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
+
+ wlen = block->binbuf;
+ if (wlen <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
+ Dmsg0(100, "return write_block_to_dev no data to write\n");
+ return true;
+ }
+ /*
+ * Clear to the end of the buffer if it is not full,
+ * and on tape devices, apply min and fixed blocking.
+ */
+ if (wlen != block->buf_len) {
+ uint32_t blen; /* current buffer length */
+
+ Dmsg2(200, "binbuf=%d buf_len=%d\n", block->binbuf, block->buf_len);
+ blen = wlen;
+
+ /* Adjust write size to min/max for tapes only */
+ if (dev->state & ST_TAPE) {
+ if (wlen < dev->min_block_size) {
+ wlen = ((dev->min_block_size + TAPE_BSIZE - 1) / TAPE_BSIZE) * TAPE_BSIZE;
+ }
+ /* check for fixed block size */
+ if (dev->min_block_size == dev->max_block_size) {
+ wlen = block->buf_len; /* fixed block size already rounded */
+ }
+ }
+ if (wlen-blen > 0) {
+ memset(block->bufp, 0, wlen-blen); /* clear garbage */
+ }
+ }
+
+ ser_block_header(block);
+
+ Dmsg1(300, "Write block of %u bytes\n", wlen);
+write_again:
+ stat = write(dcr->spool_fd, block->buf, (size_t)wlen);
+ if (stat != (ssize_t)wlen) {
+ if (!despool_data(dcr)) {
+ return false;
+ }
+ if (retry++ > 1) {
+ return false;
+ }
+ goto write_again;
+ }
+
+ empty_block(block);
+ return true;
+}
+
+
+
+bool are_attributes_spooled(JCR *jcr)
+{
+ return jcr->spool_attributes && jcr->dir_bsock->spool_fd;
+}
+
+int begin_attribute_spool(JCR *jcr)
+{
+ if (!jcr->no_attributes && jcr->spool_attributes) {
+ return open_spool_file(jcr, jcr->dir_bsock);
+ }
+ return 1;
+}
+
+int discard_attribute_spool(JCR *jcr)
+{
+ if (are_attributes_spooled(jcr)) {
+ return close_spool_file(jcr, jcr->dir_bsock);
+ }
+ return 1;
+}
+
+int commit_attribute_spool(JCR *jcr)
+{
+ if (are_attributes_spooled(jcr)) {
+ bnet_despool_to_bsock(jcr->dir_bsock);
+ return close_spool_file(jcr, jcr->dir_bsock);
+ }
+ return 1;
+}
#undef VERSION
#define VERSION "1.33.4"
#define VSTRING "1"
-#define BDATE "06 Mar 2004"
-#define LSMDATE "06Mar04"
+#define BDATE "08 Mar 2004"
+#define LSMDATE "08Mar04"
/* Debug flags */
#undef DEBUG