For 1.32:
+- Make bextract release the drive properly between tapes
+ so that an autochanger can be made to work.
+- Fix "restore all" to bypass building the tree.
+- Fix restore to list errors if Invalid block found, and if # files
+ restored does not match # expected.
- User wants to NOT backup up certain big files (email files).
- Maybe remove multiple simultaneous devices code in SD.
- On Windows with very long path names, it may be impossible to create
# If you want the MySQL version, use:
# rpmbuild -ba --define "build_mysql 1" bacula.spec
#
-
+# If you want the MySQL version and static builds, use:
+# rpmbuild -ba --define "build_mysql 1" --define "build_static 1" bacula.spec
+# If you want the MySQL version and static builds + come console , use:
+# rpmbuild -ba --define "build_mysql 1" --define "build_static 1" --define "build_gnome 1" bacula.spec
%define mysql 0
+%define static 0
+%define gnome 0
%{?build_mysql:%define mysql 1}
+%{?build_static:%define static 1}
+%{?build_gnome:%define gnome 1}
+
Summary: Bacula - The Network Backup Solution
Packager: D. Scott Barninger <barninger@fairfieldcomputers.com>
Requires: gnome-libs >= 1.4
Requires: readline
-BuildRequires: gnome-libs-devel >= 1.4
BuildRequires: readline-devel
+%if %{gnome}
+Requires: gnome-libs >= 1.4
+BuildRequires: gnome-libs-devel >= 1.4
+%endif
+
%if %{mysql}
Requires: mysql >= 3.23
Requires: mysql-server >= 3.23
--sysconfdir=/etc/bacula \
--with-scriptdir=/etc/bacula \
--enable-smartalloc \
+%if %{gnome}
--enable-gnome \
+%endif
+%if %{static}
+ --enable-static-fd \
+ --enable-static-sd \
+ --enable-static-dir \
+ --enable-static-tools \
+ --enable-static-cons \
+%endif
%if %{mysql}
--with-mysql \
%else
%endif
# install the init scripts
-cp platforms/redhat/bacula-dir $RPM_BUILD_ROOT/etc/rc.d/init.d/bacula-dir
-cp platforms/redhat/bacula-fd $RPM_BUILD_ROOT/etc/rc.d/init.d/bacula-fd
-cp platforms/redhat/bacula-sd $RPM_BUILD_ROOT/etc/rc.d/init.d/bacula-sd
+cp platforms/mandrake/bacula-dir $RPM_BUILD_ROOT/etc/rc.d/init.d/bacula-dir
+cp platforms/mandrake/bacula-fd $RPM_BUILD_ROOT/etc/rc.d/init.d/bacula-fd
+cp platforms/mandrake/bacula-sd $RPM_BUILD_ROOT/etc/rc.d/init.d/bacula-sd
# install the menu stuff
cp scripts/bacula.png $RPM_BUILD_ROOT/usr/share/pixmaps/bacula.png
if (res_incexe.current_opts == NULL) {
res_incexe.current_opts = (FOPTS *)malloc(sizeof(FOPTS));
memset(res_incexe.current_opts, 0, sizeof(FOPTS));
+ res_incexe.current_opts->match.init(1, true);
+ res_incexe.current_opts->base_list.init(1, true);
res_incexe.num_opts = 1;
res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
res_incexe.opts_list[0] = res_incexe.current_opts;
void alist::destroy()
{
if (items) {
- for (int i=0; i<num_items; i++) {
- free(items[i]);
+ if (own_items) {
+ for (int i=0; i<num_items; i++) {
+ free(items[i]);
+ }
}
free(items);
}
int num_items;
int max_items;
int num_grow;
+ bool own_items;
public:
- alist(int num = 1);
- void init(int num = 1);
+ alist(int num = 1, bool own=true);
+ void init(int num = 1, bool own=true);
void append(void *item);
void *get(int index);
void * operator [](int index) const;
return items[index];
}
-/*
+/*
* This allows us to do explicit initialization,
* allowing us to mix C++ classes inside malloc'ed
* C structures. Define before called in constructor.
*/
-inline void alist::init(int num) {
+inline void alist::init(int num, bool own) {
items = NULL;
num_items = 0;
max_items = 0;
num_grow = num;
+ own_items = own;
}
/* Constructor */
-inline alist::alist(int num) {
- this->init(num);
+inline alist::alist(int num, bool own) {
+ this->init(num, own);
}
# bacula-sd
SVRSRCS = stored.c autochanger.c acquire.c append.c \
askdir.c authenticate.c \
- block.c dev.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 record.c status.c stored_conf.c mount.c
+ read.c read_record.c \
+ record.c status.c stored_conf.c mount.c
SVROBJS = stored.o autochanger.o acquire.o append.o \
askdir.o authenticate.o \
- block.o dev.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 record.o status.o stored_conf.o
+ read.o read_record.o \
+ record.o status.o stored_conf.o
# btape
TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \
#include "stored.h"
/* Forward referenced functions */
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
/* Global variables */
static DEVICE *in_dev = NULL;
static DEVICE *out_dev = NULL;
-static JCR *in_jcr; /* input jcr */
-static JCR *out_jcr; /* output jcr */
+static JCR *in_jcr; /* input jcr */
+static JCR *out_jcr; /* output jcr */
static BSR *bsr = NULL;
static char *wd = "/tmp";
static int list_records = 0;
while ((ch = getopt(argc, argv, "b:c:d:mn:p:rsu:vV:w:?")) != -1) {
switch (ch) {
case 'b':
- bsr = parse_bsr(NULL, optarg);
- break;
+ bsr = parse_bsr(NULL, optarg);
+ break;
case 'c': /* specify config file */
- if (configfile != NULL) {
- free(configfile);
- }
- configfile = bstrdup(optarg);
- break;
+ if (configfile != NULL) {
+ free(configfile);
+ }
+ configfile = bstrdup(optarg);
+ break;
case 'd': /* debug level */
- debug_level = atoi(optarg);
- if (debug_level <= 0)
- debug_level = 1;
- break;
+ debug_level = atoi(optarg);
+ if (debug_level <= 0)
+ debug_level = 1;
+ break;
case 'v':
- verbose++;
- break;
+ verbose++;
+ break;
case 'i': /* input Volume name */
- iVolumeName = optarg;
- break;
+ iVolumeName = optarg;
+ break;
case 'o': /* output Volume name */
- oVolumeName = optarg;
- break;
+ oVolumeName = optarg;
+ break;
case 'w':
- wd = optarg;
- break;
+ wd = optarg;
+ break;
case '?':
- default:
- usage();
+ default:
+ usage();
}
}
/* Setup and acquire input device for reading */
in_jcr = setup_jcr("bcopy", argv[0], bsr, iVolumeName);
- in_dev = setup_to_access_device(in_jcr, 1); /* read device */
+ in_dev = setup_to_access_device(in_jcr, 1); /* read device */
if (!in_dev) {
exit(1);
}
out_jcr = setup_jcr("bcopy", argv[1], bsr, oVolumeName);
out_dev = setup_to_access_device(out_jcr, 0); /* no acquire */
if (!out_dev) {
- exit(1);
+ exit(1);
}
/* For we must now acquire the device for writing */
out_block = new_block(out_dev);
-static void record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static int record_cb(JCR *in_jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
if (list_records) {
Pmsg5(000, _("Record: SessId=%u SessTim=%u FileIndex=%d Stream=%d len=%u\n"),
- rec->VolSessionId, rec->VolSessionTime, rec->FileIndex,
- rec->Stream, rec->data_len);
+ rec->VolSessionId, rec->VolSessionTime, rec->FileIndex,
+ rec->Stream, rec->data_len);
}
/*
* Check for Start or End of Session Record
if (rec->FileIndex < 0) {
if (verbose > 1) {
- dump_label_record(dev, rec, 1);
+ dump_label_record(dev, rec, 1);
}
switch (rec->FileIndex) {
- case PRE_LABEL:
- Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n");
- return;
- case VOL_LABEL:
- Pmsg0(000, "Volume label not copied.\n");
- return;
- case SOS_LABEL:
- jobs++;
- break;
- case EOS_LABEL:
- 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)) {
- 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)) {
+ case PRE_LABEL:
+ Pmsg0(000, "Volume is prelabeled. This volume cannot be copied.\n");
+ return 1;
+ case VOL_LABEL:
+ Pmsg0(000, "Volume label not copied.\n");
+ return 1;
+ case SOS_LABEL:
+ jobs++;
+ break;
+ case EOS_LABEL:
+ 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)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
- dev_name(out_dev), strerror_dev(out_dev));
+ dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
- strerror_dev(out_dev));
- }
- break;
- case EOM_LABEL:
- Pmsg0(000, "EOM label not copied.\n");
- return;
- case EOT_LABEL: /* end of all tapes */
- Pmsg0(000, "EOT label not copied.\n");
- return;
- default:
- break;
+ strerror_dev(out_dev));
+ }
+ }
+ if (!write_block_to_device(out_jcr, out_dev, 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));
+ }
+ break;
+ case EOM_LABEL:
+ Pmsg0(000, "EOM label not copied.\n");
+ return 1;
+ case EOT_LABEL: /* end of all tapes */
+ Pmsg0(000, "EOT label not copied.\n");
+ return 1;
+ default:
+ break;
}
}
records++;
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);
+ rec->remainder);
if (!write_block_to_device(out_jcr, out_dev, out_block)) {
Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
- dev_name(out_dev), strerror_dev(out_dev));
+ dev_name(out_dev), strerror_dev(out_dev));
Jmsg(out_jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"),
- strerror_dev(out_dev));
- break;
+ strerror_dev(out_dev));
+ break;
}
}
- return;
+ return 1;
}
/* Dummies to replace askdir.c */
-int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;}
-int dir_find_next_appendable_volume(JCR *jcr) { return 1;}
-int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
-int dir_create_jobmedia_record(JCR *jcr) { return 1; }
-int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
-int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
-int dir_send_job_status(JCR *jcr) {return 1;}
+int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) { return 1;}
+int dir_find_next_appendable_volume(JCR *jcr) { return 1;}
+int dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
+int dir_create_jobmedia_record(JCR *jcr) { return 1; }
+int dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
+int dir_send_job_status(JCR *jcr) {return 1;}
int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
{
fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
in_jcr->VolumeName, dev_name(dev));
- getchar();
+ getchar();
return 1;
}
static void do_extract(char *fname);
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
static DEVICE *dev = NULL;
static BFILE bfd;
/*
* Called here for each record from read_records()
*/
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
int stat;
if (rec->FileIndex < 0) {
- return; /* we don't want labels */
+ return 1; /* we don't want labels */
}
/* File Attributes stream */
stream_to_ascii(attr->data_stream));
}
extract = FALSE;
- return;
+ return 1;
}
Emsg3(M_ERROR, 0, _("Seek to %s error on %s: ERR=%s\n"),
edit_uint64(fileAddr, ec1), attr->ofname, berror(&bfd));
extract = FALSE;
- return;
+ return 1;
}
}
} else {
(const Bytef *)wbuf, (uLong)wsize) != Z_OK)) {
Emsg1(M_ERROR, 0, _("Uncompression error. ERR=%d\n"), stat);
extract = FALSE;
- return;
+ return 1;
}
Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
Emsg2(M_ERROR, 0, _("Write error on %s: %s\n"),
attr->ofname, strerror(errno));
extract = FALSE;
- return;
+ return 1;
}
total += compress_len;
fileAddr += compress_len;
if (extract) {
Emsg0(M_ERROR, 0, "GZIP data stream found, but GZIP not configured!\n");
extract = FALSE;
- return;
+ return 1;
}
#endif
break;
break;
} /* end switch */
+ return 1;
}
static void do_ls(char *fname);
static void do_close(JCR *jcr);
static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
static DEVICE *dev;
static int dump_label = FALSE;
/*
* We are only looking for labels or in particula Job Session records
*/
-static void jobs_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static int jobs_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
if (rec->FileIndex < 0) {
dump_label_record(dev, rec, verbose);
}
rec->remainder = 0;
+ return 1;
}
/* Do list job records */
/*
* Called here for each record from read_records()
*/
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
if (rec->FileIndex < 0) {
get_session_record(dev, rec, &sessrec);
- return;
+ return 1;
}
/* File Attributes stream */
if (rec->Stream == STREAM_UNIX_ATTRIBUTES ||
Jmsg(jcr, M_ERROR, 0, _("%s stream not supported on this Client.\n"),
stream_to_ascii(attr->data_stream));
}
- return;
+ return 1;
}
build_attr_output_fnames(jcr, attr);
num_files++;
}
}
- return;
+ return 1;
}
/* Forward referenced functions */
static void do_scan(void);
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
static int create_file_attributes_record(B_DB *db, JCR *mjcr,
char *fname, char *lname, int type,
char *ap, DEV_RECORD *rec);
term_dev(dev);
}
-static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
JCR *mjcr;
char ec1[30];
switch (rec->FileIndex) {
case PRE_LABEL:
Pmsg0(000, _("Volume is prelabeled. This tape cannot be scanned.\n"));
- return;
+ return 1;
break;
case VOL_LABEL:
if (strcmp(pr.PoolType, dev->VolHdr.PoolType) != 0) {
Pmsg2(000, _("VOL_LABEL: PoolType mismatch. DB=%s Vol=%s\n"),
pr.PoolType, dev->VolHdr.PoolType);
- return;
+ return 1;
} else if (verbose) {
Pmsg1(000, _("Pool type \"%s\" is OK.\n"), pr.PoolType);
}
if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
Pmsg2(000, _("VOL_LABEL: MediaType mismatch. DB=%s Vol=%s\n"),
mr.MediaType, dev->VolHdr.MediaType);
- return;
+ return 1;
} else if (verbose) {
Pmsg1(000, _("Media type \"%s\" is OK.\n"), mr.MediaType);
}
Pmsg3(000, _("SOS_LABEL: VolSessId mismatch for JobId=%u. DB=%d Vol=%d\n"),
jr.JobId,
jr.VolSessionId, rec->VolSessionId);
- return;
+ return 1;
}
if (rec->VolSessionTime != jr.VolSessionTime) {
Pmsg3(000, _("SOS_LABEL: VolSessTime mismatch for JobId=%u. DB=%d Vol=%d\n"),
jr.JobId,
jr.VolSessionTime, rec->VolSessionTime);
- return;
+ return 1;
}
if (jr.PoolId != pr.PoolId) {
Pmsg3(000, _("SOS_LABEL: PoolId mismatch for JobId=%u. DB=%d Vol=%d\n"),
jr.JobId,
jr.PoolId, pr.PoolId);
- return;
+ return 1;
}
break;
default:
break;
} /* end switch */
- return;
+ return 1;
}
mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
} else {
ignored_msgs++;
}
- return;
+ return 1;
}
if (mjcr->VolFirstIndex == 0) {
mjcr->VolFirstIndex = block->FirstIndex;
Pmsg2(0, _("Unknown stream type!!! stream=%d data=%s\n"), rec->Stream, rec->data);
break;
}
- return;
+ return 1;
}
/*
static void statcmd();
static void unfillcmd();
static int flush_block(DEV_BLOCK *block, int dump);
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
static void scan_blocks();
static void set_volume_name(char *VolName, int volnum);
/*
* We are called here from "unfill" for each record on the tape.
*/
-static void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
SESSION_LABEL label;
switch (rec->FileIndex) {
case PRE_LABEL:
Pmsg0(-1, "Volume is prelabeled. This tape cannot be scanned.\n");
- return;
+ return 1;;
case VOL_LABEL:
unser_volume_label(dev, rec);
Pmsg3(-1, "VOL_LABEL: block=%u size=%d vol=%s\n", block->BlockNumber,
default:
break;
}
- return;
+ return 1;
}
if (++file_index != rec->FileIndex) {
Pmsg3(000, "Incorrect FileIndex in Block %u. Got %d, expected %d.\n",
if (end_of_tape) {
Pmsg1(000, "End of all blocks. Block=%u\n", block->BlockNumber);
}
+ return 1;
}
{
ser_declare;
- rec->sync = 1; /* wait for completion */
rec->VolSessionId = jcr->VolSessionId;
rec->VolSessionTime = jcr->VolSessionTime;
rec->Stream = jcr->JobId;
uint32_t new_VolSessionId();
/* From acquire.c */
-DEVICE *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);
+DEVICE *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 */
enum get_vol_info_rw {
GET_VOL_INFO_FOR_WRITE,
GET_VOL_INFO_FOR_READ
};
-int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw);
-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, enum get_vol_info_rw);
+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);
+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);
#define CHECK_BLOCK_NUMBERS true
#define NO_BLOCK_NUMBER_CHECK false
-int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
-int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
+int read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
+int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
/* 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, char *VolumeName);
DEVICE *setup_to_access_device(JCR *jcr, int read_access);
-void display_tape_error_status(JCR *jcr, DEVICE *dev);
+void display_tape_error_status(JCR *jcr, 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);
-int dev_can_write(DEVICE *dev);
-int offline_or_rewind_dev(DEVICE *dev);
+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);
+int dev_can_write(DEVICE *dev);
+int offline_or_rewind_dev(DEVICE *dev);
/* 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 set_new_volume_parameters(JCR *jcr, DEVICE *dev);
/* 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 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);
-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);
+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);
int match_bsr_block(BSR *bsr, DEV_BLOCK *block);
void position_bsr_block(BSR *bsr, DEV_BLOCK *block);
/* 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);
-void release_volume(JCR *jcr, DEVICE *dev);
+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);
+void release_volume(JCR *jcr, DEVICE *dev);
/* From autochanger.c */
-int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
-int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
-void invalidate_slot_in_catalog(JCR *jcr);
+int autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
+int autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
+void invalidate_slot_in_catalog(JCR *jcr);
/* 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,
- void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
+ int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
int mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block));
#include "stored.h"
/* Forward referenced subroutines */
-static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
/* Responses sent to the File daemon */
*/
int do_read_data(JCR *jcr)
{
- BSOCK *ds;
- BSOCK *fd_sock = jcr->file_bsock;
+ BSOCK *fd = jcr->file_bsock;
int ok = TRUE;
- int done = FALSE;
DEVICE *dev;
- DEV_RECORD *rec;
DEV_BLOCK *block;
- POOLMEM *hdr;
- SESSION_LABEL sessrec; /* session record */
- uint32_t BlockNumber = 0;
Dmsg0(20, "Start read data.\n");
dev = jcr->device->dev;
- memset(&sessrec, 0, sizeof(sessrec));
/* Tell File daemon we will send data */
- bnet_fsend(fd_sock, OK_data);
- Dmsg1(10, "bstored>filed: %s\n", fd_sock->msg);
+ bnet_fsend(fd, OK_data);
+ Dmsg1(10, "bstored>filed: %s\n", fd->msg);
- ds = fd_sock;
-
- if (!bnet_set_buffer_size(ds, MAX_NETWORK_BUFFER_SIZE, BNET_SETBUF_READ)) {
+ if (!bnet_set_buffer_size(fd, MAX_NETWORK_BUFFER_SIZE, BNET_SETBUF_READ)) {
return 0;
}
return 0;
}
- rec = new_record();
- free_pool_memory(rec->data);
- rec->data = ds->msg; /* use socket message buffer */
- hdr = get_pool_memory(PM_MESSAGE);
-
- /*
- * Read records, apply BSR filtering, and return any that are
- * matched.
- */
- for ( ; ok && !done; ) {
- if (job_canceled(jcr)) {
- ok = FALSE;
- break;
- }
- /* Read Record */
- Dmsg1(500, "Main read_record. rem=%d\n", rec->remainder);
-
- if (block_is_empty(block) && !read_block_from_device(jcr, dev, block, CHECK_BLOCK_NUMBERS)) {
- Dmsg1(500, "Main read record failed. rem=%d\n", rec->remainder);
- if (dev->state & ST_EOT) {
- DEV_RECORD *record;
- if (!mount_next_read_volume(jcr, dev, block)) {
- break;
- }
- /* Read and discard Volume Label */
- record = new_record();
- read_block_from_device(jcr, dev, block, NO_BLOCK_NUMBER_CHECK);
- read_record_from_block(block, record);
- get_session_record(dev, record, &sessrec);
- free_record(record);
- /* Now, continue to read the records on this volume */
-
- } else if (dev->state & ST_EOF) {
- Dmsg0(90, "Got End of File. Trying again ...\n");
- continue; /* End of File */
- } else if (dev->state & ST_SHORT) {
- continue;
- } else {
- /* I/O error -- or non-standard end of tape */
- Dmsg0(000, "I/O error, bailing out.\n");
- ok = FALSE;
- break;
- }
- }
-
- if (!block_is_empty(block) && !match_bsr_block(jcr->bsr, block)) {
- Dmsg5(150, "reject Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n",
- block->BlockNumber, block->block_len, block->BlockVer,
- block->VolSessionId, block->VolSessionTime);
- empty_block(block); /* force read next block */
- continue;
- }
-
- for (rec->state=0; !is_block_empty(rec); ) {
-
- if (!read_record_from_block(block, rec)) {
- break;
- }
- /*
- * At this point, we have at least a record header.
- * Now decide if we want this record or not, but remember
- * before accessing the record, we may need to read again to
- * get all the data.
- */
-
- if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
- Dmsg0(40, "Get EOM LABEL\n");
- rec->remainder = 0;
- break; /* yes, get out */
- }
-
- /* Some sort of label? */
- if (rec->FileIndex < 0) {
- get_session_record(dev, rec, &sessrec);
- continue;
- } /* end if label record */
-
-
- /* Match BSR against current record */
- if (jcr->bsr) {
- int stat = match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec);
- if (stat == -1) { /* no more possible matches */
- done = TRUE;
- break;
- } else if (stat == 0) { /* no match */
- Dmsg0(50, "BSR rejected record\n");
- rec->remainder = 0;
- continue;
- }
- } else {
- /* Old way, deprecated */
- if (rec->VolSessionId != jcr->read_VolSessionId ||
- rec->VolSessionTime != jcr->read_VolSessionTime) {
- Dmsg0(50, "Ignore record ids not equal\n");
- rec->remainder = 0;
- continue; /* ignore */
- }
- }
-
- if (block->block_read) {
- if (BlockNumber != block->BlockNumber) {
- Jmsg(jcr, M_ERROR, 0, _("Invalid block number. Expected %u, got %u\n"),
- BlockNumber, block->BlockNumber);
- }
- BlockNumber = block->BlockNumber + 1;
- block->block_read = false;
- }
+ ok = read_records(jcr, dev, record_cb, mount_next_read_volume);
- if (is_partial_record(rec)) {
- break; /* Go read full record */
- }
-
- /*
- * We "finally" have a full record here. Now
- * generate Header parameters and send to File daemon
- * Note, we build header in hdr buffer to avoid wiping
- * out the data record
- */
- ds->msg = hdr;
- Dmsg5(400, "Send to FD: SessId=%u SessTim=%u FI=%d Strm=%d, len=%d\n",
- rec->VolSessionId, rec->VolSessionTime, rec->FileIndex, rec->Stream,
- rec->data_len);
- if (!bnet_fsend(ds, rec_header, rec->VolSessionId, rec->VolSessionTime,
- rec->FileIndex, rec->Stream, rec->data_len)) {
- Dmsg1(30, ">filed: Error Hdr=%s\n", ds->msg);
- hdr = ds->msg;
- ds->msg = rec->data;
- Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
- bnet_strerror(ds));
- ok = FALSE;
- break;
- } else {
- Dmsg1(30, ">filed: Hdr=%s\n", ds->msg);
- }
-
- hdr = ds->msg; /* restore hdr buffer */
- ds->msg = rec->data; /* restore data record address */
-
- /* Send data record to File daemon */
- ds->msglen = rec->data_len;
- Dmsg1(40, ">filed: send %d bytes data.\n", ds->msglen);
- if (!bnet_send(ds)) {
- Pmsg1(000, "Error sending to FD. ERR=%s\n", bnet_strerror(ds));
- Dmsg1(100, "Hdr=%s\n", hdr);
- Dmsg1(100, "data=%s\n", ds->msg);
- Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
- bnet_strerror(ds));
- ok = FALSE;
- break;
- }
- } /* end for loop reading records */
- } /* end for loop reading blocks */
/* Send end of data to FD */
- bnet_sig(ds, BNET_EOD);
+ bnet_sig(fd, BNET_EOD);
if (!release_device(jcr, dev)) {
ok = FALSE;
}
- free_pool_memory(hdr);
+
free_block(block);
- rec->data = NULL; /* previously released */
- free_record(rec);
free_vol_list(jcr);
Dmsg0(30, "Done reading.\n");
return ok ? 1 : 0;
}
-static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec)
+/*
+ * Called here for each record from read_records()
+ */
+static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
{
- char *rtype;
- memset(sessrec, 0, sizeof(sessrec));
- switch (rec->FileIndex) {
- case PRE_LABEL:
- rtype = "Fresh Volume Label";
- break;
- case VOL_LABEL:
- rtype = "Volume Label";
- unser_volume_label(dev, rec);
- break;
- case SOS_LABEL:
- rtype = "Begin Session";
- unser_session_label(sessrec, rec);
- break;
- case EOS_LABEL:
- rtype = "End Session";
- break;
- case EOM_LABEL:
- rtype = "End of Media";
- break;
- default:
- rtype = "Unknown";
- break;
+ BSOCK *fd = jcr->file_bsock;
+ int ok = TRUE;
+ POOLMEM *save_msg;
+
+ if (rec->FileIndex < 0) {
+ return 1;
+ }
+ Dmsg5(100, "Send to FD: SessId=%u SessTim=%u FI=%d Strm=%d, len=%d\n",
+ rec->VolSessionId, rec->VolSessionTime, rec->FileIndex, rec->Stream,
+ rec->data_len);
+
+ /* Send record header to File daemon */
+ if (!bnet_fsend(fd, rec_header, rec->VolSessionId, rec->VolSessionTime,
+ rec->FileIndex, rec->Stream, rec->data_len)) {
+ Dmsg1(30, ">filed: Error Hdr=%s\n", fd->msg);
+ Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
+ bnet_strerror(fd));
+ return FALSE;
+ } else {
+ Dmsg1(30, ">filed: Hdr=%s\n", fd->msg);
+ }
+
+
+ /* Send data record to File daemon */
+ save_msg = fd->msg; /* save fd message pointer */
+ fd->msg = rec->data; /* pass data directly to bnet_send */
+ fd->msglen = rec->data_len;
+ Dmsg1(30, ">filed: send %d bytes data.\n", fd->msglen);
+ if (!bnet_send(fd)) {
+ Pmsg1(000, "Error sending to FD. ERR=%s\n", bnet_strerror(fd));
+ Jmsg1(jcr, M_FATAL, 0, _("Error sending to File daemon. ERR=%s\n"),
+ bnet_strerror(fd));
+
+ ok = FALSE;
}
- Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
- rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
+ fd->msg = save_msg; /* restore fd message pointer */
+ return ok;
}
#endif
int read_records(JCR *jcr, DEVICE *dev,
- void record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
+ int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec),
int mount_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block))
{
DEV_BLOCK *block;
- DEV_RECORD *rec;
- uint32_t record, num_files = 0;
+ DEV_RECORD *rec = NULL;
+ uint32_t record;
int ok = TRUE;
- int done = FALSE;
+ bool done = false;
SESSION_LABEL sessrec;
+ dlist *recs;
block = new_block(dev);
- rec = new_record();
+ recs = new dlist(rec, &rec->link);
+
for ( ; ok && !done; ) {
if (job_canceled(jcr)) {
ok = FALSE;
Dmsg3(100, "EOT. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec),
block->BlockNumber, rec->remainder);
- Jmsg(jcr, M_INFO, 0, "Got EOM at file %u on device %s, Volume \"%s\"\n",
+ Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n",
dev->file, dev_name(dev), jcr->VolumeName);
if (!mount_cb(jcr, dev, block)) {
Jmsg(jcr, M_INFO, 0, "End of all volumes.\n");
trec->FileIndex = EOT_LABEL;
trec->File = dev->file;
trec->Block = rec->Block; /* return block last read */
- record_cb(jcr, dev, block, trec);
+ ok = record_cb(jcr, dev, block, trec);
free_record(trec);
break;
}
read_block_from_device(jcr, dev, block, NO_BLOCK_NUMBER_CHECK);
read_record_from_block(block, trec);
get_session_record(dev, trec, &sessrec);
- record_cb(jcr, dev, block, trec);
+ ok = record_cb(jcr, dev, block, trec);
free_record(trec);
- goto next_record; /* go read new tape */
-
} else if (dev->state & ST_EOF) {
Jmsg(jcr, M_INFO, 0, "Got EOF at file %u on device %s, Volume \"%s\"\n",
dev->file, dev_name(dev), jcr->VolumeName);
Dmsg0(20, "read_record got eof. try again\n");
continue;
} else if (dev->state & ST_SHORT) {
- Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg);
+ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
continue;
} else {
/* I/O error or strange end of tape */
block->VolSessionId, block->VolSessionTime);
continue;
}
- if (verbose) {
- Pmsg4(000, "Block: %d VI=%u VT=%u blen=%d\n", block->BlockNumber,
- block->VolSessionId, block->VolSessionTime, block->block_len);
- }
+ Dmsg4(100, "Block: %d VI=%u VT=%u blen=%d\n", block->BlockNumber,
+ block->VolSessionId, block->VolSessionTime, block->block_len);
-next_record:
+ /*
+ * Get a new record for each Job as defined by
+ * VolSessionId and VolSessionTime
+ */
+ bool found = false;
+ for (rec=(DEV_RECORD *)recs->first(); rec; rec=(DEV_RECORD *)recs->next(rec)) {
+ if (rec->VolSessionId == block->VolSessionId &&
+ rec->VolSessionTime == block->VolSessionTime) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ rec = new_record();
+ recs->prepend(rec);
+ Dmsg2(100, "New record for SI=%d ST=%d\n",
+ block->VolSessionId, block->VolSessionTime);
+ } else {
+ if ((rec->Block+1) != block->BlockNumber) {
+ Jmsg(jcr, M_ERROR, 0, _("Invalid block number. Expected %u, got %u\n"),
+ rec->Block+1, block->BlockNumber);
+ }
+ }
record = 0;
for (rec->state=0; !is_block_empty(rec); ) {
if (!read_record_from_block(block, rec)) {
* get all the data.
*/
record++;
- if (verbose) {
- Dmsg6(30, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
- rec_state_to_str(rec), block->BlockNumber,
- rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
- }
- if (debug_level >= 30) {
- Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId,
- FI_to_ascii(rec->FileIndex),
- stream_to_ascii(rec->Stream, rec->FileIndex),
- rec->data_len);
- }
+ Dmsg6(30, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
+ rec_state_to_str(rec), block->BlockNumber,
+ rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
+ Dmsg4(30, "VolSId=%ld FI=%s Strm=%s Size=%ld\n", rec->VolSessionId,
+ FI_to_ascii(rec->FileIndex),
+ stream_to_ascii(rec->Stream, rec->FileIndex),
+ rec->data_len);
if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
Dmsg0(40, "Get EOM LABEL\n");
- rec->remainder = 0;
break; /* yes, get out */
}
/* Some sort of label? */
if (rec->FileIndex < 0) {
get_session_record(dev, rec, &sessrec);
- record_cb(jcr, dev, block, rec);
+ ok = record_cb(jcr, dev, block, rec);
+ if (rec->FileIndex == EOS_LABEL) {
+ Dmsg2(100, "Remove rec. SI=%d ST=%d\n", rec->VolSessionId,
+ rec->VolSessionTime);
+ recs->remove(rec);
+ free_record(rec);
+ }
continue;
} /* end if label record */
if (jcr->bsr) {
int stat = match_bsr(jcr->bsr, rec, &dev->VolHdr, &sessrec);
if (stat == -1) { /* no more possible matches */
- done = TRUE; /* all items found, stop */
+ done = true; /* all items found, stop */
break;
} else if (stat == 0) { /* no match */
- if (verbose) {
- Dmsg5(10, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n",
- record, block->BlockNumber, rec->VolSessionId, rec->VolSessionTime,
- rec->FileIndex);
- }
- rec->remainder = 0;
+ Dmsg5(10, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n",
+ record, block->BlockNumber, rec->VolSessionId, rec->VolSessionTime,
+ rec->FileIndex);
continue; /* we don't want record, read next one */
}
}
rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
break; /* read second part of record */
}
- record_cb(jcr, dev, block, rec);
- }
- }
- if (verbose) {
- printf("%u files found.\n", num_files);
+ ok = record_cb(jcr, dev, block, rec);
+ } /* end for loop over records */
+ } /* end for loop over blocks */
+
+ /* Walk down list and free all remaining allocated recs */
+ for (rec=(DEV_RECORD *)recs->first(); rec; ) {
+ DEV_RECORD *nrec = (DEV_RECORD *)recs->next(rec);
+ recs->remove(rec);
+ free_record(rec);
+ rec = nrec;
}
- free_record(rec);
+ delete recs;
free_block(block);
return ok;
}
char *rtype;
memset(sessrec, 0, sizeof(sessrec));
switch (rec->FileIndex) {
- case PRE_LABEL:
- rtype = "Fresh Volume Label";
- break;
- case VOL_LABEL:
- rtype = "Volume Label";
- unser_volume_label(dev, rec);
- break;
- case SOS_LABEL:
- rtype = "Begin Session";
- unser_session_label(sessrec, rec);
- break;
- case EOS_LABEL:
- rtype = "End Session";
- break;
- case EOM_LABEL:
- rtype = "End of Media";
- break;
- default:
- rtype = "Unknown";
- break;
+ case PRE_LABEL:
+ rtype = "Fresh Volume Label";
+ break;
+ case VOL_LABEL:
+ rtype = "Volume Label";
+ unser_volume_label(dev, rec);
+ break;
+ case SOS_LABEL:
+ rtype = "Begin Session";
+ unser_session_label(sessrec, rec);
+ break;
+ case EOS_LABEL:
+ rtype = "End Session";
+ break;
+ case EOM_LABEL:
+ rtype = "End of Media";
+ break;
+ default:
+ rtype = "Unknown";
+ break;
}
Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
#define __RECORD_H 1
/* Return codes from read_device_volume_label() */
-#define VOL_NOT_READ 0 /* Volume label not read */
-#define VOL_OK 1 /* volume name OK */
-#define VOL_NO_LABEL 2 /* volume not labeled */
-#define VOL_IO_ERROR 3 /* volume I/O error */
-#define VOL_NAME_ERROR 4 /* Volume name mismatch */
-#define VOL_CREATE_ERROR 5 /* Error creating label */
-#define VOL_VERSION_ERROR 6 /* Bacula version error */
-#define VOL_LABEL_ERROR 7 /* Bad label type */
-#define VOL_NO_MEDIA 8 /* Hard error -- no media present */
+#define VOL_NOT_READ 0 /* Volume label not read */
+#define VOL_OK 1 /* volume name OK */
+#define VOL_NO_LABEL 2 /* volume not labeled */
+#define VOL_IO_ERROR 3 /* volume I/O error */
+#define VOL_NAME_ERROR 4 /* Volume name mismatch */
+#define VOL_CREATE_ERROR 5 /* Error creating label */
+#define VOL_VERSION_ERROR 6 /* Bacula version error */
+#define VOL_LABEL_ERROR 7 /* Bad label type */
+#define VOL_NO_MEDIA 8 /* Hard error -- no media present */
/* See block.h for RECHDR_LENGTH */
*/
/* Record state bit definitions */
-#define REC_NO_HEADER (1<<0) /* No header read */
+#define REC_NO_HEADER (1<<0) /* No header read */
#define REC_PARTIAL_RECORD (1<<1) /* returning partial record */
#define REC_BLOCK_EMPTY (1<<2) /* not enough data in block */
-#define REC_NO_MATCH (1<<3) /* No match on continuation data */
+#define REC_NO_MATCH (1<<3) /* No match on continuation data */
#define REC_CONTINUATION (1<<4) /* Continuation record found */
-#define REC_ISTAPE (1<<5) /* Set if device is tape */
+#define REC_ISTAPE (1<<5) /* Set if device is tape */
#define is_partial_record(r) ((r)->state & REC_PARTIAL_RECORD)
#define is_block_empty(r) ((r)->state & REC_BLOCK_EMPTY)
* This is the memory structure for the record header.
*/
struct DEV_RECORD {
- int sync; /* synchronous */
- /* File and Block are always returned on reading records, but
- * only returned on writing if sync is set (obviously).
+ dlink link; /* link for chaining in read_record.c */
+ /* File and Block are always returned during reading
+ * and writing records.
*/
- uint32_t File; /* File number */
- uint32_t Block; /* Block number */
- uint32_t VolSessionId; /* sequential id within this session */
- uint32_t VolSessionTime; /* session start time */
- int32_t FileIndex; /* sequential file number */
- int32_t Stream; /* stream number */
- uint32_t data_len; /* current record length */
- uint32_t remainder; /* remaining bytes to read/write */
- uint32_t state; /* state bits */
+ uint32_t File; /* File number */
+ uint32_t Block; /* Block number */
+ uint32_t VolSessionId; /* sequential id within this session */
+ uint32_t VolSessionTime; /* session start time */
+ int32_t FileIndex; /* sequential file number */
+ int32_t Stream; /* stream number */
+ uint32_t data_len; /* current record length */
+ uint32_t remainder; /* remaining bytes to read/write */
+ uint32_t state; /* state bits */
uint8_t ser_buf[WRITE_RECHDR_LENGTH]; /* serialized record header goes here */
- POOLMEM *data; /* Record data. This MUST be a memory pool item */
-};
+ POOLMEM *data; /* Record data. This MUST be a memory pool item */
+};
/*
* Note, these values are negative to distinguish them
* from user records where the FileIndex is forced positive.
*/
-#define PRE_LABEL -1 /* Vol label on unwritten tape */
-#define VOL_LABEL -2 /* Volume label first file */
-#define EOM_LABEL -3 /* Writen at end of tape */
-#define SOS_LABEL -4 /* Start of Session */
-#define EOS_LABEL -5 /* End of Session */
-#define EOT_LABEL -6 /* End of physical tape (2 eofs) */
+#define PRE_LABEL -1 /* Vol label on unwritten tape */
+#define VOL_LABEL -2 /* Volume label first file */
+#define EOM_LABEL -3 /* Writen at end of tape */
+#define SOS_LABEL -4 /* Start of Session */
+#define EOS_LABEL -5 /* End of Session */
+#define EOT_LABEL -6 /* End of physical tape (2 eofs) */
/*
* Volume Label Record. This is the in-memory definition. The
* in the DEVICE buffer, but are not actually written
* to the tape.
*/
- int32_t LabelType; /* This is written in header only */
- uint32_t LabelSize; /* length of serialized label */
+ int32_t LabelType; /* This is written in header only */
+ uint32_t LabelSize; /* length of serialized label */
/*
* The items below this line are stored on
* the tape
*/
- char Id[32]; /* Bacula Immortal ... */
+ char Id[32]; /* Bacula Immortal ... */
- uint32_t VerNum; /* Label version number */
+ uint32_t VerNum; /* Label version number */
/* VerNum <= 10 */
- float64_t label_date; /* Date tape labeled */
- float64_t label_time; /* Time tape labeled */
+ float64_t label_date; /* Date tape labeled */
+ float64_t label_time; /* Time tape labeled */
/* VerNum >= 11 */
- btime_t label_btime; /* tdate tape labeled */
- btime_t write_btime; /* tdate tape written */
+ btime_t label_btime; /* tdate tape labeled */
+ btime_t write_btime; /* tdate tape written */
/* Unused with VerNum >= 11 */
- float64_t write_date; /* Date this label written */
- float64_t write_time; /* Time this label written */
+ float64_t write_date; /* Date this label written */
+ float64_t write_time; /* Time this label written */
char VolName[MAX_NAME_LENGTH]; /* Volume name */
char PrevVolName[MAX_NAME_LENGTH]; /* Previous Volume Name */
char MediaType[MAX_NAME_LENGTH]; /* Type of this media */
char HostName[MAX_NAME_LENGTH]; /* Host name of writing computer */
- char LabelProg[50]; /* Label program name */
- char ProgVersion[50]; /* Program version */
- char ProgDate[50]; /* Program build date/time */
+ 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 */
* This record is at the beginning and end of each session
*/
struct Session_Label {
- char Id[32]; /* Bacula Immortal ... */
+ char Id[32]; /* Bacula Immortal ... */
- uint32_t VerNum; /* Label version number */
+ uint32_t VerNum; /* Label version number */
- uint32_t JobId; /* Job id */
- uint32_t VolumeIndex; /* Sequence no of volume for this job */
+ uint32_t JobId; /* Job id */
+ uint32_t VolumeIndex; /* Sequence no of volume for this job */
/* VerNum >= 11 */
- btime_t write_btime; /* Tdate this label written */
+ btime_t write_btime; /* Tdate this label written */
/* VerNum < 11 */
- float64_t write_date; /* Date this label written */
+ float64_t write_date; /* Date this label written */
/* Unused VerNum >= 11 */
- float64_t write_time; /* Time this label written */
+ float64_t write_time; /* Time this label written */
char PoolName[MAX_NAME_LENGTH]; /* Pool name */
char PoolType[MAX_NAME_LENGTH]; /* Pool type */
char JobName[MAX_NAME_LENGTH]; /* base Job name */
char ClientName[MAX_NAME_LENGTH];
- char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */
+ char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */
char FileSetName[MAX_NAME_LENGTH];
char FileSetMD5[MAX_NAME_LENGTH];
uint32_t JobType;
uint32_t StartFile;
uint32_t EndFile;
uint32_t JobErrors;
- uint32_t JobStatus; /* Job status */
+ uint32_t JobStatus; /* Job status */
};
typedef struct Session_Label SESSION_LABEL;
-#define SERIAL_BUFSIZE 1024 /* volume serialisation buffer size */
+#define SERIAL_BUFSIZE 1024 /* volume serialisation buffer size */
#endif
/* */
-#define VERSION "1.31a"
+#define VERSION "1.31b"
#define VSTRING "1"
-#define BDATE "02 Aug 2003"
-#define LSMDATE "02Aug03"
+#define BDATE "03 Aug 2003"
+#define LSMDATE "03Aug03"
/* Debug flags */
#define DEBUG 1