* Version $Id$
*/
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2003-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
/* Forward referenced subroutines */
-void store_inc(LEX *lc, struct res_items *item, int index, int pass);
+void store_inc(LEX *lc, RES_ITEM *item, int index, int pass);
-static void store_newinc(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);
-static void store_base(LEX *lc, struct res_items *item, int index, int pass);
+static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass);
+static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass);
+static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass);
+static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass);
+static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass);
+static void options_res(LEX *lc, RES_ITEM *item, int index, int pass);
+static void store_base(LEX *lc, RES_ITEM *item, int index, int pass);
static void setup_current_opts(void);
/*
* new Include/Exclude items
- * name handler value code flags default_value
+ * name handler value code flags default_value
*/
-static struct res_items newinc_items[] = {
+static RES_ITEM newinc_items[] = {
+ {"file", store_fname, NULL, 0, 0, 0},
+ {"options", options_res, NULL, 0, 0, 0},
+ {NULL, NULL, NULL, 0, 0, 0}
+};
+
+/*
+ * Items that are valid in an Options resource
+ */
+static RES_ITEM options_items[] = {
{"compression", store_opts, NULL, 0, 0, 0},
{"signature", store_opts, NULL, 0, 0, 0},
{"verify", store_opts, NULL, 0, 0, 0},
{"readfifo", store_opts, NULL, 0, 0, 0},
{"replace", store_opts, NULL, 0, 0, 0},
{"portable", store_opts, NULL, 0, 0, 0},
- {"match", store_match, NULL, 0, 0, 0},
- {"file", store_fname, NULL, 0, 0, 0},
+ {"regex", store_regex, NULL, 0, 0, 0},
{"base", store_base, NULL, 0, 0, 0},
+ {"wild", store_wild, NULL, 0, 0, 0},
+ {"exclude", store_opts, 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 */
-#define INC_KW_PORTABLE 10
-#define INC_KW_MTIMEONLY 11
-#define INC_KW_KEEPATIME 12
-
-/* Include keywords -- these are keywords that can appear
+enum {
+ INC_KW_NONE,
+ INC_KW_COMPRESSION,
+ INC_KW_SIGNATURE,
+ INC_KW_ENCRYPTION,
+ INC_KW_VERIFY,
+ INC_KW_ONEFS,
+ INC_KW_RECURSE,
+ INC_KW_SPARSE,
+ INC_KW_REPLACE, /* restore options */
+ INC_KW_READFIFO, /* Causes fifo data to be read */
+ INC_KW_PORTABLE,
+ INC_KW_MTIMEONLY,
+ INC_KW_KEEPATIME,
+ INC_KW_EXCLUDE
+};
+
+/*
+ * Include keywords -- these are keywords that can appear
* in the options lists of an old include ( Include = compression= ...)
*/
static struct s_kw FS_option_kw[] = {
{"portable", INC_KW_PORTABLE},
{"mtimeonly", INC_KW_MTIMEONLY},
{"keepatime", INC_KW_KEEPATIME},
+ {"exclude", INC_KW_EXCLUDE},
{NULL, 0}
};
{"no", INC_KW_MTIMEONLY, "0"},
{"yes", INC_KW_KEEPATIME, "k"},
{"no", INC_KW_KEEPATIME, "0"},
+ {"yes", INC_KW_EXCLUDE, "e"},
+ {"no", INC_KW_EXCLUDE, "0"},
{NULL, 0, 0}
};
* Scan for right hand side of Include options (keyword=option) is
* converted into one or two characters. Verifyopts=xxxx is Vxxxx:
* Whatever is found is concatenated to the opts string.
+ * This code is also used inside an Options resource.
*/
static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen)
{
}
}
-/* Store FileSet Include/Exclude info */
-void store_inc(LEX *lc, struct res_items *item, int index, int pass)
+/*
+ *
+ * Store FileSet Include/Exclude info
+ */
+void store_inc(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token, i;
int options = lc->options;
/*
* Decide if we are doing a new Include or an old include. The
- * new Include is followed immediately by {, whereas the
+ * new Include is followed immediately by open brace, whereas the
* old include has options following the Include.
*/
token = lex_get_token(lc, T_ALL);
/*
* 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
+ * resource. We treat the Include/Execlude like a sort of
* mini-resource within the FileSet resource.
*/
-static void store_newinc(LEX *lc, struct res_items *item, int index, int pass)
+static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token, i;
INCEXE *incexe;
+ bool options;
if (!res_all.res_fs.have_MD5) {
MD5Init(&res_all.res_fs.md5c);
res_all.res_fs.have_MD5 = TRUE;
}
memset(&res_incexe, 0, sizeof(INCEXE));
- res_all.res_fs.new_include = TRUE;
+ res_all.res_fs.new_include = true;
while ((token = lex_get_token(lc, T_ALL)) != T_EOF) {
if (token == T_EOL) {
continue;
scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
}
for (i=0; newinc_items[i].name; i++) {
+ options = strcasecmp(lc->str, "options") == 0;
if (strcasecmp(newinc_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);
+ if (!options) {
+ token = lex_get_token(lc, T_ALL);
+ if (token != T_EQUALS) {
+ scan_err1(lc, "expected an equals, got: %s", lc->str);
+ }
}
/* Call item handler */
newinc_items[i].handler(lc, &newinc_items[i], i, pass);
}
-/* Store Match info */
-static void store_match(LEX *lc, struct res_items *item, int index, int pass)
+/* Store regex info */
+static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token;
if (pass == 1) {
- /* Pickup Match string
+ /* Pickup regex string
*/
token = lex_get_token(lc, T_ALL);
switch (token) {
case T_IDENTIFIER:
case T_UNQUOTED_STRING:
case T_QUOTED_STRING:
- setup_current_opts();
- res_incexe.current_opts->match.append(bstrdup(lc->str));
+ res_incexe.current_opts->regex.append(bstrdup(lc->str));
+ Dmsg3(200, "set regex %p size=%d %s\n",
+ res_incexe.current_opts, res_incexe.current_opts->regex.size(),lc->str);
break;
default:
- scan_err1(lc, _("Expected a filename, got: %s\n"), lc->str);
+ scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str);
}
} else { /* pass 2 */
lex_get_token(lc, T_ALL);
}
/* Store Base info */
-static void store_base(LEX *lc, struct res_items *item, int index, int pass)
+static void store_base(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token;
if (pass == 1) {
- setup_current_opts();
/*
* Pickup Base Job Name
*/
token = lex_get_token(lc, T_NAME);
- res_incexe.current_opts->base_list.append(bstrdup(lc->str));
+ res_incexe.current_opts->base.append(bstrdup(lc->str));
} else { /* pass 2 */
lex_get_token(lc, T_ALL);
}
scan_to_eol(lc);
}
+
+
+/* Store Wild-card info */
+static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+ int token;
+
+ if (pass == 1) {
+ /*
+ * Pickup Wild-card string
+ */
+ token = lex_get_token(lc, T_ALL);
+ switch (token) {
+ case T_IDENTIFIER:
+ case T_UNQUOTED_STRING:
+ case T_QUOTED_STRING:
+ res_incexe.current_opts->wild.append(bstrdup(lc->str));
+ Dmsg3(200, "set wild %p size=%d %s\n",
+ res_incexe.current_opts, res_incexe.current_opts->wild.size(),lc->str);
+ break;
+ default:
+ scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str);
+ }
+ } else { /* pass 2 */
+ lex_get_token(lc, T_ALL);
+ }
+ scan_to_eol(lc);
+}
+
+
/*
* Store Filename info. Note, for minor efficiency reasons, we
* always increase the name buffer by 10 items because we expect
* to add more entries.
*/
-static void store_fname(LEX *lc, struct res_items *item, int index, int pass)
+static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass)
{
int token;
INCEXE *incexe;
scan_to_eol(lc);
}
+/*
+ * Come here when Options seen in Include/Exclude
+ */
+static void options_res(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+ int token, i;
+
+ token = lex_get_token(lc, T_ALL);
+ if (token != T_BOB) {
+ scan_err1(lc, "Expecting open brace. Got %s", lc->str);
+ }
+
+ if (pass == 1) {
+ setup_current_opts();
+ }
+
+ 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; options_items[i].name; i++) {
+ if (strcasecmp(options_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 */
+ options_items[i].handler(lc, &options_items[i], i, pass);
+ i = -1;
+ break;
+ }
+ }
+ if (i >=0) {
+ scan_err1(lc, "Keyword %s not permitted in this resource", lc->str);
+ }
+ }
+ scan_to_eol(lc);
+}
+
+
/*
* New style options come here
*/
-static void store_opts(LEX *lc, struct res_items *item, int index, int pass)
+static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass)
{
int i;
int keyword;
/* Now scan for the value */
scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
if (pass == 1) {
- setup_current_opts();
- bstrncpy(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
+ bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
Dmsg2(100, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
}
scan_to_eol(lc);
/* If current_opts not defined, create first entry */
static void setup_current_opts(void)
{
- 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;
+ FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS));
+ memset(fo, 0, sizeof(FOPTS));
+ fo->regex.init(1, true);
+ fo->wild.init(1, true);
+ fo->base.init(1, true);
+ res_incexe.current_opts = fo;
+ if (res_incexe.num_opts == 0) {
res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
- res_incexe.opts_list[0] = res_incexe.current_opts;
+ } else {
+ res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list,
+ sizeof(FOPTS *) * (res_incexe.num_opts + 1));
}
+ res_incexe.opts_list[res_incexe.num_opts++] = fo;
}