From: Kern Sibbald Date: Sat, 13 Sep 2003 15:08:03 +0000 (+0000) Subject: Final variable expansion fixes + misc X-Git-Tag: Release-1.32~19 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5161a41601125ea46cdcf0d3723b58470ef48717;p=bacula%2Fbacula Final variable expansion fixes + misc git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@700 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/ChangeLog b/bacula/ChangeLog index 7a9c9d2b13..960937403c 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,5 +1,15 @@ -2003-08-02 Version 1.32 10Sep03 Beta +2003-09-12 Version 1.32 12Sep03 Beta +- Add new aliases SDAddress, ... +- Final changes for variable expansion +- Possible fix to Alex's SD crashes +- Correct incrementing counters not in catalog -- reported by + Chris Allen. +- Correct memory leak in core var.c code -- reported by + Chris Allen. +- Make documentation of variable substitution a bit clearer. +- Apply Nic Bellamy's patch to dbcheck.c to fix SQL to work + on both MySQL and SQLite. - Finally fixed the .messages that was sent during prompts in the console with no readline. - Implement new Include/Exclude semantics. diff --git a/bacula/ReleaseNotes b/bacula/ReleaseNotes index c647bd9f98..d86744ebe9 100644 --- a/bacula/ReleaseNotes +++ b/bacula/ReleaseNotes @@ -14,6 +14,7 @@ Major Changes this Release: - Added ClientRunBeforeJob and ClientRunAfterJob. - Implemented Include | and < in File daemon. - Implemented a new Include/Exclude syntax. +- Lots of fixes with variable expansion and counter variables Other Changes this Release: @@ -26,7 +27,7 @@ Other Changes this Release: - Delete old semaphore job and workq job scheduling code. - edit_run_codes in one place (/lib) Add Job name - Update query.sql to find current backups correctly. -- Correct ambiguous SQL statement for prunning. +- Correct ambiguous SQL statement for pruning. - Set heartbeat interval to zero by default. - Fix a possible race condition in stopping the heartbeat thread. @@ -35,6 +36,11 @@ Other Changes this Release: - Corrected console prompt problem in non-readline versions. - Correct a number of variable expansion problems. - Added a number of new regression tests. +- In an attempt to make configuration a bit less confusing, I've changed + the name of a number of variables. The old ones still work, but will + be phased out over time. FDAddress, FDPassword, SDAddress SDPassword, + SDDeviceName, and DBPassword. +- A possible fix to the very intermittent SD crashes that Alex gets. Items to note: !!!!! diff --git a/bacula/kernstodo b/bacula/kernstodo index 523becdf27..5509159166 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 10 September 2003 + 12 September 2003 Documentation to do: (any release a little bit at a time) - Document running a test version. @@ -23,6 +23,9 @@ Testing to do: (painful) - Figure out how to use ssh or stunnel to protect Bacula communications. For 1.32: +- Document new records in Director. SDAddress SDDeviceName, SDPassword. + FDPassword, FDAddress, DBAddress, DBPort, DBPassword. +- It is generally safe to use the drive when the lights stop flashing. - Document new Include/Exclude ... - Document all the status codes JobLevel, JobType, JobStatus. - Add test of exclusion, test multiple Include {} statements. @@ -32,8 +35,18 @@ For 1.32: when the magazine is changed. - Don't print "Warning: Wrong Volume mounted ..." if mounting second volume. - Implement List Volume Job=xxx or List scheduled volumes or Status Director +- May variable expansion work correctly. +- LabelFormat on tape volume apparently creates the db record but + never actually labels the volume. For 1.33 +- Think about changing Storage resource Device record to be + SDDeviceName. +- Look at how fuser works and /proc/PID/fd that is how Nic found the + file descriptor leak in Bacula. +- Implement WrapCounters in Counters. +- Turn on SIGHUP in dird.c and test. +- Use system dependent calls to get more precise info on tape errors. - Add heartbeat from FD to SD if hb interval expires. - Suppress read error on blank tape when doing a label. - Can we dynamically change FileSets. diff --git a/bacula/src/console/console.c b/bacula/src/console/console.c index f33bc81617..f518bd2ced 100644 --- a/bacula/src/console/console.c +++ b/bacula/src/console/console.c @@ -518,17 +518,18 @@ static int inputcmd(FILE *input, BSOCK *UA_sock) FILE *fd; if (argc > 2) { - sendit(_("Too many arguments.\n")); - return 0; + sendit(_("Too many arguments on input command.\n")); + return 1; } if (argc == 1) { - sendit(_("First argument must be a filename.\n")); - return 0; + sendit(_("First argument to input command must be a filename.\n")); + return 1; } fd = fopen(argk[1], "r"); if (!fd) { - sendit(_("Cannot open file. ERR=%s\n"), strerror(errno)); - return 0; + sendit(_("Cannot open file %s for input. ERR=%s\n"), + argk[1], strerror(errno)); + return 1; } read_and_process_input(fd, UA_sock); fclose(fd); @@ -554,7 +555,7 @@ static int do_outputcmd(FILE *input, BSOCK *UA_sock) char *mode = "a+"; if (argc > 3) { - sendit(_("Too many arguments.\n")); + sendit(_("Too many arguments on output/tee command.\n")); return 1; } if (argc == 1) { @@ -570,7 +571,8 @@ static int do_outputcmd(FILE *input, BSOCK *UA_sock) } fd = fopen(argk[1], mode); if (!fd) { - sendit(_("Cannot open file. ERR=%s\n"), strerror(errno)); + sendit(_("Cannot open file %s for output. ERR=%s\n"), + argk[1], strerror(errno)); return 1; } output = fd; diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 00a8f9c7e5..cc69362807 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -129,8 +129,10 @@ static struct res_items cli_items[] = { {"name", store_name, ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0}, {"description", store_str, ITEM(res_client.hdr.desc), 0, 0, 0}, {"address", store_str, ITEM(res_client.address), 0, ITEM_REQUIRED, 0}, + {"fdaddress", store_str, ITEM(res_client.address), 0, ITEM_REQUIRED, 0}, {"fdport", store_pint, ITEM(res_client.FDport), 0, ITEM_DEFAULT, 9102}, {"password", store_password, ITEM(res_client.password), 0, ITEM_REQUIRED, 0}, + {"fdpassword", store_password, ITEM(res_client.password), 0, ITEM_REQUIRED, 0}, {"catalog", store_res, ITEM(res_client.catalog), R_CATALOG, 0, 0}, {"fileretention", store_time, ITEM(res_client.FileRetention), 0, ITEM_DEFAULT, 60*60*24*60}, {"jobretention", store_time, ITEM(res_client.JobRetention), 0, ITEM_DEFAULT, 60*60*24*180}, @@ -145,17 +147,19 @@ static struct res_items cli_items[] = { * name handler value code flags default_value */ static struct res_items store_items[] = { - {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0}, - {"description", store_str, ITEM(res_store.hdr.desc), 0, 0, 0}, - {"sdport", store_pint, ITEM(res_store.SDport), 0, ITEM_DEFAULT, 9103}, - {"sddport", store_pint, ITEM(res_store.SDDport), 0, 0, 0}, /* deprecated */ - {"address", store_str, ITEM(res_store.address), 0, ITEM_REQUIRED, 0}, - {"password", store_password, ITEM(res_store.password), 0, ITEM_REQUIRED, 0}, - {"device", store_strname, ITEM(res_store.dev_name), 0, ITEM_REQUIRED, 0}, - {"mediatype", store_strname, ITEM(res_store.media_type), 0, ITEM_REQUIRED, 0}, - {"autochanger", store_yesno, ITEM(res_store.autochanger), 1, ITEM_DEFAULT, 0}, - {"enablessl", store_yesno, ITEM(res_store.enable_ssl), 1, ITEM_DEFAULT, 0}, + {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(res_store.hdr.desc), 0, 0, 0}, + {"sdport", store_pint, ITEM(res_store.SDport), 0, ITEM_DEFAULT, 9103}, + {"address", store_str, ITEM(res_store.address), 0, ITEM_REQUIRED, 0}, + {"sdaddress", store_str, ITEM(res_store.address), 0, ITEM_REQUIRED, 0}, + {"sdpassword", store_password, ITEM(res_store.password), 0, ITEM_REQUIRED, 0}, + {"device", store_strname, ITEM(res_store.dev_name), 0, ITEM_REQUIRED, 0}, + {"sddevicename", store_strname, ITEM(res_store.dev_name), 0, ITEM_REQUIRED, 0}, + {"mediatype", store_strname, ITEM(res_store.media_type), 0, ITEM_REQUIRED, 0}, + {"autochanger", store_yesno, ITEM(res_store.autochanger), 1, ITEM_DEFAULT, 0}, + {"enablessl", store_yesno, ITEM(res_store.enable_ssl), 1, ITEM_DEFAULT, 0}, {"maximumconcurrentjobs", store_pint, ITEM(res_store.MaxConcurrentJobs), 0, ITEM_DEFAULT, 1}, + {"sddport", store_pint, ITEM(res_store.SDDport), 0, 0, 0}, /* deprecated */ {NULL, NULL, NULL, 0, 0, 0} }; @@ -172,6 +176,7 @@ static struct res_items cat_items[] = { {"dbport", store_pint, ITEM(res_cat.db_port), 0, 0, 0}, /* keep this password as store_str for the moment */ {"password", store_str, ITEM(res_cat.db_password), 0, 0, 0}, + {"dbpassword", store_str, ITEM(res_cat.db_password), 0, 0, 0}, {"user", store_str, ITEM(res_cat.db_user), 0, 0, 0}, {"dbname", store_str, ITEM(res_cat.db_name), 0, ITEM_REQUIRED, 0}, {"dbsocket", store_str, ITEM(res_cat.db_socket), 0, 0, 0}, diff --git a/bacula/src/dird/expand.c b/bacula/src/dird/expand.c index a36b788f37..11bab82bb1 100644 --- a/bacula/src/dird/expand.c +++ b/bacula/src/dird/expand.c @@ -67,7 +67,7 @@ static int date_item(JCR *jcr, int code, 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; } @@ -122,7 +122,7 @@ static int job_item(JCR *jcr, int code, } *val_ptr = bstrdup(str); *val_len = strlen(str); - *val_size = *val_len; + *val_size = *val_len + 1; return 1; } @@ -203,10 +203,19 @@ static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx, for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) { if (strcmp(counter->hdr.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; + /* -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; @@ -275,14 +284,8 @@ 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; /* don't try to free val_ptr */ - return VAR_OK; - } /* He wants to index the "array" */ - count = 0; + count = 1; /* Find the size of the "array" * each element is separated by a | */ @@ -291,14 +294,30 @@ static var_rc_t lookup_var(var_t *ctx, void *my_ctx, 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) { @@ -320,7 +339,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; } @@ -414,8 +433,8 @@ 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"), + 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; } diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 9056b087b6..1273b0c83b 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -1276,17 +1276,22 @@ static int setdebug_cmd(UAContext *ua, char *cmd) static int var_cmd(UAContext *ua, char *cmd) { - POOLMEM *var = get_pool_memory(PM_FNAME); + POOLMEM *val = get_pool_memory(PM_FNAME); + char *var; if (!open_db(ua)) { return 1; } - for (int i=1; iargc; i++) { - if (ua->argk[i] && variable_expansion(ua->jcr, ua->argk[i], &var)) { - bsendmsg(ua, "%s\n", var); - } + for (var=ua->cmd; *var != ' '; ) { /* skip command */ + var++; + } + while (*var == ' ') { /* skip spaces */ + var++; } - free_pool_memory(var); + Dmsg1(100, "Var=%s:\n", var); + variable_expansion(ua->jcr, var, &val); + bsendmsg(ua, "%s\n", val); + free_pool_memory(val); return 1; } diff --git a/bacula/src/lib/var.c b/bacula/src/lib/var.c index 87d043a286..2b0bcb1400 100644 --- a/bacula/src/lib/var.c +++ b/bacula/src/lib/var.c @@ -451,7 +451,7 @@ expand_character_class(const char *desc, char_class_t chrclass) static int expand_isoct( - char c) + int c) { if (c >= '0' && c <= '7') return 1; @@ -463,7 +463,7 @@ static var_rc_t expand_octal( const char **src, char **dst, const char *end) { - unsigned char c; + int c; if (end - *src < 3) return VAR_ERR_INCOMPLETE_OCTAL; @@ -491,7 +491,7 @@ expand_octal( static int expand_ishex( - char c) + int c) { if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) @@ -504,7 +504,7 @@ static var_rc_t expand_simple_hex( const char **src, char **dst, const char *end) { - unsigned char c = 0; + int c = 0; if (end - *src < 2) return VAR_ERR_INCOMPLETE_HEX; @@ -514,9 +514,9 @@ expand_simple_hex( if (**src >= '0' && **src <= '9') c = **src - '0'; - else if (c >= 'a' && c <= 'f') + else if (**src >= 'a' && **src <= 'f') c = **src - 'a' + 10; - else if (c >= 'A' && c <= 'F') + else if (**src >= 'A' && **src <= 'F') c = **src - 'A' + 10; c = c << 4; @@ -529,7 +529,7 @@ expand_simple_hex( else if (**src >= 'A' && **src <= 'F') c += **src - 'A' + 10; - **dst = (char) c; + **dst = (char)c; (*dst)++; return VAR_OK; } @@ -735,8 +735,7 @@ parse_exptext_or_variable( goto error_return; if (rc > 0) { p += rc; - if (!tokenbuf_append - (result, tmp.begin, tmp.end - tmp.begin)) { + if (!tokenbuf_merge(result, &tmp)) { rc = VAR_ERR_OUT_OF_MEMORY; goto error_return; } @@ -787,8 +786,7 @@ parse_substext_or_variable( goto error_return; if (rc > 0) { p += rc; - if (!tokenbuf_append - (result, tmp.begin, tmp.end - tmp.begin)) { + if (!tokenbuf_merge(result, &tmp)) { rc = VAR_ERR_OUT_OF_MEMORY; goto error_return; } @@ -1080,7 +1078,7 @@ op_search_and_replace( return rc; } /* append replace string */ - if (!tokenbuf_append(&tmp, myreplace.begin, myreplace.end - myreplace.begin)) { + if (!tokenbuf_merge(&tmp, &myreplace)) { regfree(&preg); tokenbuf_free(&tmp); tokenbuf_free(&mydata); @@ -1204,7 +1202,7 @@ op_padding( if (i > 0) { i = i / (fill->end - fill->begin); while (i > 0) { - if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) { + if (!tokenbuf_merge(&result, fill)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } @@ -1215,7 +1213,7 @@ op_padding( tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } - if (!tokenbuf_append(&result, data->begin, data->end - data->begin)) { + if (!tokenbuf_merge(&result, data)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } @@ -1230,7 +1228,7 @@ op_padding( /* create the prefix */ i = i / (fill->end - fill->begin); while (i > 0) { - if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) { + if (!tokenbuf_merge(&result, fill)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } @@ -1243,7 +1241,7 @@ op_padding( return VAR_ERR_OUT_OF_MEMORY; } /* append the actual data string */ - if (!tokenbuf_append(&result, data->begin, data->end - data->begin)) { + if (!tokenbuf_merge(&result, data)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } @@ -1251,7 +1249,7 @@ op_padding( i = width - (result.end - result.begin); i = i / (fill->end - fill->begin); while (i > 0) { - if (!tokenbuf_append(&result, fill->begin, fill->end - fill->begin)) { + if (!tokenbuf_merge(&result, fill)) { tokenbuf_free(&result); return VAR_ERR_OUT_OF_MEMORY; } @@ -1615,11 +1613,16 @@ parse_operation( arg_ptr, arg_len, val_ptr, val_len, &out_ptr, &out_len, &out_size); - if (rc < 0) + if (rc < 0) { + if (arg_ptr != NULL) + free((void *)arg_ptr); goto error_return; + } tokenbuf_free(data); tokenbuf_set(data, out_ptr, out_ptr+out_len, out_size); } + if (arg_ptr != NULL) + free((void *)arg_ptr); break; } default: diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index 068bf73c60..ec67d19976 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -139,6 +139,7 @@ void *connection_request(void *arg) jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */ jcr->dir_bsock = bs; /* save Director bsock */ + jcr->dir_bsock->jcr = jcr; Dmsg0(1000, "stored in start_job\n"); diff --git a/bacula/src/version.h b/bacula/src/version.h index fd71f7c705..0f403a0d1a 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.32" #define VSTRING "1" -#define BDATE "10 Sep 2003" -#define LSMDATE "10Sep03" +#define BDATE "12 Sep 2003" +#define LSMDATE "12Sep03" /* Debug flags */ #undef DEBUG