/* Must create it */
Mmsg(&mdb->cmd,
-"INSERT INTO JobMedia (JobId, MediaId, FirstIndex, LastIndex) \
-VALUES (%d, %d, %u, %u)",
- jm->JobId, jm->MediaId, jm->FirstIndex, jm->LastIndex);
+"INSERT INTO JobMedia (JobId,MediaId,FirstIndex,LastIndex,\
+StartFile,EndFile,StartBlock,EndBlock) \
+VALUES (%u,%u,%u,%u,%u,%u,%u,%u)",
+ jm->JobId, jm->MediaId, jm->FirstIndex, jm->LastIndex,
+ jm->StartFile, jm->EndFile, jm->StartBlock, jm->EndBlock);
Dmsg0(30, mdb->cmd);
if (!INSERT_DB(mdb, mdb->cmd)) {
* Otherwise, record the fact that this job used this Volume
*/
if (!relabel) {
- Dmsg4(100, "create_jobmedia JobId=%d MediaId=%d FI=%d LI=%d\n",
- jm.JobId, jm.MediaId, jm.FirstIndex, jm.LastIndex);
+ Dmsg6(100, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n",
+ jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex);
if(!db_create_jobmedia_record(jcr->db, &jm)) {
Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"),
db_strerror(jcr->db));
*/
static void print_ls_output(JCR *jcr, char *fname, char *lname, int type, struct stat *statp)
{
- /* ********FIXME******** make memory pool */
- char buf[1000];
+ char buf[2000];
+ char ec1[30];
char *p, *f;
int n;
p += n;
n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
p += n;
- n = sprintf(p, "%8" lld " ", (uint64_t)statp->st_size);
+ n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
p += n;
p = encode_time(statp->st_ctime, p);
*p++ = ' ';
*p++ = ' ';
- for (f=fname; *f; )
+ for (f=fname; *f && (p-buf) < (int)sizeof(buf); )
*p++ = *f++;
if (type == FT_LNK) {
*p++ = ' ';
*p++ = '>';
*p++ = ' ';
/* Copy link name */
- for (f=lname; *f; )
+ for (f=lname; *f && (p-buf) < (int)sizeof(buf); )
*p++ = *f++;
}
*p++ = '\n';
extern int debug_level;
+/*
+ * Scan to "logical" end of line. I.e. end of line,
+ * or semicolon.
+ */
+void scan_to_eol(LEX *lc)
+{
+ int token;
+ Dmsg0(150, "start scan to eof\n");
+ while ((token = lex_get_token(lc)) != T_EOL) {
+ }
+ Dmsg0(150, "done scan to eof\n");
+}
+
+
+/*
+ * Format a scanner error message
+ */
+void s_err(char *file, int line, LEX *lc, char *msg, ...)
+{
+ va_list arg_ptr;
+ char buf[MAXSTRING];
+
+ va_start(arg_ptr, msg);
+ bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
+ va_end(arg_ptr);
+
+ e_msg(file, line, M_ERROR_TERM, 0, "Config error: %s,\n\
+ : Line %d, col %d of file %s\n%s\n",
+ buf, lc->line_no, lc->col_no, lc->fname, lc->line);
+}
+
+
/*
* Free the current file, and retrieve the contents
* of the previous packet if any.
sprintf(con_fname, "%s/%s.conmsg", wd, my_name);
fd = open(con_fname, O_CREAT|O_RDWR|O_BINARY, 0600);
if (fd == -1) {
- Emsg2(M_TERM, 0, "Could not open console message file %s: ERR=%s\n",
+ Emsg2(M_ERROR_TERM, 0, "Could not open console message file %s: ERR=%s\n",
con_fname, strerror(errno));
}
if (lseek(fd, 0, SEEK_END) > 0) {
Dmsg2(200, "Enter dispatch_msg type=%d msg=%s\n", type, msg);
- if (type == M_ABORT || type == M_TERM) {
+ if (type == M_ABORT || type == M_ERROR_TERM) {
fprintf(stdout, msg); /* print this here to INSURE that it is printed */
}
break;
case MD_STDOUT:
Dmsg1(200, "STDOUT for following err: %s\n", msg);
- if (type != M_ABORT && type != M_TERM) /* already printed */
+ if (type != M_ABORT && type != M_ERROR_TERM) /* already printed */
fprintf(stdout, msg);
break;
case MD_STDERR:
/*
* Check if we have a message destination defined.
- * We always report M_ABORT and M_TERM
+ * We always report M_ABORT and M_ERROR_TERM
*/
- if (!daemon_msgs || ((type != M_ABORT && type != M_TERM) &&
+ if (!daemon_msgs || ((type != M_ABORT && type != M_ERROR_TERM) &&
!bit_is_set(type, daemon_msgs->send_msg)))
return; /* no destination */
switch (type) {
sprintf(buf, "%s ABORTING due to ERROR in %s:%d\n",
my_name, file, line);
break;
- case M_TERM:
- sprintf(buf, "%s TERMINATING due to ERROR in %s:%d\n",
+ case M_ERROR_TERM:
+ sprintf(buf, "%s ERROR TERMINATING at %s:%d\n",
my_name, file, line);
break;
case M_FATAL:
char *p = 0;
p[0] = 0; /* generate segmentation violation */
}
- if (type == M_TERM) {
+ if (type == M_ERROR_TERM) {
_exit(1);
}
}
buf = rbuf; /* we are the Director */
/*
* Check if we have a message destination defined.
- * We always report M_ABORT and M_TERM
+ * We always report M_ABORT and M_ERROR_TERM
*/
- if ((type != M_ABORT && type != M_TERM) && msgs && !bit_is_set(type, msgs->send_msg)) {
+ if ((type != M_ABORT && type != M_ERROR_TERM) && msgs && !bit_is_set(type, msgs->send_msg)) {
Dmsg1(200, "No bit set for type %d\n", type);
return; /* no destination */
}
case M_ABORT:
sprintf(buf, "%s ABORTING due to ERROR\n", my_name);
break;
- case M_TERM:
- sprintf(buf, "%s TERMINATING due to ERROR\n", my_name);
+ case M_ERROR_TERM:
+ sprintf(buf, "%s ERROR TERMINATING\n", my_name);
break;
case M_FATAL:
sprintf(buf, "%s: Job %s Fatal error: ", my_name, job);
char *p = 0;
p[0] = 0; /* generate segmentation violation */
}
- if (type == M_TERM) {
+ if (type == M_ERROR_TERM) {
_exit(1);
}
}
#include "bits.h"
-#undef M_DEBUG
-#undef M_ABORT
-#undef M_FATAL
-#undef M_ERROR
-#undef M_WARNING
-#undef M_INFO
-#undef M_MOUNT
-#undef M_TERM
+#undef M_DEBUG
+#undef M_ABORT
+#undef M_FATAL
+#undef M_ERROR
+#undef M_WARNING
+#undef M_INFO
+#undef M_MOUNT
+#undef M_ERROR_TERM
+#undef M_TERM
-#define M_DEBUG 1 /* debug message */
-#define M_ABORT 2 /* MUST abort immediately */
-#define M_FATAL 3 /* Fatal error, stopping job */
-#define M_ERROR 4 /* Error, but recoverable */
-#define M_WARNING 5 /* Warning message */
-#define M_INFO 6 /* Informational message */
-#define M_SAVED 7 /* Info on saved file */
-#define M_NOTSAVED 8 /* Info on notsaved file */
-#define M_SKIPPED 9 /* File skipped by option setting */
-#define M_MOUNT 10 /* Mount requests */
-#define M_TERM 11 /* Termination request */
+/*
+ * Most of these message levels are more or less obvious.
+ * They have evolved somewhat during the development of Bacula,
+ * and here are some of the details of where I am trying to
+ * head (in the process of changing the code) as of 15 June 2002.
+ *
+ * M_ABORT Bacula immediately aborts and tries to produce a traceback
+ * This is for really serious errors like segmentation fault.
+ * M_ERROR_TERM Bacula immediately terminates but no dump. This is for
+ * "obvious" serious errors like daemon already running or
+ * cannot open critical file, ... where a dump is not wanted.
+ * M_TERM Bacula daemon shutting down because of request (SIGTERM).
+ *
+ * The remaining apply to Jobs rather than the daemon.
+ *
+ * M_FATAL Bacula detected a fatal Job error. The Job will be killed,
+ * but Bacula continues running.
+ * M_ERROR Bacula detected a Job error. The Job will continue running
+ * but the termination status will be error.
+ * M_WARNING Job warning message.
+ * M_INFO Job information message.
+ *
+ */
+
+#define M_DEBUG 1 /* debug message */
+#define M_ABORT 2 /* MUST abort immediately */
+#define M_FATAL 3 /* Fatal error, stopping job */
+#define M_ERROR 4 /* Error, but recoverable */
+#define M_WARNING 5 /* Warning message */
+#define M_INFO 6 /* Informational message */
+#define M_SAVED 7 /* Info on saved file */
+#define M_NOTSAVED 8 /* Info on notsaved file */
+#define M_SKIPPED 9 /* File skipped by option setting */
+#define M_MOUNT 10 /* Mount requests */
+#define M_ERROR_TERM 11 /* Error termination request (no dump) */
+#define M_TERM 12 /* Terminating daemon */
-#define M_MAX M_TERM /* keep this updated ! */
+#define M_MAX M_TERM /* keep this updated ! */
/* Define message destination structure */
/* *** FIXME **** where should be extended to handle multiple values */
typedef struct s_dest {
struct s_dest *next;
- int dest_code; /* destination (one of the MD_ codes) */
- int max_len; /* max mail line length */
- FILE *fd; /* file descriptor */
+ int dest_code; /* destination (one of the MD_ codes) */
+ int max_len; /* max mail line length */
+ FILE *fd; /* file descriptor */
char msg_types[nbytes_for_bits(M_MAX+1)]; /* message type mask */
- char *where; /* filename/program name */
- char *mail_cmd; /* mail command */
- POOLMEM *mail_filename; /* unique mail filename */
+ char *where; /* filename/program name */
+ char *mail_cmd; /* mail command */
+ POOLMEM *mail_filename; /* unique mail filename */
} DEST;
/* Message Destination values for dest field of DEST */
-#define MD_SYSLOG 1 /* send msg to syslog */
-#define MD_MAIL 2 /* email group of messages */
-#define MD_FILE 3 /* write messages to a file */
-#define MD_APPEND 4 /* append messages to a file */
-#define MD_STDOUT 5 /* print messages */
-#define MD_STDERR 6 /* print messages to stderr */
-#define MD_DIRECTOR 7 /* send message to the Director */
-#define MD_OPERATOR 8 /* email a single message to the operator */
-#define MD_CONSOLE 9 /* send msg to UserAgent or console */
-#define MD_MAIL_ON_ERROR 10 /* email messages if job errors */
+#define MD_SYSLOG 1 /* send msg to syslog */
+#define MD_MAIL 2 /* email group of messages */
+#define MD_FILE 3 /* write messages to a file */
+#define MD_APPEND 4 /* append messages to a file */
+#define MD_STDOUT 5 /* print messages */
+#define MD_STDERR 6 /* print messages to stderr */
+#define MD_DIRECTOR 7 /* send message to the Director */
+#define MD_OPERATOR 8 /* email a single message to the operator */
+#define MD_CONSOLE 9 /* send msg to UserAgent or console */
+#define MD_MAIL_ON_ERROR 10 /* email messages if job errors */
void d_msg(char *file, int line, int level, char *fmt,...);
}
/* If this triggers, take a look at lib/parse_conf.h */
if (i >= MAX_RES_ITEMS) {
- Emsg1(M_ABORT, 0, _("Too many items in %s resource\n"), resources[rindex]);
+ Emsg1(M_ERROR_TERM, 0, _("Too many items in %s resource\n"), resources[rindex]);
}
}
}
int token;
token = lex_get_token(lc);
- lcase(lc->str);
if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
scan_err1(lc, "expected an identifier or string, got: %s", lc->str);
- } else if (strcmp(lc->str, "yes") == 0) {
+ } else if (strcasecmp(lc->str, "yes") == 0) {
*(int *)(item->value) |= item->code;
- } else if (strcmp(lc->str, "no") == 0) {
+ } else if (strcasecmp(lc->str, "no") == 0) {
*(int *)(item->value) &= ~(item->code);
} else {
scan_err1(lc, "Expect a YES or NO, got: %s", lc->str);
}
-/*
- * Scan to "logical" end of line. I.e. end of line,
- * or semicolon.
- */
-void scan_to_eol(LEX *lc)
-{
- int token;
- Dmsg0(150, "start scan to eof\n");
- while ((token = lex_get_token(lc)) != T_EOL) {
- }
- Dmsg0(150, "done scan to eof\n");
-}
-
-
-/*
- * Format a scanner error message
- */
-void s_err(char *file, int line, LEX *lc, char *msg, ...)
-{
- va_list arg_ptr;
- char buf[MAXSTRING];
-
- va_start(arg_ptr, msg);
- bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
- va_end(arg_ptr);
-
- e_msg(file, line, M_ABORT, 0, "Config error: %s,\n\
- : Line %d, col %d of file %s\n%s\n",
- buf, lc->line_no, lc->col_no, lc->fname, lc->line);
-}
void LockRes()
{
if (token != T_IDENTIFIER) {
scan_err1(lc, "Expected a Resource name identifier, got: %s", lc->str);
}
- lcase(lc->str);
for (i=0; resources[i].name; i++)
- if (strcmp(resources[i].name, lc->str) == 0) {
+ if (strcasecmp(resources[i].name, lc->str) == 0) {
state = p_resource;
items = resources[i].items;
res_type = resources[i].rcode;
if (level != 1) {
scan_err1(lc, "not in resource definition: %s", lc->str);
}
- lcase(lc->str);
for (i=0; items[i].name; i++) {
- if (strcmp(items[i].name, lc->str) == 0) {
+ if (strcasecmp(items[i].name, lc->str) == 0) {
token = lex_get_token(lc);
Dmsg1 (150, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
if (token != T_EQUALS) {
}
already_dead = sig;
if (sig == SIGTERM) {
- Emsg1(M_INFO, -1, "Shutting down Bacula service: %s ...\n", my_name);
+ Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
} else {
Emsg2(M_FATAL, -1, "Interrupted by signal %d: %s\n", sig, sig_names[sig]);
}
#
SVRSRCS = stored.c append.c askdir.c authenticate.c block.c dev.c \
device.c dircmd.c fd_cmds.c fdmsg.c job.c \
- label.c read.c record.c stored_conf.c
+ label.c match_bsr.c parse_bsr.c \
+ read.c record.c stored_conf.c
SVROBJS = stored.o append.o askdir.o authenticate.o block.o dev.o \
device.o dircmd.o fd_cmds.o fdmsg.o job.o \
- label.o read.o record.o stored_conf.o
+ label.o match_bsr.o parse_bsr.o \
+ read.o record.o stored_conf.o
# bpool is depricated
#POOLSRCS = bpool.c block.c dev.c device.c askdir.c label.c \
BLSOBJS = bls.o block.o device.o dev.o askdir.o label.o record.o
-BEXTOBJS = bextract.o block.o device.o dev.o askdir.o label.o record.o
+BEXTOBJS = bextract.o block.o device.o dev.o askdir.o label.o record.o \
+ match_bsr.o parse_bsr.o
SCNOBJS = bscan.o block.o device.o dev.o askdir.o label.o record.o
#include "stored.h"
#include "findlib/find.h"
+
static void do_extract(char *fname, char *prefix);
-static void print_ls_output(char *fname, struct stat *statp);
+static void print_ls_output(char *fname, char *link, int type, struct stat *statp);
static DEVICE *dev = NULL;
static FF_PKT my_ff;
static FF_PKT *ff = &my_ff;
+static BSR *bsr = NULL;
+static SESSION_LABEL sesrec;
+
static void usage()
{
fprintf(stderr,
"Usage: bextract [-d debug_level] <bacula-archive> <directory-to-store-files>\n"
+" -b <file> specify a bootstrap file\n"
" -dnn set debug level to nn\n"
" -e <file> exclude list\n"
" -i <file> include list\n"
memset(ff, 0, sizeof(FF_PKT));
init_include_exclude_files(ff);
- while ((ch = getopt(argc, argv, "d:e:i:?")) != -1) {
+ while ((ch = getopt(argc, argv, "b:d:e:i:?")) != -1) {
switch (ch) {
+ case 'b': /* bootstrap file */
+ bsr = parse_bsr(optarg);
+ dump_bsr(bsr);
+ break;
+
case 'd': /* debug level */
debug_level = atoi(optarg);
if (debug_level <= 0)
do_extract(argv[0], argv[1]);
free_jcr(jcr);
+ if (bsr) {
+ free_bsr(bsr);
+ }
return 0;
}
POOLMEM *compress_buf = get_memory(compress_buf_size);
for ( ;; ) {
+ int ok;
if (!read_record(dev, block, &rec)) {
uint32_t status;
break;
case VOL_LABEL:
rtype = "Volume Label";
+ unser_volume_label(dev, &rec);
break;
case SOS_LABEL:
rtype = "Begin Session";
+ unser_session_label(&sesrec, &rec);
break;
case EOS_LABEL:
rtype = "End Session";
}
/* Is this the file we want? */
- if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
+ if (bsr) {
+ ok = match_bsr(bsr, &rec, &dev->VolHdr, &sesrec);
+ } else {
+ ok = TRUE;
+ }
+
+ if (ok && file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
decode_stat(ap, &statp);
/*
extract = create_file(jcr, fname, ofile, lname, type, &statp, &ofd);
if (extract) {
- print_ls_output(ofile, &statp);
+ print_ls_output(ofile, lname, type, &statp);
}
}
extern char *getuser(uid_t uid);
extern char *getgroup(gid_t gid);
-static void print_ls_output(char *fname, struct stat *statp)
+static void print_ls_output(char *fname, char *link, int type, struct stat *statp)
{
char buf[1000];
+ char ec1[30];
char *p, *f;
int n;
p += n;
n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
p += n;
- n = sprintf(p, "%8lld ", (uint64_t)statp->st_size);
+ n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
p += n;
p = encode_time(statp->st_ctime, p);
*p++ = ' ';
*p++ = ' ';
- for (f=fname; *f; )
+ /* Copy file name */
+ for (f=fname; *f && (p-buf) < (int)sizeof(buf); )
*p++ = *f++;
+ if (type == FT_LNK) {
+ *p++ = ' ';
+ *p++ = '-';
+ *p++ = '>';
+ *p++ = ' ';
+ /* Copy link name */
+ for (f=link; *f && (p-buf) < (int)sizeof(buf); )
+ *p++ = *f++;
+ }
*p++ = '\n';
*p = 0;
fputs(buf, stdout);
block->BlockNumber = dev->block_num;
ser_block_header(block);
- /* dump_block(block, "after ser_hdr"); */
+ /* Limit maximum Volume size to value specified by user */
if ((dev->max_volume_size > 0) &&
((int64_t) (dev->VolCatInfo.VolCatBytes + block->binbuf)) >= dev->max_volume_size) {
dev->state |= ST_WEOT;
}
dev->VolCatInfo.VolCatBytes += block->binbuf;
dev->VolCatInfo.VolCatBlocks++;
+ dev->file_bytes += block->binbuf;
+
+ /* Limit maximum File size on volume to user specified value */
+ if ((dev->max_file_size > 0) &&
+ dev->file_bytes >= dev->max_file_size) {
+ weof_dev, 1); /* write end of file */
+ }
+
Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
wlen);
empty_block(block);
static void print_ls_output(char *fname, char *link, int type, struct stat *statp)
{
char buf[1000];
+ char ec1[30];
char *p, *f;
int n;
p += n;
n = sprintf(p, "%-8.8s %-8.8s", getuser(statp->st_uid), getgroup(statp->st_gid));
p += n;
- n = sprintf(p, "%8" lld " ", (uint64_t)statp->st_size);
+ n = sprintf(p, "%8.8s ", edit_uint64(statp->st_size, ec1));
p += n;
p = encode_time(statp->st_ctime, p);
*p++ = ' ';
*p++ = ' ';
/* Copy file name */
- for (f=fname; *f; )
+ for (f=fname; *f && (p-buf) < (int)sizeof(buf); )
*p++ = *f++;
- if (type == FT_DIR) {
- *p++ = '/';
- }
if (type == FT_LNK) {
*p++ = ' ';
*p++ = '-';
*p++ = '>';
*p++ = ' ';
/* Copy link name */
- for (f=link; *f; )
+ for (f=link; *f && (p-buf) < (int)sizeof(buf); )
*p++ = *f++;
}
*p++ = '\n';
--- /dev/null
+/*
+ * BootStrap record definition -- for restoring files.
+ *
+ * Kern Sibbald, June 2002
+ *
+ * Version $Id$
+ *
+ */
+/*
+ Copyright (C) 2000, 2001, 2002 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.
+
+ */
+
+
+#ifndef __BSR_H
+#define __BSR_H 1
+
+#include "findlib/find.h"
+
+/*
+ * !!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * !!! !!!
+ * !!! All records must have a pointer to !!!
+ * !!! the next item as the first item defined. !!!
+ * !!! !!!
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+typedef struct s_bsr_client {
+ struct s_bsr_client *next;
+ char *ClientName;
+} BSR_CLIENT;
+
+typedef struct s_bsr_sessid {
+ struct s_bsr_sessid *next;
+ int type;
+ uint32_t sessid1;
+ uint32_t sessid2;
+ int found;
+} BSR_SESSID;
+
+typedef struct s_bsr_sesstime {
+ struct s_bsr_sesstime *next;
+ uint32_t sesstime;
+ int found;
+} BSR_SESSTIME;
+
+typedef struct s_bsr_findex {
+ struct s_bsr_findex *next;
+ int32_t FileIndex;
+ int found;
+} BSR_FINDEX;
+
+typedef struct s_bsr_jobid {
+ struct s_bsr_jobid *next;
+ uint32_t JobId;
+ int found;
+} BSR_JOBID;
+
+typedef struct s_bsr_jobtype {
+ struct s_bsr_jobtype *next;
+ uint32_t JobType;
+} BSR_JOBTYPE;
+
+typedef struct s_bsr_joblevel {
+ struct s_bsr_joblevel *next;
+ uint32_t JobLevel;
+} BSR_JOBLEVEL;
+
+typedef struct s_bsr_job {
+ struct s_bsr_job *next;
+ char *Job;
+ int found;
+} BSR_JOB;
+
+
+typedef struct s_bsr {
+ struct s_bsr *next; /* pointer to next one */
+ int done; /* set when everything found */
+ char *VolumeName;
+ BSR_CLIENT *client;
+ BSR_JOB *job;
+ BSR_SESSID *sessid;
+ BSR_SESSTIME *sesstime;
+ BSR_FINDEX *FileIndex;
+ BSR_JOBID *JobId;
+ BSR_JOBTYPE *JobType;
+ BSR_JOBLEVEL *JobLevel;
+ FF_PKT *ff; /* include/exclude */
+} BSR;
+
+
+#endif
}
dev->state &= ~(ST_APPEND|ST_READ|ST_EOT | ST_EOF | ST_WEOT); /* remove EOF/EOT flags */
dev->block_num = dev->file = 0;
+ dev->file_bytes = 0;
if (dev->state & ST_TAPE) {
mt_com.mt_op = MTREW;
mt_com.mt_count = 1;
}
dev->state &= ~(ST_EOF); /* remove EOF flags */
dev->block_num = dev->file = 0;
+ dev->file_bytes = 0;
if (!(dev->state & ST_TAPE)) {
pos = lseek(dev->fd, 0, SEEK_END);
if (pos > 0) {
/* Find out where we are */
if (!(dev->state & ST_TAPE)) {
dev->file = 0;
+ dev->file_bytes - 0;
pos = lseek(dev->fd, 0, SEEK_CUR);
if (pos < 0) {
Dmsg1(200, "Seek error: ERR=%s\n", strerror(dev->dev_errno));
#else
dev->block_num = dev->file = 0;
+ dev->file_bytes = 0;
mt_com.mt_op = MTLOAD;
mt_com.mt_count = 1;
if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
}
dev->block_num = dev->file = 0;
+ dev->file_bytes = 0;
mt_com.mt_op = MTOFFL;
mt_com.mt_count = 1;
if (ioctl(dev->fd, MTIOCTOP, (char *)&mt_com) < 0) {
} else {
dev->state |= ST_EOF;
dev->file++;
+ dev->file_bytes = 0;
continue;
}
} else { /* Got data */
} else {
dev->state |= ST_EOF; /* just read EOF */
dev->file++;
+ dev->file_bytes = 0;
}
}
Dmsg0(29, "bsf_dev\n");
dev->state &= ~(ST_EOT|ST_EOF);
dev->file -= num;
+ dev->file_bytes = 0;
mt_com.mt_op = MTBSF;
mt_com.mt_count = num;
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
} else {
dev->state |= ST_EOF; /* assume EOF */
dev->file++;
+ dev->file_bytes = 0;
}
clrerror_dev(dev, MTFSR);
Mmsg2(&dev->errmsg, _("ioctl MTFSR error on %s. ERR=%s.\n"),
stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
if (stat == 0) {
dev->file++;
+ dev->file_bytes = 0;
} else {
clrerror_dev(dev, MTWEOF);
Mmsg2(&dev->errmsg, _("ioctl MTWEOF error on %s. ERR=%s.\n"),
dev->state &= ~(ST_OPENED|ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
dev->block_num = 0;
dev->file = 0;
+ dev->file_bytes = 0;
dev->LastBlockNumWritten = 0;
memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
#define READ_ONLY 1
/* Generic status bits returned from status_dev() */
-#define MT_TAPE (1<<0) /* is tape device */
-#define MT_EOF (1<<1) /* just read EOF */
-#define MT_BOT (1<<2) /* at beginning of tape */
-#define MT_EOT (1<<3) /* end of tape reached */
-#define MT_SM (1<<4) /* DDS setmark */
-#define MT_EOD (1<<5) /* DDS at end of data */
-#define MT_WR_PROT (1<<6) /* tape write protected */
-#define MT_ONLINE (1<<7) /* tape online */
-#define MT_DR_OPEN (1<<8) /* tape door open */
-#define MT_IM_REP_EN (1<<9) /* immediate report enabled */
+#define MT_TAPE (1<<0) /* is tape device */
+#define MT_EOF (1<<1) /* just read EOF */
+#define MT_BOT (1<<2) /* at beginning of tape */
+#define MT_EOT (1<<3) /* end of tape reached */
+#define MT_SM (1<<4) /* DDS setmark */
+#define MT_EOD (1<<5) /* DDS at end of data */
+#define MT_WR_PROT (1<<6) /* tape write protected */
+#define MT_ONLINE (1<<7) /* tape online */
+#define MT_DR_OPEN (1<<8) /* tape door open */
+#define MT_IM_REP_EN (1<<9) /* immediate report enabled */
/* Bits for device capabilities */
-#define CAP_EOF 0x001 /* has MTWEOF */
-#define CAP_BSR 0x002 /* has MTBSR */
-#define CAP_BSF 0x004 /* has MTBSF */
-#define CAP_FSR 0x008 /* has MTFSR */
-#define CAP_FSF 0x010 /* has MTFSF */
-#define CAP_EOM 0x020 /* has MTEOM */
-#define CAP_REM 0x040 /* is removable media */
-#define CAP_RACCESS 0x080 /* is random access device */
-#define CAP_AUTOMOUNT 0x100 /* Read device at start to see what is there */
-#define CAP_LABEL 0x200 /* Label blank tapes */
-#define CAP_ANONVOLS 0x400 /* Mount without knowing volume name */
-#define CAP_ALWAYSOPEN 0x800 /* always keep device open */
+#define CAP_EOF 0x001 /* has MTWEOF */
+#define CAP_BSR 0x002 /* has MTBSR */
+#define CAP_BSF 0x004 /* has MTBSF */
+#define CAP_FSR 0x008 /* has MTFSR */
+#define CAP_FSF 0x010 /* has MTFSF */
+#define CAP_EOM 0x020 /* has MTEOM */
+#define CAP_REM 0x040 /* is removable media */
+#define CAP_RACCESS 0x080 /* is random access device */
+#define CAP_AUTOMOUNT 0x100 /* Read device at start to see what is there */
+#define CAP_LABEL 0x200 /* Label blank tapes */
+#define CAP_ANONVOLS 0x400 /* Mount without knowing volume name */
+#define CAP_ALWAYSOPEN 0x800 /* always keep device open */
/* Tape state bits */
-#define ST_OPENED 0x001 /* set when device opened */
-#define ST_TAPE 0x002 /* is a tape device */
-#define ST_LABEL 0x004 /* label found */
+#define ST_OPENED 0x001 /* set when device opened */
+#define ST_TAPE 0x002 /* is a tape device */
+#define ST_LABEL 0x004 /* label found */
#define ST_MALLOC 0x008 /* dev packet malloc'ed in init_dev() */
-#define ST_APPEND 0x010 /* ready for Bacula append */
-#define ST_READ 0x020 /* ready for Bacula read */
-#define ST_EOT 0x040 /* at end of tape */
-#define ST_WEOT 0x080 /* Got EOT on write */
-#define ST_EOF 0x100 /* Read EOF i.e. zero bytes */
-#define ST_NEXTVOL 0x200 /* Start writing on next volume */
-#define ST_SHORT 0x400 /* Short block read */
+#define ST_APPEND 0x010 /* ready for Bacula append */
+#define ST_READ 0x020 /* ready for Bacula read */
+#define ST_EOT 0x040 /* at end of tape */
+#define ST_WEOT 0x080 /* Got EOT on write */
+#define ST_EOF 0x100 /* Read EOF i.e. zero bytes */
+#define ST_NEXTVOL 0x200 /* Start writing on next volume */
+#define ST_SHORT 0x400 /* Short block read */
/* dev_blocked states (mutually exclusive) */
#define BST_NOT_BLOCKED 0 /* not blocked */
-#define BST_UNMOUNTED 1 /* User unmounted device */
+#define BST_UNMOUNTED 1 /* User unmounted device */
#define BST_WAITING_FOR_SYSOP 2 /* Waiting for operator to mount tape */
#define BST_DOING_ACQUIRE 3 /* Opening/validating/moving tape */
#define BST_WRITING_LABEL 4 /* Labeling a tape */
/* Volume Catalog Information structure definition */
typedef struct s_volume_catalog_info {
/* Media info for the current Volume */
- uint32_t VolCatJobs; /* number of jobs on this Volume */
- uint32_t VolCatFiles; /* Number of files */
- uint32_t VolCatBlocks; /* Number of blocks */
- uint64_t VolCatBytes; /* Number of bytes written */
- uint32_t VolCatMounts; /* Number of mounts this volume */
- uint32_t VolCatErrors; /* Number of errors this volume */
- uint32_t VolCatWrites; /* Number of writes this volume */
- uint32_t VolCatReads; /* Number of reads this volume */
- uint32_t VolCatRecycles; /* Number of recycles this volume */
- uint64_t VolCatMaxBytes; /* max bytes to write */
+ uint32_t VolCatJobs; /* number of jobs on this Volume */
+ uint32_t VolCatFiles; /* Number of files */
+ uint32_t VolCatBlocks; /* Number of blocks */
+ uint64_t VolCatBytes; /* Number of bytes written */
+ uint32_t VolCatMounts; /* Number of mounts this volume */
+ uint32_t VolCatErrors; /* Number of errors this volume */
+ uint32_t VolCatWrites; /* Number of writes this volume */
+ uint32_t VolCatReads; /* Number of reads this volume */
+ uint32_t VolCatRecycles; /* Number of recycles this volume */
+ uint64_t VolCatMaxBytes; /* max bytes to write */
uint64_t VolCatCapacityBytes; /* capacity estimate */
- char VolCatStatus[20]; /* Volume status */
+ char VolCatStatus[20]; /* Volume status */
char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */
} VOLUME_CAT_INFO;
/* Device structure definition */
typedef struct s_device {
- struct s_device *next; /* pointer to next open device */
- pthread_mutex_t mutex; /* access control */
- pthread_cond_t wait; /* thread wait variable */
+ struct s_device *next; /* pointer to next open device */
+ pthread_mutex_t mutex; /* access control */
+ pthread_cond_t wait; /* thread wait variable */
pthread_cond_t wait_next_vol; /* wait for tape to be mounted */
- pthread_t no_wait_id; /* this thread must not wait */
- int dev_blocked; /* set if we must wait (i.e. change tape) */
- int num_waiting; /* number of threads waiting */
- int num_writers; /* number of writing threads */
- int use_count; /* usage count on this device */
- int fd; /* file descriptor */
- int capabilities; /* capabilities mask */
- int state; /* state mask */
- int dev_errno; /* Our own errno */
- int mode; /* read/write modes */
- char *dev_name; /* device name */
- char *errmsg; /* nicely edited error message */
- uint32_t block_num; /* current block number base 0 */
- uint32_t file; /* current file number base 0 */
+ pthread_t no_wait_id; /* this thread must not wait */
+ int dev_blocked; /* set if we must wait (i.e. change tape) */
+ int num_waiting; /* number of threads waiting */
+ int num_writers; /* number of writing threads */
+ int use_count; /* usage count on this device */
+ int fd; /* file descriptor */
+ int capabilities; /* capabilities mask */
+ int state; /* state mask */
+ int dev_errno; /* Our own errno */
+ int mode; /* read/write modes */
+ char *dev_name; /* device name */
+ char *errmsg; /* nicely edited error message */
+ uint32_t block_num; /* current block number base 0 */
+ uint32_t file; /* current file number base 0 */
+ uint32_t file_bytes; /* bytes in this file */
uint32_t LastBlockNumWritten; /* last block written */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
- int64_t max_volume_files; /* max files to put on one volume */
- int64_t max_volume_size; /* max bytes to put on one volume */
- int64_t max_file_size; /* max file size in bytes */
- int64_t volume_capacity; /* advisory capacity */
- uint32_t max_rewind_wait; /* max secs to allow for rewind */
- void *device; /* pointer to Device Resource */
-
- VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
- struct Volume_Label VolHdr; /* Actual volume label */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ uint64_t max_volume_files; /* max files to put on one volume */
+ uint64_t max_volume_size; /* max bytes to put on one volume */
+ uint64_t max_file_size; /* max file size to put in one file on volume */
+ uint64_t volume_capacity; /* advisory capacity */
+ uint32_t max_rewind_wait; /* max secs to allow for rewind */
+ void *device; /* pointer to Device Resource */
+
+ VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
+ VOLUME_LABEL VolHdr; /* Actual volume label */
} DEVICE;
* dependent. Arrgggg!
*/
#ifndef MTEOM
-#ifdef MTSEOD
+#ifdef MTSEOD
#define MTEOM MTSEOD
#endif
#ifdef MTEOD
strcpy(dev->VolCatInfo.VolCatStatus, "Full");
Dmsg0(90, "Call update_vol_info\n");
+ /* Update position counters */
+ jcr->end_block = dev->block_num;
+ jcr->end_file = dev->file;
if (!dir_update_volume_info(jcr, &dev->VolCatInfo, 0)) { /* send Volume info to Director */
Jmsg(jcr, M_ERROR, 0, _("Could not update Volume info Volume=%s Job=%s\n"),
dev->VolCatInfo.VolCatName, jcr->Job);
jcr->NumVolumes++;
Dmsg0(90, "Wake up any waiting threads.\n");
free_block(label_blk);
+ /* Set new start/end positions */
+ jcr->start_block = dev->block_num;
+ jcr->start_file = dev->file;
unblock_device(dev);
jcr->run_time += time(NULL) - wait_time; /* correct run time */
return 1; /* device locked */
--- /dev/null
+/*
+ * Match Bootstrap Records (used for restores) against
+ * Volume Records
+ *
+ * Kern Sibbald, June MMII
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2002 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 references */
+static int match_sesstime(BSR_SESSTIME *sesstime, DEV_RECORD *rec);
+static int match_sessid(BSR_SESSID *sessid, DEV_RECORD *rec);
+static int match_client(BSR_CLIENT *client, SESSION_LABEL *sesrec);
+static int match_job(BSR_JOB *job, SESSION_LABEL *sesrec);
+static int match_job_type(BSR_JOBTYPE *job_type, SESSION_LABEL *sesrec);
+static int match_job_level(BSR_JOBLEVEL *job_level, SESSION_LABEL *sesrec);
+static int match_jobid(BSR_JOBID *jobid, SESSION_LABEL *sesrec);
+static int match_file_index(BSR_FINDEX *findex, DEV_RECORD *rec);
+static int match_one_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sesrec);
+
+/*********************************************************************
+ *
+ * Match Bootstrap records
+ *
+ */
+int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sesrec)
+{
+ if (!bsr) {
+ return 0;
+ }
+ if (match_one_bsr(bsr, rec, volrec, sesrec)) {
+ return 1;
+ }
+ return match_bsr(bsr->next, rec, volrec, sesrec);
+}
+
+static int match_one_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sesrec)
+{
+ if (strcmp(bsr->VolumeName, volrec->VolName) != 0) {
+ return 0;
+ }
+ if (!match_client(bsr->client, sesrec)) {
+ return 0;
+ }
+ if (!match_sessid(bsr->sessid, rec)) {
+ return 0;
+ }
+ if (!match_sesstime(bsr->sesstime, rec)) {
+ return 0;
+ }
+ if (!match_job(bsr->job, sesrec)) {
+ return 0;
+ }
+ if (!match_file_index(bsr->FileIndex, rec)) {
+ return 0;
+ }
+ if (!match_job_type(bsr->JobType, sesrec)) {
+ return 0;
+ }
+ if (!match_job_level(bsr->JobLevel, sesrec)) {
+ return 0;
+ }
+ if (!match_jobid(bsr->JobId, sesrec)) {
+ return 0;
+ }
+ return 1;
+}
+
+static int match_client(BSR_CLIENT *client, SESSION_LABEL *sesrec)
+{
+ if (!client) {
+ return 1; /* no specification matches all */
+ }
+ if (strcmp(client->ClientName, sesrec->ClientName) == 0) {
+ return 1;
+ }
+ if (client->next) {
+ return match_client(client->next, sesrec);
+ }
+ return 0;
+}
+
+static int match_job(BSR_JOB *job, SESSION_LABEL *sesrec)
+{
+ if (!job) {
+ return 1; /* no specification matches all */
+ }
+ if (strcmp(job->Job, sesrec->Job) == 0) {
+ job->found++;
+ return 1;
+ }
+ if (job->next) {
+ return match_job(job->next, sesrec);
+ }
+ return 0;
+}
+
+
+static int match_job_type(BSR_JOBTYPE *job_type, SESSION_LABEL *sesrec)
+{
+ if (!job_type) {
+ return 1; /* no specification matches all */
+ }
+ if (job_type->JobType == sesrec->JobType) {
+ return 1;
+ }
+ if (job_type->next) {
+ return match_job_type(job_type->next, sesrec);
+ }
+ return 0;
+}
+
+static int match_job_level(BSR_JOBLEVEL *job_level, SESSION_LABEL *sesrec)
+{
+ if (!job_level) {
+ return 1; /* no specification matches all */
+ }
+ if (job_level->JobLevel == sesrec->JobLevel) {
+ return 1;
+ }
+ if (job_level->next) {
+ return match_job_level(job_level->next, sesrec);
+ }
+ return 0;
+}
+
+static int match_jobid(BSR_JOBID *jobid, SESSION_LABEL *sesrec)
+{
+ if (!jobid) {
+ return 1; /* no specification matches all */
+ }
+ if (jobid->JobId == sesrec->JobId) {
+ jobid->found++;
+ return 1;
+ }
+ if (jobid->next) {
+ return match_jobid(jobid->next, sesrec);
+ }
+ return 0;
+}
+
+
+static int match_file_index(BSR_FINDEX *findex, DEV_RECORD *rec)
+{
+ if (!findex) {
+ return 1; /* no specification matches all */
+ }
+ if (findex->FileIndex == rec->FileIndex) {
+ findex->found++;
+ return 1;
+ }
+ if (findex->next) {
+ return match_file_index(findex->next, rec);
+ }
+ return 0;
+}
+
+
+static int match_sessid(BSR_SESSID *sessid, DEV_RECORD *rec)
+{
+ if (!sessid) {
+ return 1; /* no specification matches all */
+ }
+ if (sessid->sessid1 == rec->VolSessionId) {
+ sessid->found++;
+ return 1;
+ }
+ if (sessid->next) {
+ return match_sessid(sessid->next, rec);
+ }
+ return 0;
+}
+
+static int match_sesstime(BSR_SESSTIME *sesstime, DEV_RECORD *rec)
+{
+ if (!sesstime) {
+ return 1; /* no specification matches all */
+ }
+ if (sesstime->sesstime == rec->VolSessionTime) {
+ sesstime->found++;
+ return 1;
+ }
+ if (sesstime->next) {
+ return match_sesstime(sesstime->next, rec);
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * Parse a Bootstrap Records (used for restores)
+ *
+ * Kern Sibbald, June MMII
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2002 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"
+
+typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
+
+static BSR *store_vol(LEX *lc, BSR *bsr);
+static BSR *store_client(LEX *lc, BSR *bsr);
+static BSR *store_job(LEX *lc, BSR *bsr);
+static BSR *store_jobid(LEX *lc, BSR *bsr);
+static BSR *store_jobtype(LEX *lc, BSR *bsr);
+static BSR *store_joblevel(LEX *lc, BSR *bsr);
+static BSR *store_file_index(LEX *lc, BSR *bsr);
+static BSR *store_sessid(LEX *lc, BSR *bsr);
+static BSR *store_sesstime(LEX *lc, BSR *bsr);
+static BSR *store_include(LEX *lc, BSR *bsr);
+static BSR *store_exclude(LEX *lc, BSR *bsr);
+
+struct kw_items {
+ char *name;
+ ITEM_HANDLER *handler;
+};
+
+struct kw_items items[] = {
+ {"volume", store_vol},
+ {"client", store_client},
+ {"job", store_job},
+ {"jobid", store_jobid},
+ {"fileindex", store_file_index},
+ {"jobtype", store_jobtype},
+ {"joblevel", store_joblevel},
+ {"volsessionid", store_sessid},
+ {"volsessiontime", store_sesstime},
+ {"include", store_include},
+ {"exclude", store_exclude},
+ {NULL, NULL}
+
+};
+
+static BSR *new_bsr()
+{
+ BSR *bsr = (BSR *)malloc(sizeof(BSR));
+ memset(bsr, 0, sizeof(BSR));
+ return bsr;
+}
+
+/*********************************************************************
+ *
+ * Parse Bootstrap file
+ *
+ */
+BSR *parse_bsr(char *cf)
+{
+ LEX *lc = NULL;
+ int token, i;
+ BSR *root_bsr = new_bsr();
+ BSR *bsr = root_bsr;
+
+ Dmsg0(200, "Enter parse_bsf()\n");
+ lc = lex_open_file(lc, cf);
+ while ((token=lex_get_token(lc)) != T_EOF) {
+ Dmsg1(150, "parse got token=%s\n", lex_tok_to_str(token));
+ if (token == T_EOL) {
+ continue;
+ }
+ if (token != T_IDENTIFIER) {
+ scan_err1(lc, "Expected a keyword identifier, got: %s", lc->str);
+ }
+ for (i=0; items[i].name; i++) {
+ if (strcasecmp(items[i].name, lc->str) == 0) {
+ token = lex_get_token(lc);
+ Dmsg1 (150, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
+ if (token != T_EQUALS) {
+ scan_err1(lc, "expected an equals, got: %s", lc->str);
+ }
+ Dmsg1(150, "calling handler for %s\n", items[i].name);
+ /* Call item handler */
+ bsr = items[i].handler(lc, bsr);
+ i = -1;
+ break;
+ }
+ }
+ if (i >= 0) {
+ Dmsg1(150, "Keyword = %s\n", lc->str);
+ scan_err1(lc, "Keyword %s not found", lc->str);
+ }
+
+ }
+ lc = lex_close_file(lc);
+ Dmsg0(200, "Leave parse_bsf()\n");
+ return root_bsr;
+}
+
+static BSR *store_vol(LEX *lc, BSR *bsr)
+{
+ int token;
+
+ token = lex_get_token(lc);
+ if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
+ scan_err1(lc, "expected an identifier or string, got: %s", lc->str);
+ } else if (lc->str_len > MAX_RES_NAME_LENGTH) {
+ scan_err3(lc, "name %s length %d too long, max is %d\n", lc->str,
+ lc->str_len, MAX_RES_NAME_LENGTH);
+ } else {
+ if (bsr->VolumeName) {
+ bsr->next = new_bsr();
+ bsr = bsr->next;
+ }
+ bsr->VolumeName = bstrdup(lc->str);
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_client(LEX *lc, BSR *bsr)
+{
+ int token;
+ BSR_CLIENT *client;
+
+ token = lex_get_token(lc);
+ if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
+ scan_err1(lc, "expected an identifier or string, got: %s", lc->str);
+ } else if (lc->str_len > MAX_RES_NAME_LENGTH) {
+ scan_err3(lc, "name %s length %d too long, max is %d\n", lc->str,
+ lc->str_len, MAX_RES_NAME_LENGTH);
+ } else {
+ client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
+ memset(client, 0, sizeof(BSR_CLIENT));
+ client->ClientName = bstrdup(lc->str);
+ /* Add it to the end of the client chain */
+ if (!bsr->client) {
+ bsr->client = client;
+ } else {
+ BSR_CLIENT *bc = bsr->client;
+ for ( ;; ) {
+ if (bc->next) {
+ bc = bc->next;
+ } else {
+ bc->next = client;
+ break;
+ }
+ }
+ }
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_job(LEX *lc, BSR *bsr)
+{
+ int token;
+ BSR_JOB *job;
+
+ token = lex_get_token(lc);
+ if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
+ scan_err1(lc, "expected an identifier or string, got: %s", lc->str);
+ } else if (lc->str_len > MAX_RES_NAME_LENGTH) {
+ scan_err3(lc, "name %s length %d too long, max is %d\n", lc->str,
+ lc->str_len, MAX_RES_NAME_LENGTH);
+ } else {
+ job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
+ memset(job, 0, sizeof(BSR_JOB));
+ job->Job = bstrdup(lc->str);
+ /* Add it to the end of the client chain */
+ if (!bsr->job) {
+ bsr->job = job;
+ } else {
+ /* Add to end of chain */
+ BSR_JOB *bc = bsr->job;
+ for ( ;bc->next; bc=bc->next)
+ { }
+ bc->next = job;
+ }
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_file_index(LEX *lc, BSR *bsr)
+{
+ int token;
+ int32_t FileIndex;
+ BSR_FINDEX *findex;
+
+
+ token = lex_get_token(lc);
+ if (token != T_NUMBER || !is_a_number(lc->str)) {
+ scan_err1(lc, "expected a positive integer number, got: %s", lc->str);
+ } else {
+ errno = 0;
+ FileIndex = strtoul(lc->str, NULL, 10);
+ if (errno != 0) {
+ scan_err1(lc, "expected a integer number, got: %s", lc->str);
+ }
+ findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
+ memset(findex, 0, sizeof(BSR_FINDEX));
+ findex->FileIndex = FileIndex;
+ /* Add it to the end of the chain */
+ if (!bsr->FileIndex) {
+ bsr->FileIndex = findex;
+ } else {
+ /* Add to end of chain */
+ BSR_FINDEX *bs = bsr->FileIndex;
+ for ( ;bs->next; bs=bs->next)
+ { }
+ bs->next = findex;
+ }
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+
+static BSR *store_jobid(LEX *lc, BSR *bsr)
+{
+ int token;
+ uint32_t JobId;
+ BSR_JOBID *jobid;
+
+
+ token = lex_get_token(lc);
+ if (token != T_NUMBER || !is_a_number(lc->str)) {
+ scan_err1(lc, "expected a positive integer number, got: %s", lc->str);
+ } else {
+ errno = 0;
+ JobId = strtoul(lc->str, NULL, 10);
+ if (errno != 0) {
+ scan_err1(lc, "expected a integer number, got: %s", lc->str);
+ }
+ jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
+ memset(jobid, 0, sizeof(BSR_JOBID));
+ jobid->JobId = JobId;
+ /* Add it to the end of the chain */
+ if (!bsr->JobId) {
+ bsr->JobId = jobid;
+ } else {
+ /* Add to end of chain */
+ BSR_JOBID *bs = bsr->JobId;
+ for ( ;bs->next; bs=bs->next)
+ { }
+ bs->next = jobid;
+ }
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_jobtype(LEX *lc, BSR *bsr)
+{
+ /* *****FIXME****** */
+ Dmsg0(-1, "JobType not yet implemented\n");
+ return bsr;
+}
+
+
+static BSR *store_joblevel(LEX *lc, BSR *bsr)
+{
+ /* *****FIXME****** */
+ Dmsg0(-1, "JobLevel not yet implemented\n");
+ return bsr;
+}
+
+
+
+static BSR *store_sessid(LEX *lc, BSR *bsr)
+{
+ int token;
+ uint32_t sessid1;
+ BSR_SESSID *sid;
+
+
+ token = lex_get_token(lc);
+ if (token != T_NUMBER || !is_a_number(lc->str)) {
+ scan_err1(lc, "expected a positive integer number, got: %s", lc->str);
+ } else {
+ errno = 0;
+ sessid1 = strtoul(lc->str, NULL, 10);
+ if (errno != 0) {
+ scan_err1(lc, "expected a integer number, got: %s", lc->str);
+ }
+ sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
+ memset(sid, 0, sizeof(BSR_SESSID));
+ sid->sessid1 = sessid1;
+ /* Add it to the end of the chain */
+ if (!bsr->sessid) {
+ bsr->sessid = sid;
+ } else {
+ /* Add to end of chain */
+ BSR_SESSID *bs = bsr->sessid;
+ for ( ;bs->next; bs=bs->next)
+ { }
+ bs->next = sid;
+ }
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_sesstime(LEX *lc, BSR *bsr)
+{
+ int token;
+ uint32_t sesstime;
+ BSR_SESSTIME *stime;
+
+
+ token = lex_get_token(lc);
+ if (token != T_NUMBER || !is_a_number(lc->str)) {
+ scan_err1(lc, "expected a positive integer number, got: %s", lc->str);
+ } else {
+ errno = 0;
+ sesstime = strtoul(lc->str, NULL, 10);
+ if (errno != 0) {
+ scan_err1(lc, "expected a integer number, got: %s", lc->str);
+ }
+ stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
+ memset(stime, 0, sizeof(BSR_SESSTIME));
+ stime->sesstime = sesstime;
+ /* Add it to the end of the chain */
+ if (!bsr->sesstime) {
+ bsr->sesstime = stime;
+ } else {
+ /* Add to end of chain */
+ BSR_SESSTIME *bs = bsr->sesstime;
+ for ( ;bs->next; bs=bs->next)
+ { }
+ bs->next = stime;
+ }
+ }
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_include(LEX *lc, BSR *bsr)
+{
+ scan_to_eol(lc);
+ return bsr;
+}
+
+static BSR *store_exclude(LEX *lc, BSR *bsr)
+{
+ scan_to_eol(lc);
+ return bsr;
+}
+
+void dump_bsr(BSR *bsr)
+{
+ if (!bsr) {
+ Dmsg0(-1, "BSR is NULL\n");
+ return;
+ }
+ Dmsg8(-1,
+"Next : 0x%x\n"
+"VolumeName : %s\n"
+"Client : %s\n"
+"Job : %s\n"
+"JobId : %u\n"
+"SessId : %u\n"
+"SessTime : %u\n"
+"FileIndex : %d\n",
+ bsr->next,
+ bsr->VolumeName ? bsr->VolumeName : "*None*",
+ bsr->client ? bsr->client->ClientName : "*None*",
+ bsr->job ? bsr->job->Job : "*None*",
+ bsr->JobId ? bsr->JobId->JobId : 0,
+ bsr->sessid ? bsr->sessid->sessid1 : 0,
+ bsr->sesstime ? bsr->sesstime->sesstime : 0,
+ bsr->FileIndex ? bsr->FileIndex->FileIndex : 0);
+ if (bsr->next) {
+ Dmsg0(-1, "\n");
+ dump_bsr(bsr->next);
+ }
+}
+
+
+/*********************************************************************
+ *
+ * Free bsr resources
+ */
+
+static void free_bsr_item(BSR *bsr)
+{
+ if (!bsr) {
+ return;
+ }
+ free_bsr_item(bsr->next);
+ free(bsr);
+}
+
+void free_bsr(BSR *bsr)
+{
+ if (!bsr) {
+ return;
+ }
+ free_bsr_item((BSR *)bsr->client);
+ free_bsr_item((BSR *)bsr->sessid);
+ free_bsr_item((BSR *)bsr->sesstime);
+ if (bsr->VolumeName) {
+ free(bsr->VolumeName);
+ }
+ free_bsr(bsr->next);
+ free(bsr);
+}
uint32_t new_VolSessionId();
/* From askdir.c */
-int dir_get_volume_info(JCR *jcr);
-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_get_volume_info(JCR *jcr);
+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);
/* 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(DEVICE *dev, DEV_BLOCK *block);
-int read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
-int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
+void init_block_write(DEV_BLOCK *block);
+void empty_block(DEV_BLOCK *block);
+void free_block(DEV_BLOCK *block);
+int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int write_block_to_dev(DEVICE *dev, DEV_BLOCK *block);
+int read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
+int read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
/* From dev.c */
-DEVICE *init_dev(DEVICE *dev, char *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);
+DEVICE *init_dev(DEVICE *dev, char *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);
/* 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 acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void block_device(DEVICE *dev, int state);
-void unblock_device(DEVICE *dev);
-void lock_device(DEVICE *dev);
-void unlock_device(DEVICE *dev);
-int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int open_device(DEVICE *dev);
+int acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void block_device(DEVICE *dev, int state);
+void unblock_device(DEVICE *dev);
+void lock_device(DEVICE *dev);
+void unlock_device(DEVICE *dev);
+int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
/* From dircmd.c */
-void connection_request(void *arg);
+void connection_request(void *arg);
/* From fd_cmds.c */
-void run_job(JCR *jcr);
+void run_job(JCR *jcr);
/* From fdmsg.c */
-int bget_msg(BSOCK *sock);
+int bget_msg(BSOCK *sock);
/* From job.c */
-void stored_free_jcr(JCR *jcr);
-void connection_from_filed(void *arg);
-void handle_filed_connection(BSOCK *fd, char *job_name);
+void stored_free_jcr(JCR *jcr);
+void connection_from_filed(void *arg);
+void handle_filed_connection(BSOCK *fd, char *job_name);
/* From label.c */
-int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
-int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
-int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void dump_volume_label(DEVICE *dev);
-void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-int unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-int unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
+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);
+
+/* From parse_bsr.c */
+extern BSR *parse_bsr(char *lf);
+extern void dump_bsr(BSR *bsr);
+extern void free_bsr(BSR *bsr);
/* From record.c */
char *FI_to_ascii(int fi);
char *stream_to_ascii(int stream);
-int 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 read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
DEV_RECORD *new_record();
-void free_record(DEV_RECORD *rec);
-int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
-int write_record_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
+void free_record(DEV_RECORD *rec);
+int read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
+int write_record_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
#include "dev.h"
#include "stored_conf.h"
#include "jcr.h"
+#include "bsr.h"
#include "protos.h"
#ifdef HAVE_LIBZ
#include <zlib.h> /* compression headers */
/* */
-#define VERSION "1.21"
+#define VERSION "1.22"
#define VSTRING "1"
-#define DATE "12 June 2002"
-#define LSMDATE "12Jun02"
+#define DATE "15 June 2002"
+#define LSMDATE "15Jun02"
/* Debug flags */
#define DEBUG 1