X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fexpand.c;h=894be0da75cd2d764bf5e29ccaaf577603ff174d;hb=87187e5526cf427d78cbc3763a8d15df70c2ea3b;hp=265faa767808d39870e3c14b77dd82ba284b91f7;hpb=88fc2148e99ab82373f1378f9e0570b5663b480e;p=bacula%2Fbacula diff --git a/bacula/src/dird/expand.c b/bacula/src/dird/expand.c index 265faa7678..894be0da75 100644 --- a/bacula/src/dird/expand.c +++ b/bacula/src/dird/expand.c @@ -8,169 +8,191 @@ * Version $Id$ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Bacula® - The Network Backup Solution - 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. + Copyright (C) 2003-2006 Free Software Foundation Europe e.V. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - */ + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ #include "bacula.h" #include "dird.h" -static int date_item(JCR *jcr, int code, - const char **val_ptr, int *val_len, int *val_size) +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); + (void)localtime_r(&now, &tm); int val = 0; char buf[10]; switch (code) { - case 1: /* year */ + case 1: /* year */ val = tm.tm_year + 1900; break; - case 2: /* month */ + case 2: /* month */ val = tm.tm_mon + 1; break; - case 3: /* day */ + case 3: /* day */ val = tm.tm_mday; break; - case 4: /* hour */ + case 4: /* hour */ val = tm.tm_hour; break; - case 5: /* minute */ + case 5: /* minute */ val = tm.tm_min; break; - case 6: /* second */ + case 6: /* second */ val = tm.tm_sec; break; - case 7: /* Week day */ + 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; + *val_size = *val_len + 1; return 1; } -static int job_item(JCR *jcr, int code, - const char **val_ptr, int *val_len, int *val_size) +static int job_item(JCR *jcr, int code, + const char **val_ptr, int *val_len, int *val_size) { - char *str = " "; + const char *str = " "; char buf[20]; switch (code) { - case 1: /* Job */ - str = jcr->job->hdr.name; + case 1: /* Job */ + str = jcr->job->name(); break; case 2: /* Director's name */ str = my_name; break; - case 3: /* level */ - str = job_level_to_str(jcr->JobLevel); + case 3: /* level */ + str = job_level_to_str(jcr->getJobLevel()); break; - case 4: /* type */ - str = job_type_to_str(jcr->JobType); + case 4: /* type */ + str = job_type_to_str(jcr->getJobType()); break; - case 5: /* JobId */ + case 5: /* JobId */ bsnprintf(buf, sizeof(buf), "%d", jcr->JobId); str = buf; break; - case 6: /* Client */ - str = jcr->client->hdr.name; + case 6: /* Client */ + str = jcr->client->name(); if (!str) { str = " "; } break; - case 7: /* NumVols */ + case 7: /* NumVols */ bsnprintf(buf, sizeof(buf), "%d", jcr->NumVols); str = buf; break; - case 8: /* Pool */ - str = jcr->pool->hdr.name; + case 8: /* Pool */ + str = jcr->pool->name(); break; - case 9: /* Storage */ - str = jcr->store->hdr.name; + case 9: /* Storage */ + if (jcr->wstore) { + str = jcr->wstore->name(); + } else { + str = jcr->rstore->name(); + } break; - case 10: /* Catalog */ - str = jcr->catalog->hdr.name; + case 10: /* Catalog */ + str = jcr->catalog->name(); break; - case 11: /* MediaType */ - str = jcr->store->media_type; + case 11: /* MediaType */ + if (jcr->wstore) { + str = jcr->wstore->media_type; + } else { + str = jcr->rstore->media_type; + } break; - case 12: /* JobName */ + case 12: /* JobName */ str = jcr->Job; break; } *val_ptr = bstrdup(str); *val_len = strlen(str); - *val_size = *val_len; + *val_size = *val_len + 1; return 1; } +struct s_built_in_vars {const char *var_name; int code; int (*func)(JCR *jcr, int code, + const char **val_ptr, int *val_len, int *val_size);}; -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);}; - +/* + * Table of build in variables + */ 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}, + { NT_("Year"), 1, date_item}, + { NT_("Month"), 2, date_item}, + { NT_("Day"), 3, date_item}, + { NT_("Hour"), 4, date_item}, + { NT_("Minute"), 5, date_item}, + { NT_("Second"), 6, date_item}, + { NT_("WeekDay"), 7, date_item}, + + { NT_("Job"), 1, job_item}, + { NT_("Dir"), 2, job_item}, + { NT_("Level"), 3, job_item}, + { NT_("Type"), 4, job_item}, + { NT_("JobId"), 5, job_item}, + { NT_("Client"), 6, job_item}, + { NT_("NumVols"), 7, job_item}, + { NT_("Pool"), 8, job_item}, + { NT_("Storage"), 9, job_item}, + { NT_("Catalog"), 10, job_item}, + { NT_("MediaType"), 11, job_item}, + { NT_("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) +/* + * Search the table of built-in variables, and if found, + * call the appropriate subroutine to do the work. + */ +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; + 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; @@ -178,11 +200,11 @@ static var_rc_t lookup_built_in_var(var_t *ctx, void *my_ctx, /* - * Search counter variables + * 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) +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; @@ -194,38 +216,49 @@ static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, buf[var_len] = 0; LockRes(); for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) { - if (strcmp(counter->hdr.name, buf) == 0) { + if (strcmp(counter->name(), buf) == 0) { Dmsg2(100, "Counter=%s val=%d\n", buf, counter->CurrentValue); - bsnprintf(buf, sizeof(buf), "%d", counter->CurrentValue); - *val_ptr = bstrdup(buf); - *val_len = strlen(buf); - *val_size = *val_len; - if (var_inc && counter->Catalog) { - 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; - Dmsg1(100, "New value=%d\n", cr.CurrentValue); - if (counter->WrapCounter) { - bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter)); - } else { - cr.WrapCounter[0] = 0; - } - 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; + /* -1 => return size of array */ + if (var_index == -1) { + bsnprintf(buf, sizeof(buf), "%d", counter->CurrentValue); + *val_len = bsnprintf(buf, sizeof(buf), "%d", strlen(buf)); + *val_ptr = buf; + *val_size = 0; /* don't try to free val_ptr */ + return VAR_OK; + } else { + bsnprintf(buf, sizeof(buf), "%d", counter->CurrentValue); + *val_ptr = bstrdup(buf); + *val_len = strlen(buf); + *val_size = *val_len + 1; + } + if (var_inc) { /* increment the variable? */ + if (counter->CurrentValue == counter->MaxValue) { + counter->CurrentValue = counter->MinValue; + } else { + counter->CurrentValue++; + } + if (counter->Catalog) { /* update catalog if need be */ + COUNTER_DBR cr; + JCR *jcr = (JCR *)my_ctx; + memset(&cr, 0, sizeof(cr)); + bstrncpy(cr.Counter, counter->name(), sizeof(cr.Counter)); + cr.MinValue = counter->MinValue; + cr.MaxValue = counter->MaxValue; + cr.CurrentValue = counter->CurrentValue; + Dmsg1(100, "New value=%d\n", cr.CurrentValue); + if (counter->WrapCounter) { + bstrncpy(cr.WrapCounter, counter->WrapCounter->name(), sizeof(cr.WrapCounter)); + } else { + cr.WrapCounter[0] = 0; + } + if (!db_update_counter_record(jcr, jcr->db, &cr)) { + Jmsg(jcr, M_ERROR, 0, _("Count not update counter %s: ERR=%s\n"), + counter->name(), db_strerror(jcr->db)); + } + } + } + stat = VAR_OK; + break; } } UnlockRes(); @@ -234,23 +267,24 @@ static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, /* - * Called here to look up a variable + * Called here from "core" expand code 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) +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; + /* Note, if val_size > 0 and val_ptr!=NULL, the core code will free() it */ if ((stat = lookup_built_in_var(ctx, my_ctx, var_ptr, var_len, var_index, - val_ptr, val_len, val_size)) == VAR_OK) { + 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) { + val_ptr, val_len, val_size)) == VAR_OK) { return VAR_OK; } @@ -265,38 +299,48 @@ static var_rc_t lookup_var(var_t *ctx, void *my_ctx, 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 | + count = 1; + /* Find the size of the "array" + * each element is separated by a | */ for (p = val; *p; p++) { if (*p == '|') { - count++; + count++; } } - count++; Dmsg3(100, "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; + + /* -1 => return size of array */ + if (var_index == -1) { + int len; + if (count == 1) { /* if not array */ + len = strlen(val); /* return length of string */ + } else { + len = count; /* else return # array items */ + } + *val_len = bsnprintf(buf, sizeof(buf), "%d", len); + *val_ptr = buf; + *val_size = 0; /* don't try to free val_ptr */ + return VAR_OK; + } + + + if (var_index < -1 || var_index > --count) { +// return VAR_ERR_SUBMATCH_OUT_OF_RANGE; + return VAR_ERR_UNDEFINED_VARIABLE; } /* Now find the particular item (var_index) he wants */ - count = 1; + count = 0; for (p=val; *p; ) { if (*p == '|') { - if (count < var_index) { - val = ++p; - count++; - continue; - } - break; + if (count < var_index) { + val = ++p; + count++; + continue; + } + break; } p++; } @@ -310,7 +354,7 @@ static var_rc_t lookup_var(var_t *ctx, void *my_ctx, v[p-val] = 0; *val_ptr = v; *val_len = p-val; - *val_size = p-val; + *val_size = p-val+1; Dmsg1(100, "v=%s\n", v); return VAR_OK; } @@ -322,11 +366,11 @@ static var_rc_t lookup_var(var_t *ctx, void *my_ctx, * 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) +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(100, "Enter operate_var\n"); @@ -337,20 +381,20 @@ static var_rc_t operate_var(var_t *var, void *my_ctx, 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; + return VAR_ERR_OUT_OF_MEMORY; } memcpy(buf, arg_ptr, arg_len); buf[arg_len] = 0; Dmsg1(100, "Arg=%s\n", buf); memcpy(buf, val_ptr, val_len); - buf[val_len] = 0; + buf[val_len] = 0; Dmsg1(100, "Val=%s\n", buf); LockRes(); for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) { - if (strcmp(counter->hdr.name, buf) == 0) { - Dmsg2(100, "counter=%s val=%s\n", counter->hdr.name, buf); - break; - } + if (strcmp(counter->name(), buf) == 0) { + Dmsg2(100, "counter=%s val=%s\n", counter->name(), buf); + break; + } } UnlockRes(); return stat; @@ -360,11 +404,11 @@ static var_rc_t operate_var(var_t *var, void *my_ctx, } -/* +/* * Expand an input line and return it. * * Returns: 0 on failure - * 1 on success and exp has expanded input + * 1 on success and exp has expanded input */ int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp) { @@ -404,9 +448,9 @@ int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp) 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)); + if ((stat = var_expand(var_ctx, inp, in_len, &outp, &out_len, 0)) != VAR_OK) { + Jmsg(jcr, M_ERROR, 0, _("Cannot expand expression \"%s\": ERR=%s\n"), + inp, var_strerror(var_ctx, stat)); goto bail_out; } @@ -418,7 +462,7 @@ int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp) pm_strcpy(exp, outp); - rtn_stat = 1; + rtn_stat = 1; bail_out: /* destroy expansion context */