2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * Configuration file parser for new and old Include and
20 * Written by Kern Sibbald, March MMIII
27 #include "lib/bregex.h"
32 /* Forward referenced subroutines */
34 void store_inc(LEX *lc, RES_ITEM *item, int index, int pass);
36 static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass);
37 static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass);
38 static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass);
39 static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass);
40 static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass);
41 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass);
42 static void store_base(LEX *lc, RES_ITEM *item, int index, int pass);
43 static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass);
44 static void setup_current_opts(void);
46 /* Include and Exclude items */
47 static void store_fname(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
48 static void store_plugin_name(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
49 static void options_res(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
50 static void store_excludedir(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
53 /* We build the current resource here as we are
54 * scanning the resource configuration definition,
55 * then move it to allocated memory when the resource
59 extern "C" { // work around visual compiler mangling variables
65 extern int32_t res_all_size;
67 /* We build the current new Include and Exclude items here */
68 static INCEXE res_incexe;
71 * new Include/Exclude items
72 * name handler value code flags default_value
74 static RES_ITEM2 newinc_items[] = {
75 {"file", store_fname, {0}, 0, 0, 0},
76 {"plugin", store_plugin_name, {0}, 0, 0, 0},
77 {"excludedircontaining", store_excludedir, {0}, 0, 0, 0},
78 {"options", options_res, {0}, 0, 0, 0},
79 {NULL, NULL, {0}, 0, 0, 0}
83 * Items that are valid in an Options resource
85 static RES_ITEM options_items[] = {
86 {"compression", store_opts, {0}, 0, 0, 0},
87 {"signature", store_opts, {0}, 0, 0, 0},
88 {"basejob", store_opts, {0}, 0, 0, 0},
89 {"accurate", store_opts, {0}, 0, 0, 0},
90 {"verify", store_opts, {0}, 0, 0, 0},
91 {"onefs", store_opts, {0}, 0, 0, 0},
92 {"recurse", store_opts, {0}, 0, 0, 0},
93 {"sparse", store_opts, {0}, 0, 0, 0},
94 {"hardlinks", store_opts, {0}, 0, 0, 0},
95 {"readfifo", store_opts, {0}, 0, 0, 0},
96 {"replace", store_opts, {0}, 0, 0, 0},
97 {"portable", store_opts, {0}, 0, 0, 0},
98 {"mtimeonly", store_opts, {0}, 0, 0, 0},
99 {"keepatime", store_opts, {0}, 0, 0, 0},
100 {"regex", store_regex, {0}, 0, 0, 0},
101 {"regexdir", store_regex, {0}, 1, 0, 0},
102 {"regexfile", store_regex, {0}, 2, 0, 0},
103 {"base", store_base, {0}, 0, 0, 0},
104 {"wild", store_wild, {0}, 0, 0, 0},
105 {"wilddir", store_wild, {0}, 1, 0, 0},
106 {"wildfile", store_wild, {0}, 2, 0, 0},
107 {"exclude", store_opts, {0}, 0, 0, 0},
108 {"aclsupport", store_opts, {0}, 0, 0, 0},
109 {"plugin", store_plugin, {0}, 0, 0, 0},
110 {"ignorecase", store_opts, {0}, 0, 0, 0},
111 {"fstype", store_fstype, {0}, 0, 0, 0},
112 {"hfsplussupport", store_opts, {0}, 0, 0, 0},
113 {"noatime", store_opts, {0}, 0, 0, 0},
114 {"enhancedwild", store_opts, {0}, 0, 0, 0},
115 {"drivetype", store_drivetype, {0}, 0, 0, 0},
116 {"checkfilechanges",store_opts, {0}, 0, 0, 1},
117 {"strippath", store_opts, {0}, 0, 0, 0},
118 {"honornodumpflag", store_opts, {0}, 0, 0, 0},
119 {"xattrsupport", store_opts, {0}, 0, 0, 0},
120 {NULL, NULL, {0}, 0, 0, 0}
124 /* Define FileSet KeyWord values */
137 INC_KW_REPLACE, /* restore options */
138 INC_KW_READFIFO, /* Causes fifo data to be read */
155 * This is the list of options that can be stored by store_opts
156 * Note, now that the old style Include/Exclude code is gone,
157 * the INC_KW code could be put into the "code" field of the
158 * options given above.
160 static struct s_kw FS_option_kw[] = {
161 {"compression", INC_KW_COMPRESSION},
162 {"signature", INC_KW_DIGEST},
163 {"encryption", INC_KW_ENCRYPTION},
164 {"verify", INC_KW_VERIFY},
165 {"basejob", INC_KW_BASEJOB},
166 {"accurate", INC_KW_ACCURATE},
167 {"onefs", INC_KW_ONEFS},
168 {"recurse", INC_KW_RECURSE},
169 {"sparse", INC_KW_SPARSE},
170 {"hardlinks", INC_KW_HARDLINK},
171 {"replace", INC_KW_REPLACE},
172 {"readfifo", INC_KW_READFIFO},
173 {"portable", INC_KW_PORTABLE},
174 {"mtimeonly", INC_KW_MTIMEONLY},
175 {"keepatime", INC_KW_KEEPATIME},
176 {"exclude", INC_KW_EXCLUDE},
177 {"aclsupport", INC_KW_ACL},
178 {"ignorecase", INC_KW_IGNORECASE},
179 {"hfsplussupport", INC_KW_HFSPLUS},
180 {"noatime", INC_KW_NOATIME},
181 {"enhancedwild", INC_KW_ENHANCEDWILD},
182 {"checkfilechanges", INC_KW_CHKCHANGES},
183 {"strippath", INC_KW_STRIPPATH},
184 {"honornodumpflag", INC_KW_HONOR_NODUMP},
185 {"xattrsupport", INC_KW_XATTR},
189 /* Options for FileSet keywords */
198 * Options permitted for each keyword and resulting value.
199 * The output goes into opts, which are then transmitted to
200 * the FD for application as options to the following list of
203 static struct s_fs_opt FS_options[] = {
204 {"md5", INC_KW_DIGEST, "M"},
205 {"sha1", INC_KW_DIGEST, "S"},
206 {"sha256", INC_KW_DIGEST, "S2"},
207 {"sha512", INC_KW_DIGEST, "S3"},
208 {"gzip", INC_KW_COMPRESSION, "Z6"},
209 {"gzip1", INC_KW_COMPRESSION, "Z1"},
210 {"gzip2", INC_KW_COMPRESSION, "Z2"},
211 {"gzip3", INC_KW_COMPRESSION, "Z3"},
212 {"gzip4", INC_KW_COMPRESSION, "Z4"},
213 {"gzip5", INC_KW_COMPRESSION, "Z5"},
214 {"gzip6", INC_KW_COMPRESSION, "Z6"},
215 {"gzip7", INC_KW_COMPRESSION, "Z7"},
216 {"gzip8", INC_KW_COMPRESSION, "Z8"},
217 {"gzip9", INC_KW_COMPRESSION, "Z9"},
218 {"lzo", INC_KW_COMPRESSION, "Zo"},
219 {"blowfish", INC_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
220 {"3des", INC_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
221 {"yes", INC_KW_ONEFS, "0"},
222 {"no", INC_KW_ONEFS, "f"},
223 {"yes", INC_KW_RECURSE, "0"},
224 {"no", INC_KW_RECURSE, "h"},
225 {"yes", INC_KW_SPARSE, "s"},
226 {"no", INC_KW_SPARSE, "0"},
227 {"yes", INC_KW_HARDLINK, "0"},
228 {"no", INC_KW_HARDLINK, "H"},
229 {"always", INC_KW_REPLACE, "a"},
230 {"ifnewer", INC_KW_REPLACE, "w"},
231 {"never", INC_KW_REPLACE, "n"},
232 {"yes", INC_KW_READFIFO, "r"},
233 {"no", INC_KW_READFIFO, "0"},
234 {"yes", INC_KW_PORTABLE, "p"},
235 {"no", INC_KW_PORTABLE, "0"},
236 {"yes", INC_KW_MTIMEONLY, "m"},
237 {"no", INC_KW_MTIMEONLY, "0"},
238 {"yes", INC_KW_KEEPATIME, "k"},
239 {"no", INC_KW_KEEPATIME, "0"},
240 {"yes", INC_KW_EXCLUDE, "e"},
241 {"no", INC_KW_EXCLUDE, "0"},
242 {"yes", INC_KW_ACL, "A"},
243 {"no", INC_KW_ACL, "0"},
244 {"yes", INC_KW_IGNORECASE, "i"},
245 {"no", INC_KW_IGNORECASE, "0"},
246 {"yes", INC_KW_HFSPLUS, "R"}, /* "R" for resource fork */
247 {"no", INC_KW_HFSPLUS, "0"},
248 {"yes", INC_KW_NOATIME, "K"},
249 {"no", INC_KW_NOATIME, "0"},
250 {"yes", INC_KW_ENHANCEDWILD, "K"},
251 {"no", INC_KW_ENHANCEDWILD, "0"},
252 {"yes", INC_KW_CHKCHANGES, "c"},
253 {"no", INC_KW_CHKCHANGES, "0"},
254 {"yes", INC_KW_HONOR_NODUMP, "N"},
255 {"no", INC_KW_HONOR_NODUMP, "0"},
256 {"yes", INC_KW_XATTR, "X"},
257 {"no", INC_KW_XATTR, "0"},
264 * Scan for right hand side of Include options (keyword=option) is
265 * converted into one or two characters. Verifyopts=xxxx is Vxxxx:
266 * Whatever is found is concatenated to the opts string.
267 * This code is also used inside an Options resource.
269 static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen)
273 int lcopts = lc->options;
275 option[0] = 0; /* default option = none */
276 option[2] = 0; /* terminate options */
277 lc->options |= LOPT_STRING; /* force string */
278 lex_get_token(lc, T_STRING); /* expect at least one option */
279 if (keyword == INC_KW_VERIFY) { /* special case */
280 /* ***FIXME**** ensure these are in permitted set */
281 bstrncat(opts, "V", optlen); /* indicate Verify */
282 bstrncat(opts, lc->str, optlen);
283 bstrncat(opts, ":", optlen); /* terminate it */
284 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
285 } else if (keyword == INC_KW_ACCURATE) { /* special case */
286 /* ***FIXME**** ensure these are in permitted set */
287 bstrncat(opts, "C", optlen); /* indicate Accurate */
288 bstrncat(opts, lc->str, optlen);
289 bstrncat(opts, ":", optlen); /* terminate it */
290 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
291 } else if (keyword == INC_KW_BASEJOB) { /* special case */
292 /* ***FIXME**** ensure these are in permitted set */
293 bstrncat(opts, "J", optlen); /* indicate BaseJob */
294 bstrncat(opts, lc->str, optlen);
295 bstrncat(opts, ":", optlen); /* terminate it */
296 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
297 } else if (keyword == INC_KW_STRIPPATH) { /* another special case */
298 if (!is_an_integer(lc->str)) {
299 scan_err1(lc, _("Expected a strip path positive integer, got:%s:"), lc->str);
301 bstrncat(opts, "P", optlen); /* indicate strip path */
302 bstrncat(opts, lc->str, optlen);
303 bstrncat(opts, ":", optlen); /* terminate it */
304 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
306 * Standard keyword options for Include/Exclude
309 for (i=0; FS_options[i].name; i++) {
310 if (FS_options[i].keyword == keyword && strcasecmp(lc->str, FS_options[i].name) == 0) {
311 /* NOTE! maximum 2 letters here or increase option[3] */
312 option[0] = FS_options[i].option[0];
313 option[1] = FS_options[i].option[1];
319 scan_err1(lc, _("Expected a FileSet option keyword, got:%s:"), lc->str);
320 } else { /* add option */
321 bstrncat(opts, option, optlen);
322 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
325 lc->options = lcopts;
327 /* If option terminated by comma, eat it */
329 lex_get_token(lc, T_ALL); /* yes, eat comma */
335 * Store FileSet Include/Exclude info
336 * new style includes are handled in store_newinc()
338 void store_inc(LEX *lc, RES_ITEM *item, int index, int pass)
343 * Decide if we are doing a new Include or an old include. The
344 * new Include is followed immediately by open brace, whereas the
345 * old include has options following the Include.
347 token = lex_get_token(lc, T_SKIP_EOL);
348 if (token == T_BOB) {
349 store_newinc(lc, item, index, pass);
352 scan_err0(lc, _("Old style Include/Exclude not supported\n"));
357 * Store new style FileSet Include/Exclude info
359 * Note, when this routine is called, we are inside a FileSet
360 * resource. We treat the Include/Execlude like a sort of
361 * mini-resource within the FileSet resource.
363 static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass)
369 if (!res_all.res_fs.have_MD5) {
370 MD5Init(&res_all.res_fs.md5c);
371 res_all.res_fs.have_MD5 = true;
373 memset(&res_incexe, 0, sizeof(INCEXE));
374 res_all.res_fs.new_include = true;
375 while ((token = lex_get_token(lc, T_SKIP_EOL)) != T_EOF) {
376 if (token == T_EOB) {
379 if (token != T_IDENTIFIER) {
380 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
382 for (i=0; newinc_items[i].name; i++) {
383 options = strcasecmp(lc->str, "options") == 0;
384 if (strcasecmp(newinc_items[i].name, lc->str) == 0) {
386 token = lex_get_token(lc, T_SKIP_EOL);
387 if (token != T_EQUALS) {
388 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
391 /* Call item handler */
392 newinc_items[i].handler(lc, &newinc_items[i], i, pass, item->code);
398 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
402 incexe = (INCEXE *)malloc(sizeof(INCEXE));
403 memcpy(incexe, &res_incexe, sizeof(INCEXE));
404 memset(&res_incexe, 0, sizeof(INCEXE));
405 if (item->code == 0) { /* include */
406 if (res_all.res_fs.num_includes == 0) {
407 res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *));
409 res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items,
410 sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1));
412 res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
413 Dmsg1(900, "num_includes=%d\n", res_all.res_fs.num_includes);
414 } else { /* exclude */
415 if (res_all.res_fs.num_excludes == 0) {
416 res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
418 res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items,
419 sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1));
421 res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
422 Dmsg1(900, "num_excludes=%d\n", res_all.res_fs.num_excludes);
426 set_bit(index, res_all.hdr.item_present);
430 /* Store regex info */
431 static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass)
439 token = lex_get_token(lc, T_SKIP_EOL);
441 /* Pickup regex string
445 case T_UNQUOTED_STRING:
446 case T_QUOTED_STRING:
447 rc = regcomp(&preg, lc->str, REG_EXTENDED);
449 regerror(rc, &preg, prbuf, sizeof(prbuf));
451 scan_err1(lc, _("Regex compile error. ERR=%s\n"), prbuf);
455 if (item->code == 1) {
457 res_incexe.current_opts->regexdir.append(bstrdup(lc->str));
458 newsize = res_incexe.current_opts->regexdir.size();
459 } else if (item->code == 2) {
461 res_incexe.current_opts->regexfile.append(bstrdup(lc->str));
462 newsize = res_incexe.current_opts->regexfile.size();
465 res_incexe.current_opts->regex.append(bstrdup(lc->str));
466 newsize = res_incexe.current_opts->regex.size();
468 Dmsg4(900, "set %s %p size=%d %s\n",
469 type, res_incexe.current_opts, newsize, lc->str);
472 scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str);
478 /* Store Base info */
479 static void store_base(LEX *lc, RES_ITEM *item, int index, int pass)
482 lex_get_token(lc, T_NAME);
485 * Pickup Base Job Name
487 res_incexe.current_opts->base.append(bstrdup(lc->str));
492 /* Store reader info */
493 static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass)
496 lex_get_token(lc, T_NAME);
499 * Pickup plugin command
501 res_incexe.current_opts->plugin = bstrdup(lc->str);
507 /* Store Wild-card info */
508 static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
514 token = lex_get_token(lc, T_SKIP_EOL);
517 * Pickup Wild-card string
521 case T_UNQUOTED_STRING:
522 case T_QUOTED_STRING:
523 if (item->code == 1) {
525 res_incexe.current_opts->wilddir.append(bstrdup(lc->str));
526 newsize = res_incexe.current_opts->wilddir.size();
527 } else if (item->code == 2) {
528 if (strpbrk(lc->str, "/\\") != NULL) {
530 res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
531 newsize = res_incexe.current_opts->wildfile.size();
534 res_incexe.current_opts->wildbase.append(bstrdup(lc->str));
535 newsize = res_incexe.current_opts->wildbase.size();
539 res_incexe.current_opts->wild.append(bstrdup(lc->str));
540 newsize = res_incexe.current_opts->wild.size();
542 Dmsg4(9, "set %s %p size=%d %s\n",
543 type, res_incexe.current_opts, newsize, lc->str);
546 scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str);
552 /* Store fstype info */
553 static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass)
557 token = lex_get_token(lc, T_SKIP_EOL);
559 /* Pickup fstype string */
562 case T_UNQUOTED_STRING:
563 case T_QUOTED_STRING:
564 res_incexe.current_opts->fstype.append(bstrdup(lc->str));
565 Dmsg3(900, "set fstype %p size=%d %s\n",
566 res_incexe.current_opts, res_incexe.current_opts->fstype.size(), lc->str);
569 scan_err1(lc, _("Expected an fstype string, got: %s\n"), lc->str);
575 /* Store exclude directory containing info */
576 static void store_excludedir(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
580 scan_err0(lc, _("ExcludeDirContaining directive not permitted in Exclude.\n"));
583 lex_get_token(lc, T_NAME);
585 res_incexe.ignoredir = bstrdup(lc->str);
590 /* Store drivetype info */
591 static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass)
595 token = lex_get_token(lc, T_SKIP_EOL);
597 /* Pickup drivetype string */
600 case T_UNQUOTED_STRING:
601 case T_QUOTED_STRING:
602 res_incexe.current_opts->drivetype.append(bstrdup(lc->str));
603 Dmsg3(900, "set drivetype %p size=%d %s\n",
604 res_incexe.current_opts, res_incexe.current_opts->drivetype.size(), lc->str);
607 scan_err1(lc, _("Expected an drivetype string, got: %s\n"), lc->str);
614 * Store Filename info. Note, for minor efficiency reasons, we
615 * always increase the name buffer by 10 items because we expect
616 * to add more entries.
618 static void store_fname(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
623 token = lex_get_token(lc, T_SKIP_EOL);
625 /* Pickup Filename string
629 case T_UNQUOTED_STRING:
630 if (strchr(lc->str, '\\')) {
631 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
634 case T_QUOTED_STRING:
635 if (res_all.res_fs.have_MD5) {
636 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
638 incexe = &res_incexe;
639 if (incexe->name_list.size() == 0) {
640 incexe->name_list.init(10, true);
642 incexe->name_list.append(bstrdup(lc->str));
643 Dmsg1(900, "Add to name_list %s\n", lc->str);
646 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
653 * Store Filename info. Note, for minor efficiency reasons, we
654 * always increase the name buffer by 10 items because we expect
655 * to add more entries.
657 static void store_plugin_name(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
663 scan_err0(lc, _("Plugin directive not permitted in Exclude\n"));
666 token = lex_get_token(lc, T_SKIP_EOL);
668 /* Pickup Filename string
672 case T_UNQUOTED_STRING:
673 if (strchr(lc->str, '\\')) {
674 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
677 case T_QUOTED_STRING:
678 if (res_all.res_fs.have_MD5) {
679 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
681 incexe = &res_incexe;
682 if (incexe->plugin_list.size() == 0) {
683 incexe->plugin_list.init(10, true);
685 incexe->plugin_list.append(bstrdup(lc->str));
686 Dmsg1(900, "Add to plugin_list %s\n", lc->str);
689 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
699 * Come here when Options seen in Include/Exclude
701 static void options_res(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
706 scan_err0(lc, _("Options section not permitted in Exclude\n"));
709 token = lex_get_token(lc, T_SKIP_EOL);
710 if (token != T_BOB) {
711 scan_err1(lc, _("Expecting open brace. Got %s"), lc->str);
715 setup_current_opts();
718 while ((token = lex_get_token(lc, T_ALL)) != T_EOF) {
719 if (token == T_EOL) {
722 if (token == T_EOB) {
725 if (token != T_IDENTIFIER) {
726 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
728 for (i=0; options_items[i].name; i++) {
729 if (strcasecmp(options_items[i].name, lc->str) == 0) {
730 token = lex_get_token(lc, T_SKIP_EOL);
731 if (token != T_EQUALS) {
732 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
734 /* Call item handler */
735 options_items[i].handler(lc, &options_items[i], i, pass);
741 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
748 * New style options come here
750 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass)
757 keyword = INC_KW_NONE;
758 /* Look up the keyword */
759 for (i=0; FS_option_kw[i].name; i++) {
760 if (strcasecmp(item->name, FS_option_kw[i].name) == 0) {
761 keyword = FS_option_kw[i].token;
765 if (keyword == INC_KW_NONE) {
766 scan_err1(lc, _("Expected a FileSet keyword, got: %s"), lc->str);
768 /* Now scan for the value */
769 scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
771 bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
772 Dmsg2(900, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
779 /* If current_opts not defined, create first entry */
780 static void setup_current_opts(void)
782 FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS));
783 memset(fo, 0, sizeof(FOPTS));
784 fo->regex.init(1, true);
785 fo->regexdir.init(1, true);
786 fo->regexfile.init(1, true);
787 fo->wild.init(1, true);
788 fo->wilddir.init(1, true);
789 fo->wildfile.init(1, true);
790 fo->wildbase.init(1, true);
791 fo->base.init(1, true);
792 fo->fstype.init(1, true);
793 fo->drivetype.init(1, true);
794 res_incexe.current_opts = fo;
795 if (res_incexe.num_opts == 0) {
796 res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
798 res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list,
799 sizeof(FOPTS *) * (res_incexe.num_opts + 1));
801 res_incexe.opts_list[res_incexe.num_opts++] = fo;