]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/inc_conf.c
More FileSet changes
[bacula/bacula] / bacula / src / dird / inc_conf.c
index 9d09e1a535b3a096051d32e5eb3ce56270cf0cbb..ff76230b9c67792dbf925331eb8d8bcccf32ea8a 100644 (file)
@@ -7,7 +7,7 @@
  *     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);
 
 
@@ -54,9 +56,18 @@ static INCEXE res_incexe;
 
 /* 
  * 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},
@@ -66,29 +77,35 @@ static struct res_items newinc_items[] = {
    {"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[] = {
@@ -104,6 +121,7 @@ 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}
 };
 
@@ -153,6 +171,8 @@ static struct s_fs_opt FS_options[] = {
    {"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}
 };
 
@@ -162,6 +182,7 @@ static struct s_fs_opt FS_options[] = {
  * 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)
 {
@@ -205,8 +226,11 @@ 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;
@@ -216,7 +240,7 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass)
 
    /*
     * 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);           
@@ -335,20 +359,21 @@ void store_inc(LEX *lc, struct res_items *item, int index, int pass)
 /*
  * 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;
@@ -360,10 +385,13 @@ static void store_newinc(LEX *lc, struct res_items *item, int index, int pass)
          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);
@@ -404,24 +432,25 @@ static void store_newinc(LEX *lc, struct res_items *item, int index, int 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);         
@@ -430,28 +459,57 @@ static void store_match(LEX *lc, struct res_items *item, int index, int pass)
 }
 
 /* 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;
@@ -483,10 +541,56 @@ static void store_fname(LEX *lc, struct res_items *item, int index, int pass)
    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;
@@ -507,8 +611,7 @@ static void store_opts(LEX *lc, struct res_items *item, int index, int pass)
    /* 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);
@@ -519,13 +622,17 @@ static void store_opts(LEX *lc, struct res_items *item, int index, int pass)
 /* 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;
 }