2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Configuration file parser for new and old Include and
32 * Kern Sibbald, March MMIII
40 #include "lib/bregex.h"
45 /* Forward referenced subroutines */
47 void store_inc(LEX *lc, RES_ITEM *item, int index, int pass);
49 static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass);
50 static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass);
51 static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass);
52 static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass);
53 static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass);
54 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass);
55 static void store_base(LEX *lc, RES_ITEM *item, int index, int pass);
56 static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass);
57 static void setup_current_opts(void);
59 /* Include and Exclude items */
60 static void store_fname(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
61 static void store_plugin_name(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
62 static void options_res(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
63 static void store_excludedir(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude);
66 /* We build the current resource here as we are
67 * scanning the resource configuration definition,
68 * then move it to allocated memory when the resource
72 extern "C" { // work around visual compiler mangling variables
78 extern int res_all_size;
80 /* We build the current new Include and Exclude items here */
81 static INCEXE res_incexe;
84 * new Include/Exclude items
85 * name handler value code flags default_value
87 static RES_ITEM2 newinc_items[] = {
88 {"file", store_fname, {0}, 0, 0, 0},
89 {"plugin", store_plugin_name, {0}, 0, 0, 0},
90 {"excludedircontaining", store_excludedir, {0}, 0, 0, 0},
91 {"options", options_res, {0}, 0, 0, 0},
92 {NULL, NULL, {0}, 0, 0, 0}
96 * Items that are valid in an Options resource
98 static RES_ITEM options_items[] = {
99 {"compression", store_opts, {0}, 0, 0, 0},
100 {"signature", store_opts, {0}, 0, 0, 0},
101 {"accurate", store_opts, {0}, 0, 0, 0},
102 {"verify", store_opts, {0}, 0, 0, 0},
103 {"onefs", store_opts, {0}, 0, 0, 0},
104 {"recurse", store_opts, {0}, 0, 0, 0},
105 {"sparse", store_opts, {0}, 0, 0, 0},
106 {"hardlinks", store_opts, {0}, 0, 0, 0},
107 {"readfifo", store_opts, {0}, 0, 0, 0},
108 {"replace", store_opts, {0}, 0, 0, 0},
109 {"portable", store_opts, {0}, 0, 0, 0},
110 {"mtimeonly", store_opts, {0}, 0, 0, 0},
111 {"keepatime", store_opts, {0}, 0, 0, 0},
112 {"regex", store_regex, {0}, 0, 0, 0},
113 {"regexdir", store_regex, {0}, 1, 0, 0},
114 {"regexfile", store_regex, {0}, 2, 0, 0},
115 {"base", store_base, {0}, 0, 0, 0},
116 {"wild", store_wild, {0}, 0, 0, 0},
117 {"wilddir", store_wild, {0}, 1, 0, 0},
118 {"wildfile", store_wild, {0}, 2, 0, 0},
119 {"exclude", store_opts, {0}, 0, 0, 0},
120 {"aclsupport", store_opts, {0}, 0, 0, 0},
121 {"plugin", store_plugin, {0}, 0, 0, 0},
122 {"ignorecase", store_opts, {0}, 0, 0, 0},
123 {"fstype", store_fstype, {0}, 0, 0, 0},
124 {"hfsplussupport", store_opts, {0}, 0, 0, 0},
125 {"noatime", store_opts, {0}, 0, 0, 0},
126 {"enhancedwild", store_opts, {0}, 0, 0, 0},
127 {"drivetype", store_drivetype, {0}, 0, 0, 0},
128 {"checkfilechanges",store_opts, {0}, 0, 0, 1},
129 {"strippath", store_opts, {0}, 0, 0, 0},
130 {"honornodumpflag", store_opts, {0}, 0, 0, 0},
131 {NULL, NULL, {0}, 0, 0, 0}
135 /* Define FileSet KeyWord values */
147 INC_KW_REPLACE, /* restore options */
148 INC_KW_READFIFO, /* Causes fifo data to be read */
164 * This is the list of options that can be stored by store_opts
165 * Note, now that the old style Include/Exclude code is gone,
166 * the INC_KW code could be put into the "code" field of the
167 * options given above.
169 static struct s_kw FS_option_kw[] = {
170 {"compression", INC_KW_COMPRESSION},
171 {"signature", INC_KW_DIGEST},
172 {"encryption", INC_KW_ENCRYPTION},
173 {"verify", INC_KW_VERIFY},
174 {"accurate", INC_KW_ACCURATE},
175 {"onefs", INC_KW_ONEFS},
176 {"recurse", INC_KW_RECURSE},
177 {"sparse", INC_KW_SPARSE},
178 {"hardlinks", INC_KW_HARDLINK},
179 {"replace", INC_KW_REPLACE},
180 {"readfifo", INC_KW_READFIFO},
181 {"portable", INC_KW_PORTABLE},
182 {"mtimeonly", INC_KW_MTIMEONLY},
183 {"keepatime", INC_KW_KEEPATIME},
184 {"exclude", INC_KW_EXCLUDE},
185 {"aclsupport", INC_KW_ACL},
186 {"ignorecase", INC_KW_IGNORECASE},
187 {"hfsplussupport", INC_KW_HFSPLUS},
188 {"noatime", INC_KW_NOATIME},
189 {"enhancedwild", INC_KW_ENHANCEDWILD},
190 {"checkfilechanges", INC_KW_CHKCHANGES},
191 {"strippath", INC_KW_STRIPPATH},
192 {"honornodumpflag", INC_KW_HONOR_NODUMP},
196 /* Options for FileSet keywords */
205 * Options permitted for each keyword and resulting value.
206 * The output goes into opts, which are then transmitted to
207 * the FD for application as options to the following list of
210 static struct s_fs_opt FS_options[] = {
211 {"md5", INC_KW_DIGEST, "M"},
212 {"sha1", INC_KW_DIGEST, "S"},
213 {"sha256", INC_KW_DIGEST, "S2"},
214 {"sha512", INC_KW_DIGEST, "S3"},
215 {"gzip", INC_KW_COMPRESSION, "Z6"},
216 {"gzip1", INC_KW_COMPRESSION, "Z1"},
217 {"gzip2", INC_KW_COMPRESSION, "Z2"},
218 {"gzip3", INC_KW_COMPRESSION, "Z3"},
219 {"gzip4", INC_KW_COMPRESSION, "Z4"},
220 {"gzip5", INC_KW_COMPRESSION, "Z5"},
221 {"gzip6", INC_KW_COMPRESSION, "Z6"},
222 {"gzip7", INC_KW_COMPRESSION, "Z7"},
223 {"gzip8", INC_KW_COMPRESSION, "Z8"},
224 {"gzip9", INC_KW_COMPRESSION, "Z9"},
225 {"blowfish", INC_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
226 {"3des", INC_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
227 {"yes", INC_KW_ONEFS, "0"},
228 {"no", INC_KW_ONEFS, "f"},
229 {"yes", INC_KW_RECURSE, "0"},
230 {"no", INC_KW_RECURSE, "h"},
231 {"yes", INC_KW_SPARSE, "s"},
232 {"no", INC_KW_SPARSE, "0"},
233 {"yes", INC_KW_HARDLINK, "0"},
234 {"no", INC_KW_HARDLINK, "H"},
235 {"always", INC_KW_REPLACE, "a"},
236 {"ifnewer", INC_KW_REPLACE, "w"},
237 {"never", INC_KW_REPLACE, "n"},
238 {"yes", INC_KW_READFIFO, "r"},
239 {"no", INC_KW_READFIFO, "0"},
240 {"yes", INC_KW_PORTABLE, "p"},
241 {"no", INC_KW_PORTABLE, "0"},
242 {"yes", INC_KW_MTIMEONLY, "m"},
243 {"no", INC_KW_MTIMEONLY, "0"},
244 {"yes", INC_KW_KEEPATIME, "k"},
245 {"no", INC_KW_KEEPATIME, "0"},
246 {"yes", INC_KW_EXCLUDE, "e"},
247 {"no", INC_KW_EXCLUDE, "0"},
248 {"yes", INC_KW_ACL, "A"},
249 {"no", INC_KW_ACL, "0"},
250 {"yes", INC_KW_IGNORECASE, "i"},
251 {"no", INC_KW_IGNORECASE, "0"},
252 {"yes", INC_KW_HFSPLUS, "R"}, /* "R" for resource fork */
253 {"no", INC_KW_HFSPLUS, "0"},
254 {"yes", INC_KW_NOATIME, "K"},
255 {"no", INC_KW_NOATIME, "0"},
256 {"yes", INC_KW_ENHANCEDWILD, "K"},
257 {"no", INC_KW_ENHANCEDWILD, "0"},
258 {"yes", INC_KW_CHKCHANGES, "c"},
259 {"no", INC_KW_CHKCHANGES, "0"},
260 {"yes", INC_KW_HONOR_NODUMP, "N"},
261 {"no", INC_KW_HONOR_NODUMP, "0"},
268 * Scan for right hand side of Include options (keyword=option) is
269 * converted into one or two characters. Verifyopts=xxxx is Vxxxx:
270 * Whatever is found is concatenated to the opts string.
271 * This code is also used inside an Options resource.
273 static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen)
277 int lcopts = lc->options;
279 option[0] = 0; /* default option = none */
280 option[2] = 0; /* terminate options */
281 lc->options |= LOPT_STRING; /* force string */
282 token = lex_get_token(lc, T_STRING); /* expect at least one option */
283 if (keyword == INC_KW_VERIFY) { /* special case */
284 /* ***FIXME**** ensure these are in permitted set */
285 bstrncat(opts, "V", optlen); /* indicate Verify */
286 bstrncat(opts, lc->str, optlen);
287 bstrncat(opts, ":", optlen); /* terminate it */
288 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
289 } else if (keyword == INC_KW_ACCURATE) { /* special case */
290 /* ***FIXME**** ensure these are in permitted set */
291 bstrncat(opts, "C", optlen); /* indicate Accurate */
292 bstrncat(opts, lc->str, optlen);
293 bstrncat(opts, ":", optlen); /* terminate it */
294 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
295 } else if (keyword == INC_KW_STRIPPATH) { /* another special case */
296 if (!is_an_integer(lc->str)) {
297 scan_err1(lc, _("Expected a strip path positive integer, got:%s:"), lc->str);
299 bstrncat(opts, "P", optlen); /* indicate strip path */
300 bstrncat(opts, lc->str, optlen);
301 bstrncat(opts, ":", optlen); /* terminate it */
302 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
304 * Standard keyword options for Include/Exclude
307 for (i=0; FS_options[i].name; i++) {
308 if (FS_options[i].keyword == keyword && strcasecmp(lc->str, FS_options[i].name) == 0) {
309 /* NOTE! maximum 2 letters here or increase option[3] */
310 option[0] = FS_options[i].option[0];
311 option[1] = FS_options[i].option[1];
317 scan_err1(lc, _("Expected a FileSet option keyword, got:%s:"), lc->str);
318 } else { /* add option */
319 bstrncat(opts, option, optlen);
320 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
323 lc->options = lcopts;
325 /* If option terminated by comma, eat it */
327 token = lex_get_token(lc, T_ALL); /* yes, eat comma */
333 * Store FileSet Include/Exclude info
334 * new style includes are handled in store_newinc()
336 void store_inc(LEX *lc, RES_ITEM *item, int index, int pass)
341 * Decide if we are doing a new Include or an old include. The
342 * new Include is followed immediately by open brace, whereas the
343 * old include has options following the Include.
345 token = lex_get_token(lc, T_SKIP_EOL);
346 if (token == T_BOB) {
347 store_newinc(lc, item, index, pass);
350 scan_err0(lc, _("Old style Include/Exclude not supported\n"));
355 * Store new style FileSet Include/Exclude info
357 * Note, when this routine is called, we are inside a FileSet
358 * resource. We treat the Include/Execlude like a sort of
359 * mini-resource within the FileSet resource.
361 static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass)
367 if (!res_all.res_fs.have_MD5) {
368 MD5Init(&res_all.res_fs.md5c);
369 res_all.res_fs.have_MD5 = true;
371 memset(&res_incexe, 0, sizeof(INCEXE));
372 res_all.res_fs.new_include = true;
373 while ((token = lex_get_token(lc, T_SKIP_EOL)) != T_EOF) {
374 if (token == T_EOB) {
377 if (token != T_IDENTIFIER) {
378 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
380 for (i=0; newinc_items[i].name; i++) {
381 options = strcasecmp(lc->str, "options") == 0;
382 if (strcasecmp(newinc_items[i].name, lc->str) == 0) {
384 token = lex_get_token(lc, T_SKIP_EOL);
385 if (token != T_EQUALS) {
386 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
389 /* Call item handler */
390 newinc_items[i].handler(lc, &newinc_items[i], i, pass, item->code);
396 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
400 incexe = (INCEXE *)malloc(sizeof(INCEXE));
401 memcpy(incexe, &res_incexe, sizeof(INCEXE));
402 memset(&res_incexe, 0, sizeof(INCEXE));
403 if (item->code == 0) { /* include */
404 if (res_all.res_fs.num_includes == 0) {
405 res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *));
407 res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items,
408 sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1));
410 res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
411 Dmsg1(900, "num_includes=%d\n", res_all.res_fs.num_includes);
412 } else { /* exclude */
413 if (res_all.res_fs.num_excludes == 0) {
414 res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
416 res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items,
417 sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1));
419 res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
420 Dmsg1(900, "num_excludes=%d\n", res_all.res_fs.num_excludes);
424 set_bit(index, res_all.hdr.item_present);
428 /* Store regex info */
429 static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass)
437 token = lex_get_token(lc, T_SKIP_EOL);
439 /* Pickup regex string
443 case T_UNQUOTED_STRING:
444 case T_QUOTED_STRING:
445 rc = regcomp(&preg, lc->str, REG_EXTENDED);
447 regerror(rc, &preg, prbuf, sizeof(prbuf));
449 scan_err1(lc, _("Regex compile error. ERR=%s\n"), prbuf);
453 if (item->code == 1) {
455 res_incexe.current_opts->regexdir.append(bstrdup(lc->str));
456 newsize = res_incexe.current_opts->regexdir.size();
457 } else if (item->code == 2) {
459 res_incexe.current_opts->regexfile.append(bstrdup(lc->str));
460 newsize = res_incexe.current_opts->regexfile.size();
463 res_incexe.current_opts->regex.append(bstrdup(lc->str));
464 newsize = res_incexe.current_opts->regex.size();
466 Dmsg4(900, "set %s %p size=%d %s\n",
467 type, res_incexe.current_opts, newsize, lc->str);
470 scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str);
476 /* Store Base info */
477 static void store_base(LEX *lc, RES_ITEM *item, int index, int pass)
481 token = lex_get_token(lc, T_NAME);
484 * Pickup Base Job Name
486 res_incexe.current_opts->base.append(bstrdup(lc->str));
491 /* Store reader info */
492 static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass)
496 token = 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)
581 scan_err0(lc, _("ExcludeDirContaining directive not permitted in Exclude.\n"));
584 token = lex_get_token(lc, T_NAME);
586 res_incexe.current_opts->ignoredir = bstrdup(lc->str);
591 /* Store drivetype info */
592 static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass)
596 token = lex_get_token(lc, T_SKIP_EOL);
598 /* Pickup drivetype string */
601 case T_UNQUOTED_STRING:
602 case T_QUOTED_STRING:
603 res_incexe.current_opts->drivetype.append(bstrdup(lc->str));
604 Dmsg3(900, "set drivetype %p size=%d %s\n",
605 res_incexe.current_opts, res_incexe.current_opts->drivetype.size(), lc->str);
608 scan_err1(lc, _("Expected an drivetype string, got: %s\n"), lc->str);
615 * Store Filename info. Note, for minor efficiency reasons, we
616 * always increase the name buffer by 10 items because we expect
617 * to add more entries.
619 static void store_fname(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
624 token = lex_get_token(lc, T_SKIP_EOL);
626 /* Pickup Filename string
630 case T_UNQUOTED_STRING:
631 if (strchr(lc->str, '\\')) {
632 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
635 case T_QUOTED_STRING:
636 if (res_all.res_fs.have_MD5) {
637 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
639 incexe = &res_incexe;
640 if (incexe->name_list.size() == 0) {
641 incexe->name_list.init(10, true);
643 incexe->name_list.append(bstrdup(lc->str));
644 Dmsg1(900, "Add to name_list %s\n", lc->str);
647 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
654 * Store Filename info. Note, for minor efficiency reasons, we
655 * always increase the name buffer by 10 items because we expect
656 * to add more entries.
658 static void store_plugin_name(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
664 scan_err0(lc, _("Plugin directive not permitted in Exclude\n"));
667 token = lex_get_token(lc, T_SKIP_EOL);
669 /* Pickup Filename string
673 case T_UNQUOTED_STRING:
674 if (strchr(lc->str, '\\')) {
675 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
678 case T_QUOTED_STRING:
679 if (res_all.res_fs.have_MD5) {
680 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
682 incexe = &res_incexe;
683 if (incexe->plugin_list.size() == 0) {
684 incexe->plugin_list.init(10, true);
686 incexe->plugin_list.append(bstrdup(lc->str));
687 Dmsg1(900, "Add to plugin_list %s\n", lc->str);
690 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
700 * Come here when Options seen in Include/Exclude
702 static void options_res(LEX *lc, RES_ITEM2 *item, int index, int pass, bool exclude)
707 scan_err0(lc, _("Options section not permitted in Exclude\n"));
710 token = lex_get_token(lc, T_SKIP_EOL);
711 if (token != T_BOB) {
712 scan_err1(lc, _("Expecting open brace. Got %s"), lc->str);
716 setup_current_opts();
719 while ((token = lex_get_token(lc, T_ALL)) != T_EOF) {
720 if (token == T_EOL) {
723 if (token == T_EOB) {
726 if (token != T_IDENTIFIER) {
727 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
729 for (i=0; options_items[i].name; i++) {
730 if (strcasecmp(options_items[i].name, lc->str) == 0) {
731 token = lex_get_token(lc, T_SKIP_EOL);
732 if (token != T_EQUALS) {
733 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
735 /* Call item handler */
736 options_items[i].handler(lc, &options_items[i], i, pass);
742 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
749 * New style options come here
751 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass)
758 keyword = INC_KW_NONE;
759 /* Look up the keyword */
760 for (i=0; FS_option_kw[i].name; i++) {
761 if (strcasecmp(item->name, FS_option_kw[i].name) == 0) {
762 keyword = FS_option_kw[i].token;
766 if (keyword == INC_KW_NONE) {
767 scan_err1(lc, _("Expected a FileSet keyword, got: %s"), lc->str);
769 /* Now scan for the value */
770 scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
772 bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
773 Dmsg2(900, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
780 /* If current_opts not defined, create first entry */
781 static void setup_current_opts(void)
783 FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS));
784 memset(fo, 0, sizeof(FOPTS));
785 fo->regex.init(1, true);
786 fo->regexdir.init(1, true);
787 fo->regexfile.init(1, true);
788 fo->wild.init(1, true);
789 fo->wilddir.init(1, true);
790 fo->wildfile.init(1, true);
791 fo->wildbase.init(1, true);
792 fo->base.init(1, true);
793 fo->fstype.init(1, true);
794 fo->drivetype.init(1, true);
795 res_incexe.current_opts = fo;
796 if (res_incexe.num_opts == 0) {
797 res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
799 res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list,
800 sizeof(FOPTS *) * (res_incexe.num_opts + 1));
802 res_incexe.opts_list[res_incexe.num_opts++] = fo;