]> git.sur5r.net Git - bacula/bacula/commitdiff
Add new files
authorKern Sibbald <kern@sibbald.com>
Sat, 21 Jun 2003 15:45:52 +0000 (15:45 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 21 Jun 2003 15:45:52 +0000 (15:45 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@600 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/dird/expand.c [new file with mode: 0644]

diff --git a/bacula/src/dird/expand.c b/bacula/src/dird/expand.c
new file mode 100644 (file)
index 0000000..6f327cd
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ *
+ *   Bacula Director -- expand.c -- does variable expansion
+ *    in particular for the LabelFormat specification.
+ *
+ *     Kern Sibbald, June MMIII
+ *
+ *   Version $Id$
+ */
+/*
+   Copyright (C) 2000-2003 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
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "dird.h"
+
+
+
+static int date_item(JCR *jcr, int code, 
+             const char **val_ptr, int *val_len, int *val_size)
+{
+   struct tm tm;
+   time_t now = time(NULL);
+   localtime_r(&now, &tm);
+   int val = 0;
+   char buf[10];
+
+   switch (code) {
+   case 1:                           /* year */
+      val = tm.tm_year + 1900;
+      break;
+   case 2:                           /* month */
+      val = tm.tm_mon + 1;
+      break;
+   case 3:                           /* day */
+      val = tm.tm_mday;
+      break;
+   case 4:                           /* hour */
+      val = tm.tm_hour;
+      break;
+   case 5:                           /* minute */
+      val = tm.tm_min;
+      break;
+   case 6:                           /* second */
+      val = tm.tm_sec;
+      break;
+   case 7:                           /* Week day */
+      val = tm.tm_wday;
+      break;
+   }
+   bsnprintf(buf, sizeof(buf), "%d", val);
+   *val_ptr = bstrdup(buf);
+   *val_len = strlen(buf);
+   *val_size = *val_len;
+   return 1;
+}
+
+static int job_item(JCR *jcr, int code, 
+             const char **val_ptr, int *val_len, int *val_size)
+{
+   char *str = " ";
+   char buf[20];
+
+   switch (code) {
+   case 1:                           /* Job */
+      str = jcr->job->hdr.name;
+      break;
+   case 2:                            /* Director's name */
+      str = my_name;
+      break;
+   case 3:                           /* level */
+      str = job_level_to_str(jcr->JobLevel);
+      break;
+   case 4:                           /* type */
+      str = job_type_to_str(jcr->JobType);
+      break;
+   case 5:                           /* JobId */
+      bsnprintf(buf, sizeof(buf), "%d", jcr->JobId);
+      str = buf;
+      break;
+   case 6:                           /* Client */
+      str = jcr->client->hdr.name;
+      if (!str) {
+         str = " ";
+      }
+      break;
+   case 7:                           /* NumVols */
+      bsnprintf(buf, sizeof(buf), "%d", jcr->NumVols);
+      str = buf;
+      break;
+   case 8:                           /* Pool */
+      str = jcr->pool->hdr.name;   
+      break;
+   case 9:                           /* Storage */
+      str = jcr->store->hdr.name;
+      break;
+   case 10:                          /* Catalog */
+      str = jcr->catalog->hdr.name;
+      break;
+   case 11:                          /* MediaType */
+      str = jcr->store->media_type;
+      break;
+   case 12:                          /* JobName */
+      str = jcr->Job;
+      break;
+   }
+   *val_ptr = bstrdup(str);
+   *val_len = strlen(str);
+   *val_size = *val_len;
+   return 1;
+}
+
+
+struct s_built_in_vars {char *var_name; int code; int (*func)(JCR *jcr, int code,
+                        const char **val_ptr, int *val_len, int *val_size);};
+
+static struct s_built_in_vars built_in_vars[] = {
+   { N_("Year"),       1, date_item},
+   { N_("Month"),      2, date_item},
+   { N_("Day"),        3, date_item},
+   { N_("Hour"),       4, date_item},
+   { N_("Minute"),     5, date_item},
+   { N_("Second"),     6, date_item},
+   { N_("WeekDay"),    7, date_item},
+
+   { N_("Job"),        1, job_item},
+   { N_("Dir"),        2, job_item},
+   { N_("Level"),      3, job_item},
+   { N_("Type"),       4, job_item},
+   { N_("JobId"),      5, job_item},
+   { N_("Client"),     6, job_item},
+   { N_("NumVols"),    7, job_item},
+   { N_("Pool"),       8, job_item},
+   { N_("Storage"),    9, job_item},
+   { N_("Catalog"),   10, job_item},
+   { N_("MediaType"), 11, job_item},
+   { N_("JobName"),   12, job_item},
+
+   { NULL, 0, NULL}
+};
+
+
+static var_rc_t lookup_built_in_var(var_t *ctx, void *my_ctx, 
+         const char *var_ptr, int var_len, int var_index, 
+         const char **val_ptr, int *val_len, int *val_size)
+{
+   JCR *jcr = (JCR *)my_ctx;
+   int stat;
+
+   for (int i=0; _(built_in_vars[i].var_name); i++) {
+      if (strncmp(_(built_in_vars[i].var_name), var_ptr, var_len) == 0) {
+        stat = (*built_in_vars[i].func)(jcr, built_in_vars[i].code,
+           val_ptr, val_len, val_size);
+        if (stat) {
+           return VAR_OK;
+        }
+        break;
+      }
+   }
+   return VAR_ERR_UNDEFINED_VARIABLE;
+}
+
+
+/*
+ * Search counter variables 
+ */
+static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, 
+         const char *var_ptr, int var_len, int var_inc, int var_index, 
+         const char **val_ptr, int *val_len, int *val_size)
+{
+   char buf[MAXSTRING];
+   var_rc_t stat = VAR_ERR_UNDEFINED_VARIABLE;
+
+   if (var_len > (int)sizeof(buf) - 1) {
+       return VAR_ERR_OUT_OF_MEMORY;
+   }
+   memcpy(buf, var_ptr, var_len);
+   buf[var_len] = 0;
+   LockRes();
+   for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
+      if (strcmp(counter->hdr.name, buf) == 0) {
+         bsnprintf(buf, sizeof(buf), "%d", counter->CurrentValue);
+        *val_ptr = bstrdup(buf);
+        *val_len = strlen(buf);
+        *val_size = *val_len;
+        if (var_inc) {
+           COUNTER_DBR cr;
+           JCR *jcr = (JCR *)my_ctx;
+           memset(&cr, 0, sizeof(cr));
+           bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter));
+           cr.MinValue = counter->MinValue;
+           cr.MaxValue = counter->MaxValue;
+           if (counter->CurrentValue == counter->MaxValue) {
+              counter->CurrentValue = counter->MinValue;
+           } else {
+              counter->CurrentValue++;
+           }
+           cr.CurrentValue = counter->CurrentValue;
+           bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter));
+           if (!db_update_counter_record(jcr, jcr->db, &cr)) {
+               Jmsg(jcr, M_ERROR, 0, _("Count not update counter %s: ERR=%s\n"),
+                 counter->hdr.name, db_strerror(jcr->db));
+           }
+        }  
+        stat = VAR_OK;
+        break;
+      }
+   }
+   UnlockRes();
+   return stat;
+}
+
+
+/*
+ * Called here to look up a variable   
+ */
+static var_rc_t lookup_var(var_t *ctx, void *my_ctx, 
+         const char *var_ptr, int var_len, int var_inc, int var_index, 
+         const char **val_ptr, int *val_len, int *val_size)
+{
+   char buf[MAXSTRING], *val, *p, *v;
+   var_rc_t stat;
+   int count;
+
+   if ((stat = lookup_built_in_var(ctx, my_ctx, var_ptr, var_len, var_index,
+       val_ptr, val_len, val_size)) == VAR_OK) {
+      return VAR_OK;
+   }
+
+   if ((stat = lookup_counter_var(ctx, my_ctx, var_ptr, var_len, var_inc, var_index,
+       val_ptr, val_len, val_size)) == VAR_OK) {
+      return VAR_OK;
+   }
+
+   /* Look in environment */
+   if (var_len > (int)sizeof(buf) - 1) {
+       return VAR_ERR_OUT_OF_MEMORY;
+   }
+   memcpy(buf, var_ptr, var_len + 1);
+   buf[var_len] = 0;
+// Dmsg1(000, "Var=%s\n", buf);
+
+   if ((val = getenv(buf)) == NULL) {
+       return VAR_ERR_UNDEFINED_VARIABLE;
+   }
+   if (var_index == 0) {
+      *val_ptr = val;
+      *val_len = strlen(val);
+      *val_size = 0;
+      return VAR_OK;
+   }
+   /* He wants to index the "array" */
+   count = 0;
+   /* Find the size of the "array"                           
+    *  each element is separated by a |  
+    */
+   for (p = val; *p; p++) {
+      if (*p == '|') {
+        count++;
+      }
+   }
+   count++;
+// Dmsg3(000, "For %s, reqest index=%d have=%d\n",
+//    buf, var_index, count);
+   if (var_index < 0 || var_index > count) {
+      return VAR_ERR_SUBMATCH_OUT_OF_RANGE;
+   }
+   /* Now find the particular item (var_index) he wants */
+   count = 1;
+   for (p=val; *p; ) {
+      if (*p == '|') {
+        if (count < var_index) {
+           val = ++p;
+           count++;
+           continue;
+        }
+        break;
+      }
+      p++;
+   }
+   if (p-val > (int)sizeof(buf) - 1) {
+       return VAR_ERR_OUT_OF_MEMORY;
+   }
+// Dmsg2(000, "val=%s len=%d\n", val, p-val);
+   /* Make a copy of item, and pass it back */
+   v = (char *)malloc(p-val+1);
+   memcpy(v, val, p-val);
+   v[p-val] = 0;
+   *val_ptr = v;
+   *val_len = p-val;
+   *val_size = p-val;
+// Dmsg1(000, "v=%s\n", v);
+   return VAR_OK;
+}
+
+/*
+ * Called here to do a special operation on a variable
+ *   op_ptr  points to the special operation code (not EOS terminated)
+ *   arg_ptr points to argument to special op code
+ *   val_ptr points to the value string
+ *   out_ptr points to string to be returned
+ */
+static var_rc_t operate_var(var_t *var, void *my_ctx, 
+         const char *op_ptr, int op_len, 
+         const char *arg_ptr, int arg_len,
+         const char *val_ptr, int val_len, 
+         char **out_ptr, int *out_len, int *out_size)
+{
+   var_rc_t stat = VAR_ERR_UNDEFINED_OPERATION;
+   Dmsg0(000, "Enter operate_var\n");
+   if (!val_ptr) {
+      *out_size = 0;
+      return stat;
+   }
+   if (op_len == 3 && strncmp(op_ptr, "inc", 3) == 0) {
+      char buf[MAXSTRING];
+      if (val_len > (int)sizeof(buf) - 1) {
+         return VAR_ERR_OUT_OF_MEMORY;
+      }
+      memcpy(buf, arg_ptr, arg_len);
+      buf[arg_len] = 0;
+      Dmsg1(000, "Arg=%s\n", buf);
+      memcpy(buf, val_ptr, val_len);
+      buf[val_len] = 0;   
+      Dmsg1(000, "Val=%s\n", buf);
+      LockRes();
+      for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
+        if (strcmp(counter->hdr.name, buf) == 0) {
+            Dmsg2(000, "counter=%s val=%s\n", counter->hdr.name, buf);
+           break;
+        }
+      }
+      UnlockRes();
+      return stat;
+   }
+   *out_size = 0;
+   return stat;
+}
+
+
+/* 
+ * Expand an input line and return it.
+ *
+ *  Returns: 0 on failure
+ *          1 on success and exp has expanded input
+ */
+int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp)
+{
+   var_t *var_ctx;
+   var_rc_t stat;
+   char *outp;
+   int in_len, out_len;
+   int rtn_stat = 0;
+
+   in_len = strlen(inp);
+   outp = NULL;
+   out_len = 0;
+
+   /* create context */
+   if ((stat = var_create(&var_ctx)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot create var context: ERR=%s\n"), var_strerror(var_ctx, stat));
+       goto bail_out;
+   }
+   /* define callback */
+   if ((stat = var_config(var_ctx, VAR_CONFIG_CB_VALUE, lookup_var, (void *)jcr)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot set var callback: ERR=%s\n"), var_strerror(var_ctx, stat));
+       goto bail_out;
+   }
+
+   /* define special operations */
+   if ((stat = var_config(var_ctx, VAR_CONFIG_CB_OPERATION, operate_var, (void *)jcr)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot set var operate: ERR=%s\n"), var_strerror(var_ctx, stat));
+       goto bail_out;
+   }
+
+   /* unescape in place */
+   if ((stat = var_unescape(var_ctx, inp, in_len, inp, in_len+1, 0)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot unescape string: ERR=%s\n"), var_strerror(var_ctx, stat));
+       goto bail_out;
+   }
+
+   in_len = strlen(inp);
+
+   /* expand variables */
+   if ((stat = var_expand(var_ctx, inp, in_len, &outp, &out_len, 1)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot expand LabelFormat \"%s\": ERR=%s\n"), 
+         inp, var_strerror(var_ctx, stat));
+       goto bail_out;
+   }
+
+   /* unescape once more in place */
+   if ((stat = var_unescape(var_ctx, outp, out_len, outp, out_len+1, 1)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot unescape string: ERR=%s\n"), var_strerror(var_ctx, stat));
+       goto bail_out;
+   }
+
+   pm_strcpy(exp, outp);
+
+   rtn_stat = 1;  
+
+bail_out:
+   /* destroy expansion context */
+   if ((stat = var_destroy(var_ctx)) != VAR_OK) {
+       Jmsg(jcr, M_ERROR, 0, _("Cannot destroy var context: ERR=%s\n"), var_strerror(var_ctx, stat));
+   }
+   if (outp) {
+      free(outp);
+   }
+   return rtn_stat;
+}