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 John Walker.
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_fname(LEX *lc, RES_ITEM *item, int index, int pass);
56 static void store_plugin_name(LEX *lc, RES_ITEM *item, int index, int pass);
57 static void options_res(LEX *lc, RES_ITEM *item, int index, int pass);
58 static void store_base(LEX *lc, RES_ITEM *item, int index, int pass);
59 static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass);
60 static void store_reader(LEX *lc, RES_ITEM *item, int index, int pass);
61 static void store_writer(LEX *lc, RES_ITEM *item, int index, int pass);
62 static void setup_current_opts(void);
65 /* We build the current resource here as we are
66 * scanning the resource configuration definition,
67 * then move it to allocated memory when the resource
71 extern "C" { // work around visual compiler mangling variables
77 extern int res_all_size;
79 /* We build the current new Include and Exclude items here */
80 static INCEXE res_incexe;
83 * new Include/Exclude items
84 * name handler value code flags default_value
86 static RES_ITEM newinc_items[] = {
87 {"file", store_fname, {0}, 0, 0, 0},
88 {"plugin", store_plugin_name, {0}, 0, 0, 0},
89 {"options", options_res, {0}, 0, 0, 0},
90 {NULL, NULL, {0}, 0, 0, 0}
94 * Items that are valid in an Options resource
96 static RES_ITEM options_items[] = {
97 {"compression", store_opts, {0}, 0, 0, 0},
98 {"signature", store_opts, {0}, 0, 0, 0},
99 {"accurate", store_opts, {0}, 0, 0, 0},
100 {"verify", store_opts, {0}, 0, 0, 0},
101 {"onefs", store_opts, {0}, 0, 0, 0},
102 {"recurse", store_opts, {0}, 0, 0, 0},
103 {"sparse", store_opts, {0}, 0, 0, 0},
104 {"hardlinks", store_opts, {0}, 0, 0, 0},
105 {"readfifo", store_opts, {0}, 0, 0, 0},
106 {"replace", store_opts, {0}, 0, 0, 0},
107 {"portable", store_opts, {0}, 0, 0, 0},
108 {"mtimeonly", store_opts, {0}, 0, 0, 0},
109 {"keepatime", store_opts, {0}, 0, 0, 0},
110 {"regex", store_regex, {0}, 0, 0, 0},
111 {"regexdir", store_regex, {0}, 1, 0, 0},
112 {"regexfile", store_regex, {0}, 2, 0, 0},
113 {"base", store_base, {0}, 0, 0, 0},
114 {"wild", store_wild, {0}, 0, 0, 0},
115 {"wilddir", store_wild, {0}, 1, 0, 0},
116 {"wildfile", store_wild, {0}, 2, 0, 0},
117 {"exclude", store_opts, {0}, 0, 0, 0},
118 {"aclsupport", store_opts, {0}, 0, 0, 0},
119 {"plugin", store_plugin, {0}, 0, 0, 0},
120 {"reader", store_reader, {0}, 0, 0, 0},
121 {"writer", store_writer, {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, 0},
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 FInclude/FExclude 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);
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 reader info */
508 static void store_reader(LEX *lc, RES_ITEM *item, int index, int pass)
512 token = lex_get_token(lc, T_NAME);
515 * Pickup reader command
517 res_incexe.current_opts->reader = bstrdup(lc->str);
522 /* Store writer innfo */
523 static void store_writer(LEX *lc, RES_ITEM *item, int index, int pass)
527 token = lex_get_token(lc, T_NAME);
530 * Pickup writer command
532 res_incexe.current_opts->writer = bstrdup(lc->str);
539 /* Store Wild-card info */
540 static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
546 token = lex_get_token(lc, T_SKIP_EOL);
549 * Pickup Wild-card string
553 case T_UNQUOTED_STRING:
554 case T_QUOTED_STRING:
555 if (item->code == 1) {
557 res_incexe.current_opts->wilddir.append(bstrdup(lc->str));
558 newsize = res_incexe.current_opts->wilddir.size();
559 } else if (item->code == 2) {
560 if (strpbrk(lc->str, "/\\") != NULL) {
562 res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
563 newsize = res_incexe.current_opts->wildfile.size();
566 res_incexe.current_opts->wildbase.append(bstrdup(lc->str));
567 newsize = res_incexe.current_opts->wildbase.size();
571 res_incexe.current_opts->wild.append(bstrdup(lc->str));
572 newsize = res_incexe.current_opts->wild.size();
574 Dmsg4(9, "set %s %p size=%d %s\n",
575 type, res_incexe.current_opts, newsize, lc->str);
578 scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str);
584 /* Store fstype info */
585 static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass)
589 token = lex_get_token(lc, T_SKIP_EOL);
591 /* Pickup fstype string */
594 case T_UNQUOTED_STRING:
595 case T_QUOTED_STRING:
596 res_incexe.current_opts->fstype.append(bstrdup(lc->str));
597 Dmsg3(900, "set fstype %p size=%d %s\n",
598 res_incexe.current_opts, res_incexe.current_opts->fstype.size(), lc->str);
601 scan_err1(lc, _("Expected an fstype string, got: %s\n"), lc->str);
607 /* Store drivetype info */
608 static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass)
612 token = lex_get_token(lc, T_SKIP_EOL);
614 /* Pickup drivetype string */
617 case T_UNQUOTED_STRING:
618 case T_QUOTED_STRING:
619 res_incexe.current_opts->drivetype.append(bstrdup(lc->str));
620 Dmsg3(900, "set drivetype %p size=%d %s\n",
621 res_incexe.current_opts, res_incexe.current_opts->drivetype.size(), lc->str);
624 scan_err1(lc, _("Expected an drivetype string, got: %s\n"), lc->str);
631 * Store Filename info. Note, for minor efficiency reasons, we
632 * always increase the name buffer by 10 items because we expect
633 * to add more entries.
635 static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass)
640 token = lex_get_token(lc, T_SKIP_EOL);
642 /* Pickup Filename string
646 case T_UNQUOTED_STRING:
647 if (strchr(lc->str, '\\')) {
648 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
651 case T_QUOTED_STRING:
652 if (res_all.res_fs.have_MD5) {
653 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
655 incexe = &res_incexe;
656 if (incexe->name_list.size() == 0) {
657 incexe->name_list.init(10, true);
659 incexe->name_list.append(bstrdup(lc->str));
660 Dmsg1(900, "Add to name_list %s\n", lc->str);
663 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
670 * Store Filename info. Note, for minor efficiency reasons, we
671 * always increase the name buffer by 10 items because we expect
672 * to add more entries.
674 static void store_plugin_name(LEX *lc, RES_ITEM *item, int index, int pass)
679 token = lex_get_token(lc, T_SKIP_EOL);
681 /* Pickup Filename string
685 case T_UNQUOTED_STRING:
686 if (strchr(lc->str, '\\')) {
687 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
690 case T_QUOTED_STRING:
691 if (res_all.res_fs.have_MD5) {
692 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
694 incexe = &res_incexe;
695 if (incexe->plugin_list.size() == 0) {
696 incexe->plugin_list.init(10, true);
698 incexe->plugin_list.append(bstrdup(lc->str));
699 Dmsg1(900, "Add to plugin_list %s\n", lc->str);
702 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
711 * Come here when Options seen in Include/Exclude
713 static void options_res(LEX *lc, RES_ITEM *item, int index, int pass)
717 token = lex_get_token(lc, T_SKIP_EOL);
718 if (token != T_BOB) {
719 scan_err1(lc, _("Expecting open brace. Got %s"), lc->str);
723 setup_current_opts();
726 while ((token = lex_get_token(lc, T_ALL)) != T_EOF) {
727 if (token == T_EOL) {
730 if (token == T_EOB) {
733 if (token != T_IDENTIFIER) {
734 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
736 for (i=0; options_items[i].name; i++) {
737 if (strcasecmp(options_items[i].name, lc->str) == 0) {
738 token = lex_get_token(lc, T_SKIP_EOL);
739 if (token != T_EQUALS) {
740 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
742 /* Call item handler */
743 options_items[i].handler(lc, &options_items[i], i, pass);
749 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
756 * New style options come here
758 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass)
765 keyword = INC_KW_NONE;
766 /* Look up the keyword */
767 for (i=0; FS_option_kw[i].name; i++) {
768 if (strcasecmp(item->name, FS_option_kw[i].name) == 0) {
769 keyword = FS_option_kw[i].token;
773 if (keyword == INC_KW_NONE) {
774 scan_err1(lc, _("Expected a FileSet keyword, got: %s"), lc->str);
776 /* Now scan for the value */
777 scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
779 bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
780 Dmsg2(900, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
787 /* If current_opts not defined, create first entry */
788 static void setup_current_opts(void)
790 FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS));
791 memset(fo, 0, sizeof(FOPTS));
792 fo->regex.init(1, true);
793 fo->regexdir.init(1, true);
794 fo->regexfile.init(1, true);
795 fo->wild.init(1, true);
796 fo->wilddir.init(1, true);
797 fo->wildfile.init(1, true);
798 fo->wildbase.init(1, true);
799 fo->base.init(1, true);
800 fo->fstype.init(1, true);
801 fo->drivetype.init(1, true);
802 res_incexe.current_opts = fo;
803 if (res_incexe.num_opts == 0) {
804 res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
806 res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list,
807 sizeof(FOPTS *) * (res_incexe.num_opts + 1));
809 res_incexe.opts_list[res_incexe.num_opts++] = fo;