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_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_ignoredir(LEX *lc, RES_ITEM *item, int index, int pass);
61 static void setup_current_opts(void);
64 /* We build the current resource here as we are
65 * scanning the resource configuration definition,
66 * then move it to allocated memory when the resource
70 extern "C" { // work around visual compiler mangling variables
76 extern int res_all_size;
78 /* We build the current new Include and Exclude items here */
79 static INCEXE res_incexe;
82 * new Include/Exclude items
83 * name handler value code flags default_value
85 static RES_ITEM newinc_items[] = {
86 {"file", store_fname, {0}, 0, 0, 0},
87 {"plugin", store_plugin_name, {0}, 0, 0, 0},
88 {"ignoredir", store_ignoredir, {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 {"ignorecase", store_opts, {0}, 0, 0, 0},
121 {"fstype", store_fstype, {0}, 0, 0, 0},
122 {"hfsplussupport", store_opts, {0}, 0, 0, 0},
123 {"noatime", store_opts, {0}, 0, 0, 0},
124 {"enhancedwild", store_opts, {0}, 0, 0, 0},
125 {"drivetype", store_drivetype, {0}, 0, 0, 0},
126 {"checkfilechanges",store_opts, {0}, 0, 0, 1},
127 {"strippath", store_opts, {0}, 0, 0, 0},
128 {"honornodumpflag", store_opts, {0}, 0, 0, 0},
129 {NULL, NULL, {0}, 0, 0, 0}
133 /* Define FileSet KeyWord values */
145 INC_KW_REPLACE, /* restore options */
146 INC_KW_READFIFO, /* Causes fifo data to be read */
162 * This is the list of options that can be stored by store_opts
163 * Note, now that the old style Include/Exclude code is gone,
164 * the INC_KW code could be put into the "code" field of the
165 * options given above.
167 static struct s_kw FS_option_kw[] = {
168 {"compression", INC_KW_COMPRESSION},
169 {"signature", INC_KW_DIGEST},
170 {"encryption", INC_KW_ENCRYPTION},
171 {"verify", INC_KW_VERIFY},
172 {"accurate", INC_KW_ACCURATE},
173 {"onefs", INC_KW_ONEFS},
174 {"recurse", INC_KW_RECURSE},
175 {"sparse", INC_KW_SPARSE},
176 {"hardlinks", INC_KW_HARDLINK},
177 {"replace", INC_KW_REPLACE},
178 {"readfifo", INC_KW_READFIFO},
179 {"portable", INC_KW_PORTABLE},
180 {"mtimeonly", INC_KW_MTIMEONLY},
181 {"keepatime", INC_KW_KEEPATIME},
182 {"exclude", INC_KW_EXCLUDE},
183 {"aclsupport", INC_KW_ACL},
184 {"ignorecase", INC_KW_IGNORECASE},
185 {"hfsplussupport", INC_KW_HFSPLUS},
186 {"noatime", INC_KW_NOATIME},
187 {"enhancedwild", INC_KW_ENHANCEDWILD},
188 {"checkfilechanges", INC_KW_CHKCHANGES},
189 {"strippath", INC_KW_STRIPPATH},
190 {"honornodumpflag", INC_KW_HONOR_NODUMP},
194 /* Options for FileSet keywords */
203 * Options permitted for each keyword and resulting value.
204 * The output goes into opts, which are then transmitted to
205 * the FD for application as options to the following list of
208 static struct s_fs_opt FS_options[] = {
209 {"md5", INC_KW_DIGEST, "M"},
210 {"sha1", INC_KW_DIGEST, "S"},
211 {"sha256", INC_KW_DIGEST, "S2"},
212 {"sha512", INC_KW_DIGEST, "S3"},
213 {"gzip", INC_KW_COMPRESSION, "Z6"},
214 {"gzip1", INC_KW_COMPRESSION, "Z1"},
215 {"gzip2", INC_KW_COMPRESSION, "Z2"},
216 {"gzip3", INC_KW_COMPRESSION, "Z3"},
217 {"gzip4", INC_KW_COMPRESSION, "Z4"},
218 {"gzip5", INC_KW_COMPRESSION, "Z5"},
219 {"gzip6", INC_KW_COMPRESSION, "Z6"},
220 {"gzip7", INC_KW_COMPRESSION, "Z7"},
221 {"gzip8", INC_KW_COMPRESSION, "Z8"},
222 {"gzip9", INC_KW_COMPRESSION, "Z9"},
223 {"blowfish", INC_KW_ENCRYPTION, "B"}, /* ***FIXME*** not implemented */
224 {"3des", INC_KW_ENCRYPTION, "3"}, /* ***FIXME*** not implemented */
225 {"yes", INC_KW_ONEFS, "0"},
226 {"no", INC_KW_ONEFS, "f"},
227 {"yes", INC_KW_RECURSE, "0"},
228 {"no", INC_KW_RECURSE, "h"},
229 {"yes", INC_KW_SPARSE, "s"},
230 {"no", INC_KW_SPARSE, "0"},
231 {"yes", INC_KW_HARDLINK, "0"},
232 {"no", INC_KW_HARDLINK, "H"},
233 {"always", INC_KW_REPLACE, "a"},
234 {"ifnewer", INC_KW_REPLACE, "w"},
235 {"never", INC_KW_REPLACE, "n"},
236 {"yes", INC_KW_READFIFO, "r"},
237 {"no", INC_KW_READFIFO, "0"},
238 {"yes", INC_KW_PORTABLE, "p"},
239 {"no", INC_KW_PORTABLE, "0"},
240 {"yes", INC_KW_MTIMEONLY, "m"},
241 {"no", INC_KW_MTIMEONLY, "0"},
242 {"yes", INC_KW_KEEPATIME, "k"},
243 {"no", INC_KW_KEEPATIME, "0"},
244 {"yes", INC_KW_EXCLUDE, "e"},
245 {"no", INC_KW_EXCLUDE, "0"},
246 {"yes", INC_KW_ACL, "A"},
247 {"no", INC_KW_ACL, "0"},
248 {"yes", INC_KW_IGNORECASE, "i"},
249 {"no", INC_KW_IGNORECASE, "0"},
250 {"yes", INC_KW_HFSPLUS, "R"}, /* "R" for resource fork */
251 {"no", INC_KW_HFSPLUS, "0"},
252 {"yes", INC_KW_NOATIME, "K"},
253 {"no", INC_KW_NOATIME, "0"},
254 {"yes", INC_KW_ENHANCEDWILD, "K"},
255 {"no", INC_KW_ENHANCEDWILD, "0"},
256 {"yes", INC_KW_CHKCHANGES, "c"},
257 {"no", INC_KW_CHKCHANGES, "0"},
258 {"yes", INC_KW_HONOR_NODUMP, "N"},
259 {"no", INC_KW_HONOR_NODUMP, "0"},
266 * Scan for right hand side of Include options (keyword=option) is
267 * converted into one or two characters. Verifyopts=xxxx is Vxxxx:
268 * Whatever is found is concatenated to the opts string.
269 * This code is also used inside an Options resource.
271 static void scan_include_options(LEX *lc, int keyword, char *opts, int optlen)
275 int lcopts = lc->options;
277 option[0] = 0; /* default option = none */
278 option[2] = 0; /* terminate options */
279 lc->options |= LOPT_STRING; /* force string */
280 token = lex_get_token(lc, T_STRING); /* expect at least one option */
281 if (keyword == INC_KW_VERIFY) { /* special case */
282 /* ***FIXME**** ensure these are in permitted set */
283 bstrncat(opts, "V", optlen); /* indicate Verify */
284 bstrncat(opts, lc->str, optlen);
285 bstrncat(opts, ":", optlen); /* terminate it */
286 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
287 } else if (keyword == INC_KW_ACCURATE) { /* special case */
288 /* ***FIXME**** ensure these are in permitted set */
289 bstrncat(opts, "C", optlen); /* indicate Accurate */
290 bstrncat(opts, lc->str, optlen);
291 bstrncat(opts, ":", optlen); /* terminate it */
292 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
293 } else if (keyword == INC_KW_STRIPPATH) { /* another special case */
294 if (!is_an_integer(lc->str)) {
295 scan_err1(lc, _("Expected a strip path positive integer, got:%s:"), lc->str);
297 bstrncat(opts, "P", optlen); /* indicate strip path */
298 bstrncat(opts, lc->str, optlen);
299 bstrncat(opts, ":", optlen); /* terminate it */
300 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
302 * Standard keyword options for Include/Exclude
305 for (i=0; FS_options[i].name; i++) {
306 if (FS_options[i].keyword == keyword && strcasecmp(lc->str, FS_options[i].name) == 0) {
307 /* NOTE! maximum 2 letters here or increase option[3] */
308 option[0] = FS_options[i].option[0];
309 option[1] = FS_options[i].option[1];
315 scan_err1(lc, _("Expected a FileSet option keyword, got:%s:"), lc->str);
316 } else { /* add option */
317 bstrncat(opts, option, optlen);
318 Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
321 lc->options = lcopts;
323 /* If option terminated by comma, eat it */
325 token = lex_get_token(lc, T_ALL); /* yes, eat comma */
331 * Store FileSet Include/Exclude info
332 * NEW style includes are handled in store_newinc()
334 void store_inc(LEX *lc, RES_ITEM *item, int index, int pass)
339 * Decide if we are doing a new Include or an old include. The
340 * new Include is followed immediately by open brace, whereas the
341 * old include has options following the Include.
343 token = lex_get_token(lc, T_SKIP_EOL);
344 if (token == T_BOB) {
345 store_newinc(lc, item, index, pass);
348 scan_err0(lc, _("Old style Include/Exclude not supported\n"));
353 * Store NEW style FileSet FInclude/FExclude info
355 * Note, when this routine is called, we are inside a FileSet
356 * resource. We treat the Include/Execlude like a sort of
357 * mini-resource within the FileSet resource.
359 static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass)
365 if (!res_all.res_fs.have_MD5) {
366 MD5Init(&res_all.res_fs.md5c);
367 res_all.res_fs.have_MD5 = true;
369 memset(&res_incexe, 0, sizeof(INCEXE));
370 res_all.res_fs.new_include = true;
371 while ((token = lex_get_token(lc, T_SKIP_EOL)) != T_EOF) {
372 if (token == T_EOB) {
375 if (token != T_IDENTIFIER) {
376 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
378 for (i=0; newinc_items[i].name; i++) {
379 options = strcasecmp(lc->str, "options") == 0;
380 if (strcasecmp(newinc_items[i].name, lc->str) == 0) {
382 token = lex_get_token(lc, T_SKIP_EOL);
383 if (token != T_EQUALS) {
384 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
387 /* Call item handler */
388 newinc_items[i].handler(lc, &newinc_items[i], i, pass);
394 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
398 incexe = (INCEXE *)malloc(sizeof(INCEXE));
399 memcpy(incexe, &res_incexe, sizeof(INCEXE));
400 memset(&res_incexe, 0, sizeof(INCEXE));
401 if (item->code == 0) { /* include */
402 if (res_all.res_fs.num_includes == 0) {
403 res_all.res_fs.include_items = (INCEXE **)malloc(sizeof(INCEXE *));
405 res_all.res_fs.include_items = (INCEXE **)realloc(res_all.res_fs.include_items,
406 sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1));
408 res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
409 Dmsg1(900, "num_includes=%d\n", res_all.res_fs.num_includes);
410 } else { /* exclude */
411 if (res_all.res_fs.num_excludes == 0) {
412 res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
414 res_all.res_fs.exclude_items = (INCEXE **)realloc(res_all.res_fs.exclude_items,
415 sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1));
417 res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
418 Dmsg1(900, "num_excludes=%d\n", res_all.res_fs.num_excludes);
422 set_bit(index, res_all.hdr.item_present);
426 /* Store regex info */
427 static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass)
435 token = lex_get_token(lc, T_SKIP_EOL);
437 /* Pickup regex string
441 case T_UNQUOTED_STRING:
442 case T_QUOTED_STRING:
443 rc = regcomp(&preg, lc->str, REG_EXTENDED);
445 regerror(rc, &preg, prbuf, sizeof(prbuf));
447 scan_err1(lc, _("Regex compile error. ERR=%s\n"), prbuf);
451 if (item->code == 1) {
453 res_incexe.current_opts->regexdir.append(bstrdup(lc->str));
454 newsize = res_incexe.current_opts->regexdir.size();
455 } else if (item->code == 2) {
457 res_incexe.current_opts->regexfile.append(bstrdup(lc->str));
458 newsize = res_incexe.current_opts->regexfile.size();
461 res_incexe.current_opts->regex.append(bstrdup(lc->str));
462 newsize = res_incexe.current_opts->regex.size();
464 Dmsg4(900, "set %s %p size=%d %s\n",
465 type, res_incexe.current_opts, newsize, lc->str);
468 scan_err1(lc, _("Expected a regex string, got: %s\n"), lc->str);
474 /* Store Base info */
475 static void store_base(LEX *lc, RES_ITEM *item, int index, int pass)
479 token = lex_get_token(lc, T_NAME);
482 * Pickup Base Job Name
484 res_incexe.current_opts->base.append(bstrdup(lc->str));
489 /* Store reader info */
490 static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass)
494 token = lex_get_token(lc, T_NAME);
497 * Pickup plugin command
499 res_incexe.current_opts->plugin = bstrdup(lc->str);
505 /* Store Wild-card info */
506 static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
512 token = lex_get_token(lc, T_SKIP_EOL);
515 * Pickup Wild-card string
519 case T_UNQUOTED_STRING:
520 case T_QUOTED_STRING:
521 if (item->code == 1) {
523 res_incexe.current_opts->wilddir.append(bstrdup(lc->str));
524 newsize = res_incexe.current_opts->wilddir.size();
525 } else if (item->code == 2) {
526 if (strpbrk(lc->str, "/\\") != NULL) {
528 res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
529 newsize = res_incexe.current_opts->wildfile.size();
532 res_incexe.current_opts->wildbase.append(bstrdup(lc->str));
533 newsize = res_incexe.current_opts->wildbase.size();
537 res_incexe.current_opts->wild.append(bstrdup(lc->str));
538 newsize = res_incexe.current_opts->wild.size();
540 Dmsg4(9, "set %s %p size=%d %s\n",
541 type, res_incexe.current_opts, newsize, lc->str);
544 scan_err1(lc, _("Expected a wild-card string, got: %s\n"), lc->str);
550 /* Store fstype info */
551 static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass)
555 token = lex_get_token(lc, T_SKIP_EOL);
557 /* Pickup fstype string */
560 case T_UNQUOTED_STRING:
561 case T_QUOTED_STRING:
562 res_incexe.current_opts->fstype.append(bstrdup(lc->str));
563 Dmsg3(900, "set fstype %p size=%d %s\n",
564 res_incexe.current_opts, res_incexe.current_opts->fstype.size(), lc->str);
567 scan_err1(lc, _("Expected an fstype string, got: %s\n"), lc->str);
573 /* Store ignoredir info */
574 static void store_ignoredir(LEX *lc, RES_ITEM *item, int index, int pass)
578 token = lex_get_token(lc, T_NAME);
581 * Pickup reader command
583 res_incexe.current_opts->ignoredir = bstrdup(lc->str);
588 /* Store drivetype info */
589 static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass)
593 token = lex_get_token(lc, T_SKIP_EOL);
595 /* Pickup drivetype string */
598 case T_UNQUOTED_STRING:
599 case T_QUOTED_STRING:
600 res_incexe.current_opts->drivetype.append(bstrdup(lc->str));
601 Dmsg3(900, "set drivetype %p size=%d %s\n",
602 res_incexe.current_opts, res_incexe.current_opts->drivetype.size(), lc->str);
605 scan_err1(lc, _("Expected an drivetype string, got: %s\n"), lc->str);
612 * Store Filename info. Note, for minor efficiency reasons, we
613 * always increase the name buffer by 10 items because we expect
614 * to add more entries.
616 static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass)
621 token = lex_get_token(lc, T_SKIP_EOL);
623 /* Pickup Filename string
627 case T_UNQUOTED_STRING:
628 if (strchr(lc->str, '\\')) {
629 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
632 case T_QUOTED_STRING:
633 if (res_all.res_fs.have_MD5) {
634 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
636 incexe = &res_incexe;
637 if (incexe->name_list.size() == 0) {
638 incexe->name_list.init(10, true);
640 incexe->name_list.append(bstrdup(lc->str));
641 Dmsg1(900, "Add to name_list %s\n", lc->str);
644 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
651 * Store Filename info. Note, for minor efficiency reasons, we
652 * always increase the name buffer by 10 items because we expect
653 * to add more entries.
655 static void store_plugin_name(LEX *lc, RES_ITEM *item, int index, int pass)
660 token = lex_get_token(lc, T_SKIP_EOL);
662 /* Pickup Filename string
666 case T_UNQUOTED_STRING:
667 if (strchr(lc->str, '\\')) {
668 scan_err1(lc, _("Backslash found. Use forward slashes or quote the string.: %s\n"), lc->str);
671 case T_QUOTED_STRING:
672 if (res_all.res_fs.have_MD5) {
673 MD5Update(&res_all.res_fs.md5c, (unsigned char *)lc->str, lc->str_len);
675 incexe = &res_incexe;
676 if (incexe->plugin_list.size() == 0) {
677 incexe->plugin_list.init(10, true);
679 incexe->plugin_list.append(bstrdup(lc->str));
680 Dmsg1(900, "Add to plugin_list %s\n", lc->str);
683 scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
692 * Come here when Options seen in Include/Exclude
694 static void options_res(LEX *lc, RES_ITEM *item, int index, int pass)
698 token = lex_get_token(lc, T_SKIP_EOL);
699 if (token != T_BOB) {
700 scan_err1(lc, _("Expecting open brace. Got %s"), lc->str);
704 setup_current_opts();
707 while ((token = lex_get_token(lc, T_ALL)) != T_EOF) {
708 if (token == T_EOL) {
711 if (token == T_EOB) {
714 if (token != T_IDENTIFIER) {
715 scan_err1(lc, _("Expecting keyword, got: %s\n"), lc->str);
717 for (i=0; options_items[i].name; i++) {
718 if (strcasecmp(options_items[i].name, lc->str) == 0) {
719 token = lex_get_token(lc, T_SKIP_EOL);
720 if (token != T_EQUALS) {
721 scan_err1(lc, _("expected an equals, got: %s"), lc->str);
723 /* Call item handler */
724 options_items[i].handler(lc, &options_items[i], i, pass);
730 scan_err1(lc, _("Keyword %s not permitted in this resource"), lc->str);
737 * New style options come here
739 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass)
746 keyword = INC_KW_NONE;
747 /* Look up the keyword */
748 for (i=0; FS_option_kw[i].name; i++) {
749 if (strcasecmp(item->name, FS_option_kw[i].name) == 0) {
750 keyword = FS_option_kw[i].token;
754 if (keyword == INC_KW_NONE) {
755 scan_err1(lc, _("Expected a FileSet keyword, got: %s"), lc->str);
757 /* Now scan for the value */
758 scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
760 bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
761 Dmsg2(900, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
768 /* If current_opts not defined, create first entry */
769 static void setup_current_opts(void)
771 FOPTS *fo = (FOPTS *)malloc(sizeof(FOPTS));
772 memset(fo, 0, sizeof(FOPTS));
773 fo->regex.init(1, true);
774 fo->regexdir.init(1, true);
775 fo->regexfile.init(1, true);
776 fo->wild.init(1, true);
777 fo->wilddir.init(1, true);
778 fo->wildfile.init(1, true);
779 fo->wildbase.init(1, true);
780 fo->base.init(1, true);
781 fo->fstype.init(1, true);
782 fo->drivetype.init(1, true);
783 res_incexe.current_opts = fo;
784 if (res_incexe.num_opts == 0) {
785 res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
787 res_incexe.opts_list = (FOPTS **)realloc(res_incexe.opts_list,
788 sizeof(FOPTS *) * (res_incexe.num_opts + 1));
790 res_incexe.opts_list[res_incexe.num_opts++] = fo;