SVRSRCS = dird.c authenticate.c autoprune.c \
backup.c \
catreq.c dird_conf.c \
- fd_cmds.c getmsg.c job.c \
+ fd_cmds.c getmsg.c inc_conf.c job.c \
mountreq.c msgchan.c newvol.c \
recycle.c restore.c run_conf.c \
scheduler.c sql_cmds.c \
SVROBJS = dird.o authenticate.o autoprune.o \
backup.o \
catreq.o dird_conf.o \
- fd_cmds.o getmsg.o job.o \
+ fd_cmds.o getmsg.o inc_conf.o job.o \
mountreq.o msgchan.o newvol.o \
recycle.o restore.o run_conf.o \
scheduler.o sql_cmds.o \
/* Imported subroutines */
extern void store_run(LEX *lc, struct res_items *item, int index, int pass);
+extern void store_finc(LEX *lc, struct res_items *item, int index, int pass);
+extern void store_inc(LEX *lc, struct res_items *item, int index, int pass);
/* Forward referenced subroutines */
-static void store_inc(LEX *lc, struct res_items *item, int index, int pass);
-static void store_match(LEX *lc, struct res_items *item, int index, int pass);
static void store_backup(LEX *lc, struct res_items *item, int index, int pass);
static void store_restore(LEX *lc, struct res_items *item, int index, int pass);
static void store_jobtype(LEX *lc, struct res_items *item, int index, int pass);
static void store_level(LEX *lc, struct res_items *item, int index, int pass);
static void store_replace(LEX *lc, struct res_items *item, int index, int pass);
-static void store_opts(LEX *lc, struct res_items *item, int index, int pass);
/* We build the current resource here as we are
{"name", store_name, ITEM(res_fs.hdr.name), 0, ITEM_REQUIRED, 0},
{"description", store_str, ITEM(res_fs.hdr.desc), 0, 0, 0},
{"include", store_inc, NULL, 0, 0, 0},
+ {"finclude", store_finc, NULL, 0, ITEM_NO_EQUALS, 0},
{"exclude", store_inc, NULL, 1, 0, 0},
+ {"fexclude", store_finc, NULL, 1, ITEM_NO_EQUALS, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
};
-/*
- * FileOptions Resource
- * name handler value code flags default_value
- */
-static struct res_items fo_items[] = {
- {"name", store_name, ITEM(res_fopts.hdr.name), 0, ITEM_REQUIRED, 0},
- {"description", store_str, ITEM(res_fopts.hdr.desc), 0, 0, 0},
- {"compression", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"signature", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"verify", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"onefs", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"recurse", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"sparse", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"readfifo", store_opts, ITEM(res_fopts.opts), 0, 0, 0},
- {"replace", store_replace, ITEM(res_fopts.replace), 0, 0, 0},
- {"match", store_match, ITEM(res_fopts.match), 0, 0, 0},
- {NULL, NULL, NULL, 0, 0, 0}
-};
-
-
-
/* Message resource */
extern struct res_items msgs_items[];
{"pool", pool_items, R_POOL, NULL},
{"messages", msgs_items, R_MSGS, NULL},
{"counter", counter_items, R_COUNTER, NULL},
- {"fileoptions", fo_items, R_FILEOPTIONS, NULL},
{NULL, NULL, 0, NULL}
};
{NULL, 0}
};
-
-
-/* Define FileSet KeyWord values */
-
-#define INC_KW_NONE 0
-#define INC_KW_COMPRESSION 1
-#define INC_KW_SIGNATURE 2
-#define INC_KW_ENCRYPTION 3
-#define INC_KW_VERIFY 4
-#define INC_KW_ONEFS 5
-#define INC_KW_RECURSE 6
-#define INC_KW_SPARSE 7
-#define INC_KW_REPLACE 8 /* restore options */
-#define INC_KW_READFIFO 9 /* Causes fifo data to be read */
-#define INC_KW_FILEOPTIONS 10 /* file options */
-
-/* Include keywords -- these are keywords that can appear
- * in the options lists of an include ( Include = compression= ...)
- */
-static struct s_kw FS_option_kw[] = {
- {"compression", INC_KW_COMPRESSION},
- {"signature", INC_KW_SIGNATURE},
- {"encryption", INC_KW_ENCRYPTION},
- {"verify", INC_KW_VERIFY},
- {"onefs", INC_KW_ONEFS},
- {"recurse", INC_KW_RECURSE},
- {"sparse", INC_KW_SPARSE},
- {"replace", INC_KW_REPLACE},
- {"readfifo", INC_KW_READFIFO},
- {"fileoptions", INC_KW_FILEOPTIONS},
- {NULL, 0}
-};
-
-/* Options for FileSet keywords */
-
-struct s_fs_opt {
- char *name;
- int keyword;
- char *option;
-};
-
-/* Options permitted for each keyword and resulting value */
-static struct s_fs_opt FS_options[] = {
- {"md5", INC_KW_SIGNATURE, "M"},
- {"sha1", INC_KW_SIGNATURE, "S"},
- {"gzip", INC_KW_COMPRESSION, "Z6"},
- {"gzip1", INC_KW_COMPRESSION, "Z1"},
- {"gzip2", INC_KW_COMPRESSION, "Z2"},
- {"gzip3", INC_KW_COMPRESSION, "Z3"},
- {"gzip4", INC_KW_COMPRESSION, "Z4"},
- {"gzip5", INC_KW_COMPRESSION, "Z5"},
- {"gzip6", INC_KW_COMPRESSION, "Z6"},
- {"gzip7", INC_KW_COMPRESSION, "Z7"},
- {"gzip8", INC_KW_COMPRESSION, "Z8"},
- {"gzip9", INC_KW_COMPRESSION, "Z9"},
- {"blowfish", INC_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
- {"3des", INC_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
- {"yes", INC_KW_ONEFS, "0"},
- {"no", INC_KW_ONEFS, "f"},
- {"yes", INC_KW_RECURSE, "0"},
- {"no", INC_KW_RECURSE, "h"},
- {"yes", INC_KW_SPARSE, "s"},
- {"no", INC_KW_SPARSE, "0"},
- {"always", INC_KW_REPLACE, "a"},
- {"ifnewer", INC_KW_REPLACE, "w"},
- {"never", INC_KW_REPLACE, "n"},
- {"yes", INC_KW_READFIFO, "r"},
- {"no", INC_KW_READFIFO, "0"},
- {NULL, 0, 0}
-};
-
char *level_to_str(int level)
{
int i;
return str;
}
-
-
/* Dump contents of resource */
void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...), void *sock)
{
if (res->res_msgs.operator_cmd)
sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
break;
- case R_FILEOPTIONS:
- sendit(sock, "FileOptions: name=%s\n", res->res_msgs.hdr.name);
- sendit(sock, " opts=%s replace=%c\n", res->res_fopts.opts,
- res->res_fopts.replace);
- for (int i=0; i < res->res_fopts.num_match; i++) {
- sendit(sock, " match=%s\n", res->res_fopts.match[i]);
- }
- break;
default:
sendit(sock, "Unknown resource type %d in dump_resource.\n", type);
break;
if (incexe->name_list) {
free(incexe->name_list);
}
+ for (int i=0; i<incexe->num_match; i++) {
+ free(incexe->match_list[i]);
+ }
+ if (incexe->match_list) {
+ free(incexe->match_list);
+ }
free(incexe);
}
free(res->res_fs.include_items);
if (incexe->name_list) {
free(incexe->name_list);
}
+ for (int i=0; i<incexe->num_match; i++) {
+ free(incexe->match_list[i]);
+ }
+ if (incexe->match_list) {
+ free(incexe->match_list);
+ }
free(incexe);
}
free(res->res_fs.exclude_items);
free_msgs_res((MSGS *)res); /* free message resource */
res = NULL;
break;
- case R_FILEOPTIONS:
- if (res->res_fopts.num_match) {
- for (int i=0; i < res->res_fopts.num_match; i++) {
- free(res->res_fopts.match[i]);
- }
- free((char *)res->res_fopts.match);
- }
- break;
case R_GROUP:
break;
default:
/* Resources not containing a resource */
case R_CATALOG:
case R_STORAGE:
- case R_FILEOPTIONS:
case R_GROUP:
case R_POOL:
case R_MSGS:
- break;
-
- /* Special case for FileSet, all allocations are done
- * only in pass 2, so here we must copy the whole structure.
- * This is done so that we can have forward references to
- * FileOptions resources within the fileset
- */
case R_FILESET:
- RES res_save;
- if ((res = (URES *)GetResWithName(R_FILESET, res_all.res_dir.hdr.name)) == NULL) {
- Emsg1(M_ERROR_TERM, 0, "Cannot find FileSet resource %s\n", res_all.res_dir.hdr.name);
- }
- memcpy(&res_save, &res_all, sizeof(RES));
- memcpy(&res_all, res, sizeof(RES));
- memcpy(res, &res_all, sizeof(FILESET));
- memcpy(&res_all, &res_save, sizeof(RES));
break;
/* Resources containing another resource */
case R_COUNTER:
size = sizeof(COUNTER);
break;
- case R_FILEOPTIONS:
- size = sizeof(FILEOPTIONS);
- break;
default:
printf("Unknown resource type %d in save_resrouce.\n", type);
error = 1;
lc->options = options; /* reset original options */
set_bit(index, res_all.hdr.item_present);
}
-
-
-
-/*
- * Scan for Include options (keyword=option) is converted into one or
- * two characters. Verifyopts=xxxx is Vxxxx:
- */
-static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen)
-{
- int token, i;
- char option[3];
-
- option[0] = 0; /* default option = none */
- option[2] = 0; /* terminate options */
- token = lex_get_token(lc, T_NAME); /* expect at least one option */
- if (keyword == INC_KW_VERIFY) { /* special case */
- /* ***FIXME**** ensure these are in permitted set */
- bstrncat(opts, "V", optlen); /* indicate Verify */
- bstrncat(opts, lc->str, optlen);
- bstrncat(opts, ":", optlen); /* terminate it */
-
- /* Standard keyword -- these are now deprecated and should be specified
- * in the FileOptions resource
- */
- } else {
- for (i=0; FS_options[i].name; i++) {
- if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) {
- /* NOTE! maximum 2 letters here or increase option[3] */
- option[0] = FS_options[i].option[0];
- option[1] = FS_options[i].option[1];
- i = 0;
- break;
- }
- }
- if (i != 0) {
- scan_err1(lc, "Expected a FileSet option keyword, got:%s:", lc->str);
- } else { /* add option */
- bstrncat(opts, option, optlen);
- Dmsg3(200, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
- }
- }
-
- /* If option terminated by comma, eat it */
- if (lc->ch == ',') {
- token = lex_get_token(lc, T_ALL); /* yes, eat comma */
- }
-}
-
-/* Store FileSet Include/Exclude info */
-static void store_inc(LEX *lc, struct res_items *item, int index, int pass)
-{
- int token, i;
- int options = lc->options;
- int keyword;
- char inc_opts[100];
- int inc_opts_len;
- RES *res = NULL;
-
- lc->options |= LOPT_NO_IDENT; /* make spaces significant */
-
- /* Get include options */
- inc_opts[0] = 0;
- while ((token=lex_get_token(lc, T_ALL)) != T_BOB) {
- keyword = INC_KW_NONE;
- for (i=0; FS_option_kw[i].name; i++) {
- if (strcasecmp(lc->str, FS_option_kw[i].name) == 0) {
- keyword = FS_option_kw[i].token;
- break;
- }
- }
- if (keyword == INC_KW_NONE) {
- scan_err1(lc, _("Expected a FileSet keyword, got: %s"), lc->str);
- }
- /* Option keyword should be following by = <option> */
- if ((token=lex_get_token(lc, T_ALL)) != T_EQUALS) {
- scan_err1(lc, _("expected an = following keyword, got: %s"), lc->str);
- }
- if (keyword == INC_KW_FILEOPTIONS) {
- token = lex_get_token(lc, T_NAME);
- if (pass == 2) {
- res = GetResWithName(R_FILEOPTIONS, lc->str);
- if (res == NULL) {
- scan_err1(lc, _("Could not find specified FileOptions Resource: %s"), lc->str);
- }
- }
- } else {
- scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
- }
- if (token == T_BOB) {
- break;
- }
- }
- if (!inc_opts[0]) {
- strcat(inc_opts, "0"); /* set no options */
- }
- inc_opts_len = strlen(inc_opts);
-
- if (pass == 2) {
- INCEXE *incexe;
- if (!res_all.res_fs.have_MD5) {
- MD5Init(&res_all.res_fs.md5c);
- res_all.res_fs.have_MD5 = TRUE;
- }
- /* Create incexe structure */
- Dmsg0(200, "Create INCEXE structure\n");
- incexe = (INCEXE *)malloc(sizeof(INCEXE));
- memset(incexe, 0, sizeof(INCEXE));
- bstrncpy(incexe->opts, inc_opts, sizeof(incexe->opts));
- incexe->fileopts = (struct s_res_fopts *)res;
- Dmsg1(200, "incexe opts=%s\n", incexe->opts);
- if (item->code == 0) { /* include */
- if (res_all.res_fs.num_includes == 0) {
- res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *));
- } else {
- res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items,
- sizeof(INCEXE *) * res_all.res_fs.num_includes + 1);
- }
- res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
- Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes);
- } else { /* exclude */
- if (res_all.res_fs.num_excludes == 0) {
- res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
- } else {
- res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items,
- sizeof(INCEXE *) * res_all.res_fs.num_excludes + 1);
- }
- res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
- Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes);
- }
-
- /* Pickup include/exclude names. They are stored in INCEXE
- * structures which contains the options and the name.
- */
- while ((token = lex_get_token(lc, T_ALL)) != T_EOB) {
- switch (token) {
- case T_COMMA:
- case T_EOL:
- continue;
-
- case T_IDENTIFIER:
- case T_UNQUOTED_STRING:
- case T_QUOTED_STRING:
- if (res_all.res_fs.have_MD5) {
- MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
- }
- if (incexe->num_names == incexe->max_names) {
- incexe->max_names += 10;
- if (incexe->name_list == NULL) {
- incexe->name_list = (char **)malloc(sizeof(char *) * incexe->max_names);
- } else {
- incexe->name_list = (char **)realloc(incexe->name_list,
- sizeof(char *) * incexe->max_names);
- }
- }
- incexe->name_list[incexe->num_names++] = bstrdup(lc->str);
- Dmsg1(200, "Add to name_list %s\n", incexe->name_list[incexe->num_names -1]);
- break;
- default:
- scan_err1(lc, "Expected a filename, got: %s", lc->str);
- }
- }
- /* Note, MD5Final is done in backup.c */
- } else { /* pass 1 */
- while (lex_get_token(lc, T_ALL) != T_EOB)
- {}
- }
- scan_to_eol(lc);
- lc->options = options;
- set_bit(index, res_all.hdr.item_present);
-}
-
-/* Store FileOptions Match info */
-static void store_match(LEX *lc, struct res_items *item, int index, int pass)
-{
- int token;
- char *match;
-
- if (pass == 1) {
- /* Pickup Match string
- */
- token = lex_get_token(lc, T_ALL);
- switch (token) {
- case T_IDENTIFIER:
- case T_UNQUOTED_STRING:
- case T_QUOTED_STRING:
- match = (char *)malloc(lc->str_len + 1);
- strcpy(match, lc->str);
- res_all.res_fopts.num_match++;
- if (res_all.res_fopts.match == NULL) {
- res_all.res_fopts.match = (char **)malloc(sizeof(char *) * res_all.res_fopts.num_match);
- } else {
- res_all.res_fopts.match = (char **)realloc(res_all.res_fopts.match,
- sizeof(char *) * res_all.res_fopts.num_match);
- }
- res_all.res_fopts.match[res_all.res_fopts.num_match-1] = match;
- break;
- default:
- scan_err1(lc, "Expected a filename, got: %s", lc->str);
- }
- } else { /* pass 2 */
- lex_get_token(lc, T_ALL);
- }
- scan_to_eol(lc);
- set_bit(index, res_all.hdr.item_present);
-}
-
-static void store_opts(LEX *lc, struct res_items *item, int index, int pass)
-{
- int i;
- int keyword;
- char inc_opts[100];
-
- inc_opts[0] = 0;
- keyword = INC_KW_NONE;
- for (i=0; FS_option_kw[i].name; i++) {
- if (strcasecmp(item->name, FS_option_kw[i].name) == 0) {
- keyword = FS_option_kw[i].token;
- break;
- }
- }
- if (keyword == INC_KW_NONE) {
- scan_err1(lc, "Expected a FileSet keyword, got: %s", lc->str);
- }
- Dmsg2(200, "keyword=%d %s\n", keyword, FS_option_kw[keyword].name);
- scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
-
- bstrncat((char *)item->value, inc_opts, MAX_FO_OPTS);
-
- scan_to_eol(lc);
- set_bit(index, res_all.hdr.item_present);
-}
#define R_POOL 1009
#define R_MSGS 1010
#define R_COUNTER 1011
-#define R_FILEOPTIONS 1012
-#define R_LAST R_FILEOPTIONS
+#define R_LAST R_COUNTER
/*
* Some resource attributes
};
typedef struct s_res_job JOB;
-/*
- * File Options Resource (options for Includes)
- */
#define MAX_FO_OPTS 30
-struct s_res_fopts {
- RES hdr;
-
- char opts[MAX_FO_OPTS]; /* Options string */
- int replace; /* How (overwrite, ...) */
- char **match; /* match strings */
- int num_match; /* number of match strings */
-};
-typedef struct s_res_fopts FILEOPTIONS;
/* This is either an include item or an exclude item */
struct s_incexc_item {
char opts[MAX_FO_OPTS]; /* options string */
- struct s_res_fopts *fileopts; /* File Options resource */
+ char **match_list; /* match strings */
+ int num_match; /* number of match strings */
char **name_list; /* filename list */
+ int max_names; /* malloc'ed size of name list */
int num_names; /* number of names in the list */
- int max_names; /* malloc'ed size of list */
};
typedef struct s_incexc_item INCEXE;
struct s_res_fs {
RES hdr;
+ int finclude; /* Set if finclude/fexclude used */
INCEXE **include_items; /* array of incexe structures */
int num_includes; /* number in array */
INCEXE **exclude_items;
struct s_res_pool res_pool;
struct s_res_msgs res_msgs;
struct s_res_counter res_counter;
- struct s_res_fopts res_fopts;
RES hdr;
};
goto bail_out;
}
/* Copy File options */
- if (ie->fileopts) {
- strcpy(buf, ie->fileopts->opts);
- } else {
- strcpy(buf, ie->opts);
- }
+ strcpy(buf, ie->opts);
strcat(buf, " ");
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) {
goto bail_out;
}
/* Copy File options */
- if (ie->fileopts) {
- strcpy(buf, ie->fileopts->opts);
- } else {
- strcpy(buf, ie->opts);
- }
+ strcpy(buf, ie->opts);
strcat(buf, " ");
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) {
fclose(ffd);
break;
default:
- if (ie->fileopts) {
- pm_strcpy(&fd->msg, ie->fileopts->opts);
- Dmsg1(200, "Fileopts=%s\n", fd->msg);
- } else {
- pm_strcpy(&fd->msg, ie->opts);
- }
+ pm_strcpy(&fd->msg, ie->opts);
pm_strcat(&fd->msg, " ");
pm_strcat(&fd->msg, ie->name_list[j]);
Dmsg1(200, "Include name=%s\n", fd->msg);
--- /dev/null
+/*
+ * Configuration file parser for Include, Exclude, Finclude
+ * and FExclude records.
+ *
+ * Kern Sibbald, March MMIII
+ *
+ * Version $Id$
+ */
+/*
+ Copyright (C) 2000-2003 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 "dird.h"
+
+/* Forward referenced subroutines */
+
+void store_inc(LEX *lc, struct res_items *item, int index, int pass);
+void store_finc(LEX *lc, struct res_items *item, int index, int pass);
+
+static void store_match(LEX *lc, struct res_items *item, int index, int pass);
+static void store_opts(LEX *lc, struct res_items *item, int index, int pass);
+static void store_fname(LEX *lc, struct res_items *item, int index, int pass);
+
+
+/* We build the current resource here as we are
+ * scanning the resource configuration definition,
+ * then move it to allocated memory when the resource
+ * scan is complete.
+ */
+extern URES res_all;
+extern int res_all_size;
+
+/* We build the current Finclude Fexclude item here */
+static INCEXE res_incexe;
+
+/*
+ * FInclude/FExclude items
+ * name handler value code flags default_value
+ */
+static struct res_items finc_items[] = {
+ {"compression", store_opts, NULL, 0, 0, 0},
+ {"signature", store_opts, NULL, 0, 0, 0},
+ {"verify", store_opts, NULL, 0, 0, 0},
+ {"onefs", store_opts, NULL, 0, 0, 0},
+ {"recurse", store_opts, NULL, 0, 0, 0},
+ {"sparse", store_opts, NULL, 0, 0, 0},
+ {"readfifo", store_opts, NULL, 0, 0, 0},
+ {"replace", store_opts, NULL, 0, 0, 0},
+ {"match", store_match, NULL, 0, 0, 0},
+ {"file", store_fname, NULL, 0, 0, 0},
+
+ {NULL, NULL, NULL, 0, 0, 0}
+};
+
+/* Define FileSet KeyWord values */
+
+#define INC_KW_NONE 0
+#define INC_KW_COMPRESSION 1
+#define INC_KW_SIGNATURE 2
+#define INC_KW_ENCRYPTION 3
+#define INC_KW_VERIFY 4
+#define INC_KW_ONEFS 5
+#define INC_KW_RECURSE 6
+#define INC_KW_SPARSE 7
+#define INC_KW_REPLACE 8 /* restore options */
+#define INC_KW_READFIFO 9 /* Causes fifo data to be read */
+
+/* Include keywords -- these are keywords that can appear
+ * in the options lists of an include ( Include = compression= ...)
+ */
+static struct s_kw FS_option_kw[] = {
+ {"compression", INC_KW_COMPRESSION},
+ {"signature", INC_KW_SIGNATURE},
+ {"encryption", INC_KW_ENCRYPTION},
+ {"verify", INC_KW_VERIFY},
+ {"onefs", INC_KW_ONEFS},
+ {"recurse", INC_KW_RECURSE},
+ {"sparse", INC_KW_SPARSE},
+ {"replace", INC_KW_REPLACE},
+ {"readfifo", INC_KW_READFIFO},
+ {NULL, 0}
+};
+
+/* Options for FileSet keywords */
+
+struct s_fs_opt {
+ char *name;
+ int keyword;
+ char *option;
+};
+
+/*
+ * Options permitted for each keyword and resulting value.
+ * The output goes into opts, which are then transmitted to
+ * the FD for application as options to the following list of
+ * included files.
+ */
+static struct s_fs_opt FS_options[] = {
+ {"md5", INC_KW_SIGNATURE, "M"},
+ {"sha1", INC_KW_SIGNATURE, "S"},
+ {"gzip", INC_KW_COMPRESSION, "Z6"},
+ {"gzip1", INC_KW_COMPRESSION, "Z1"},
+ {"gzip2", INC_KW_COMPRESSION, "Z2"},
+ {"gzip3", INC_KW_COMPRESSION, "Z3"},
+ {"gzip4", INC_KW_COMPRESSION, "Z4"},
+ {"gzip5", INC_KW_COMPRESSION, "Z5"},
+ {"gzip6", INC_KW_COMPRESSION, "Z6"},
+ {"gzip7", INC_KW_COMPRESSION, "Z7"},
+ {"gzip8", INC_KW_COMPRESSION, "Z8"},
+ {"gzip9", INC_KW_COMPRESSION, "Z9"},
+ {"blowfish", INC_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
+ {"3des", INC_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
+ {"yes", INC_KW_ONEFS, "0"},
+ {"no", INC_KW_ONEFS, "f"},
+ {"yes", INC_KW_RECURSE, "0"},
+ {"no", INC_KW_RECURSE, "h"},
+ {"yes", INC_KW_SPARSE, "s"},
+ {"no", INC_KW_SPARSE, "0"},
+ {"always", INC_KW_REPLACE, "a"},
+ {"ifnewer", INC_KW_REPLACE, "w"},
+ {"never", INC_KW_REPLACE, "n"},
+ {"yes", INC_KW_READFIFO, "r"},
+ {"no", INC_KW_READFIFO, "0"},
+ {NULL, 0, 0}
+};
+
+
+
+/*
+ * Scan for Include options (keyword=option) is converted into one or
+ * two characters. Verifyopts=xxxx is Vxxxx:
+ */
+static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen)
+{
+ int token, i;
+ char option[3];
+
+ option[0] = 0; /* default option = none */
+ option[2] = 0; /* terminate options */
+ token = lex_get_token(lc, T_NAME); /* expect at least one option */
+ if (keyword == INC_KW_VERIFY) { /* special case */
+ /* ***FIXME**** ensure these are in permitted set */
+ bstrncat(opts, "V", optlen); /* indicate Verify */
+ bstrncat(opts, lc->str, optlen);
+ bstrncat(opts, ":", optlen); /* terminate it */
+
+ /*
+ * Standard keyword options for Include/Exclude
+ */
+ } else {
+ for (i=0; FS_options[i].name; i++) {
+ if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) {
+ /* NOTE! maximum 2 letters here or increase option[3] */
+ option[0] = FS_options[i].option[0];
+ option[1] = FS_options[i].option[1];
+ i = 0;
+ break;
+ }
+ }
+ if (i != 0) {
+ scan_err1(lc, "Expected a FileSet option keyword, got:%s:", lc->str);
+ } else { /* add option */
+ bstrncat(opts, option, optlen);
+ Dmsg3(200, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
+ }
+ }
+
+ /* If option terminated by comma, eat it */
+ if (lc->ch == ',') {
+ token = lex_get_token(lc, T_ALL); /* yes, eat comma */
+ }
+}
+
+/* Store FileSet Include/Exclude info */
+void store_inc(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token, i;
+ int options = lc->options;
+ int keyword;
+ char inc_opts[100];
+ int inc_opts_len;
+
+ lc->options |= LOPT_NO_IDENT; /* make spaces significant */
+
+ /* Get include options */
+ inc_opts[0] = 0;
+ while ((token=lex_get_token(lc, T_ALL)) != T_BOB) {
+ keyword = INC_KW_NONE;
+ for (i=0; FS_option_kw[i].name; i++) {
+ if (strcasecmp(lc->str, FS_option_kw[i].name) == 0) {
+ keyword = FS_option_kw[i].token;
+ break;
+ }
+ }
+ if (keyword == INC_KW_NONE) {
+ scan_err1(lc, _("Expected a FileSet keyword, got: %s"), lc->str);
+ }
+ /* Option keyword should be following by = <option> */
+ if ((token=lex_get_token(lc, T_ALL)) != T_EQUALS) {
+ scan_err1(lc, _("expected an = following keyword, got: %s"), lc->str);
+ } else {
+ scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
+ }
+ if (token == T_BOB) {
+ break;
+ }
+ }
+ if (!inc_opts[0]) {
+ strcat(inc_opts, "0"); /* set no options */
+ }
+ inc_opts_len = strlen(inc_opts);
+
+ if (pass == 1) {
+ INCEXE *incexe;
+ if (!res_all.res_fs.have_MD5) {
+ MD5Init(&res_all.res_fs.md5c);
+ res_all.res_fs.have_MD5 = TRUE;
+ }
+ /* Create incexe structure */
+ Dmsg0(200, "Create INCEXE structure\n");
+ incexe = (INCEXE *)malloc(sizeof(INCEXE));
+ memset(incexe, 0, sizeof(INCEXE));
+ bstrncpy(incexe->opts, inc_opts, sizeof(incexe->opts));
+ Dmsg1(200, "incexe opts=%s\n", incexe->opts);
+ if (item->code == 0) { /* include */
+ if (res_all.res_fs.num_includes == 0) {
+ res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *));
+ } else {
+ res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items,
+ sizeof(INCEXE *) * res_all.res_fs.num_includes + 1);
+ }
+ res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
+ Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes);
+ } else { /* exclude */
+ if (res_all.res_fs.num_excludes == 0) {
+ res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
+ } else {
+ res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items,
+ sizeof(INCEXE *) * res_all.res_fs.num_excludes + 1);
+ }
+ res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
+ Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes);
+ }
+
+ /* Pickup include/exclude names. They are stored in INCEXE
+ * structures which contains the options and the name.
+ */
+ while ((token = lex_get_token(lc, T_ALL)) != T_EOB) {
+ switch (token) {
+ case T_COMMA:
+ case T_EOL:
+ continue;
+
+ case T_IDENTIFIER:
+ case T_UNQUOTED_STRING:
+ case T_QUOTED_STRING:
+ if (res_all.res_fs.have_MD5) {
+ MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
+ }
+ if (incexe->num_names == incexe->max_names) {
+ incexe->max_names += 10;
+ if (incexe->name_list == NULL) {
+ incexe->name_list = (char **)malloc(sizeof(char *) * incexe->max_names);
+ } else {
+ incexe->name_list = (char **)realloc(incexe->name_list,
+ sizeof(char *) * incexe->max_names);
+ }
+ }
+ incexe->name_list[incexe->num_names++] = bstrdup(lc->str);
+ Dmsg1(200, "Add to name_list %s\n", incexe->name_list[incexe->num_names -1]);
+ break;
+ default:
+ scan_err1(lc, "Expected a filename, got: %s", lc->str);
+ }
+ }
+ /* Note, MD5Final is done in backup.c */
+ } else { /* pass 1 */
+ while (lex_get_token(lc, T_ALL) != T_EOB)
+ {}
+ }
+ scan_to_eol(lc);
+ lc->options = options;
+ set_bit(index, res_all.hdr.item_present);
+}
+
+
+/*
+ * Store FileSet FInclude/FExclude info
+ * Note, when this routine is called, we are inside a FileSet
+ * resource. We treat the Finclude/Fexeclude like a sort of
+ * mini-resource within the FileSet resource.
+ */
+void store_finc(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token, i;
+ INCEXE *incexe;
+
+ res_all.res_fs.finclude = TRUE;
+ token = lex_get_token(lc, T_ALL);
+ if (token != T_BOB) {
+ scan_err1(lc, _("Expecting a beginning brace, got: %s\n"), lc->str);
+ }
+ memset(&res_incexe, 0, sizeof(INCEXE));
+ while ((token = lex_get_token(lc, T_ALL)) != T_EOF) {
+ if (token == T_EOL) {
+ continue;
+ }
+ if (token == T_EOB) {
+ break;
+ }
+ if (token != T_IDENTIFIER) {
+ scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
+ }
+ for (i=0; finc_items[i].name; i++) {
+ if (strcasecmp(finc_items[i].name, lc->str) == 0) {
+ token = lex_get_token(lc, T_ALL);
+ if (token != T_EQUALS) {
+ scan_err1(lc, "expected an equals, got: %s", lc->str);
+ }
+ /* Call item handler */
+ finc_items[i].handler(lc, &finc_items[i], i, pass);
+ i = -1;
+ break;
+ }
+ }
+ if (i >=0) {
+ scan_err1(lc, "Keyword %s not permitted in this resource", lc->str);
+ }
+ }
+ if (pass == 1) {
+ incexe = (INCEXE *)malloc(sizeof(INCEXE));
+ memcpy(incexe, &res_incexe, sizeof(INCEXE));
+ Dmsg1(200, "incexe opts=%s\n", incexe->opts);
+ if (item->code == 0) { /* include */
+ if (res_all.res_fs.num_includes == 0) {
+ res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *));
+ } else {
+ res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items,
+ sizeof(INCEXE *) * res_all.res_fs.num_includes + 1);
+ }
+ res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
+ Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes);
+ } else { /* exclude */
+ if (res_all.res_fs.num_excludes == 0) {
+ res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
+ } else {
+ res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items,
+ sizeof(INCEXE *) * res_all.res_fs.num_excludes + 1);
+ }
+ res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
+ Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes);
+ }
+ }
+ scan_to_eol(lc);
+ set_bit(index, res_all.hdr.item_present);
+}
+
+
+/* Store Match info */
+static void store_match(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token;
+ char *match;
+
+ if (pass == 1) {
+ /* Pickup Match string
+ */
+ token = lex_get_token(lc, T_ALL);
+ switch (token) {
+ case T_IDENTIFIER:
+ case T_UNQUOTED_STRING:
+ case T_QUOTED_STRING:
+ match = (char *)malloc(lc->str_len + 1);
+ strcpy(match, lc->str);
+ res_incexe.num_match++;
+ if (res_incexe.match_list == NULL) {
+ res_incexe.match_list = (char **)malloc(sizeof(char *) * res_incexe.num_match);
+ } else {
+ res_incexe.match_list = (char **)realloc(res_incexe.match_list,
+ sizeof(char *) * res_incexe.num_match);
+ }
+ res_incexe.match_list[res_incexe.num_match-1] = match;
+ break;
+ default:
+ scan_err1(lc, "Expected a filename, got: %s", lc->str);
+ }
+ } else { /* pass 2 */
+ lex_get_token(lc, T_ALL);
+ }
+ scan_to_eol(lc);
+}
+
+
+/* Store Filename info */
+static void store_fname(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token;
+ INCEXE *incexe;
+
+ if (pass == 1) {
+ /* Pickup Filename string
+ */
+ token = lex_get_token(lc, T_ALL);
+ switch (token) {
+ case T_IDENTIFIER:
+ case T_UNQUOTED_STRING:
+ case T_QUOTED_STRING:
+ if (res_all.res_fs.have_MD5) {
+ MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
+ }
+ incexe = &res_incexe;
+ if (incexe->num_names == incexe->max_names) {
+ incexe->max_names += 10;
+ if (incexe->name_list == NULL) {
+ incexe->name_list = (char **)malloc(sizeof(char *) * incexe->max_names);
+ } else {
+ incexe->name_list = (char **)realloc(incexe->name_list,
+ sizeof(char *) * incexe->max_names);
+ }
+ }
+ incexe->name_list[incexe->num_names++] = bstrdup(lc->str);
+ Dmsg1(200, "Add to name_list %s\n", incexe->name_list[incexe->num_names -1]);
+ break;
+ default:
+ scan_err1(lc, "Expected a filename, got: %s", lc->str);
+ }
+ } else { /* pass 2 */
+ lex_get_token(lc, T_ALL);
+ }
+ scan_to_eol(lc);
+}
+
+
+static void store_opts(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int i;
+ int keyword;
+ char inc_opts[100];
+
+ inc_opts[0] = 0;
+ keyword = INC_KW_NONE;
+ for (i=0; FS_option_kw[i].name; i++) {
+ if (strcasecmp(item->name, FS_option_kw[i].name) == 0) {
+ keyword = FS_option_kw[i].token;
+ break;
+ }
+ }
+ if (keyword == INC_KW_NONE) {
+ scan_err1(lc, "Expected a FileSet keyword, got: %s", lc->str);
+ }
+ Dmsg2(200, "keyword=%d %s\n", keyword, FS_option_kw[keyword].name);
+ scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
+
+ bstrncat(res_incexe.opts, inc_opts, MAX_FO_OPTS);
+
+ scan_to_eol(lc);
+}
}
for (i=0; items[i].name; i++) {
if (strcasecmp(items[i].name, lc->str) == 0) {
- token = lex_get_token(lc, T_ALL);
- 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);
- /* NOT REACHED */
+ /* If the ITEM_NO_EQUALS flag is set we do NOT
+ * scan for = after the keyword */
+ if (!(items[i].flags & ITEM_NO_EQUALS)) {
+ token = lex_get_token(lc, T_ALL);
+ 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);
+ /* NOT REACHED */
+ }
}
Dmsg1(150, "calling handler for %s\n", items[i].name);
/* Call item handler */
#define MAX_RES_NAME_LENGTH MAX_NAME_LENGTH-1 /* maximum resource name length */
-#define ITEM_REQUIRED 0x1 /* item required */
-#define ITEM_DEFAULT 0x2 /* default supplied */
+#define ITEM_REQUIRED 0x1 /* item required */
+#define ITEM_DEFAULT 0x2 /* default supplied */
+#define ITEM_NO_EQUALS 0x4 /* Don't scan = after name */
/* Message Resource */
struct s_res_msgs {
/* */
#define VERSION "1.30"
#define VSTRING "1"
-#define BDATE "02 March 2003"
-#define LSMDATE "02Mar03"
+#define BDATE "03 March 2003"
+#define LSMDATE "03Mar03"
/* Debug flags */
#define DEBUG 1