-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.
- 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:
- 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.
- 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: !!!!!
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.
- 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.
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.
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);
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) {
}
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;
{"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},
* 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}
};
{"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},
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;
}
}
*val_ptr = bstrdup(str);
*val_len = strlen(str);
- *val_size = *val_len;
+ *val_size = *val_len + 1;
return 1;
}
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;
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 |
*/
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) {
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;
}
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;
}
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; i<ua->argc; 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;
}
static int
expand_isoct(
- char c)
+ int c)
{
if (c >= '0' && c <= '7')
return 1;
expand_octal(
const char **src, char **dst, const char *end)
{
- unsigned char c;
+ int c;
if (end - *src < 3)
return VAR_ERR_INCOMPLETE_OCTAL;
static int
expand_ishex(
- char c)
+ int c)
{
if ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
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;
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;
else if (**src >= 'A' && **src <= 'F')
c += **src - 'A' + 10;
- **dst = (char) c;
+ **dst = (char)c;
(*dst)++;
return VAR_OK;
}
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;
}
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;
}
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);
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;
}
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;
}
/* 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;
}
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;
}
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;
}
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:
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");
#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