From 1edca25cd7db939fd65c2c3581b9bb4c7cff5c4b Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 9 May 2005 18:19:27 +0000 Subject: [PATCH] - Correct bug in parse_config error handling. - Where ever possible mark a volume in error or not InChanger in mount.c git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2016 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/lib/lex.c | 12 +- bacula/src/lib/parse_conf.c | 450 ++++++++++++++++---------------- bacula/src/lib/protos.h | 1 + bacula/src/stored/askdir.c | 2 +- bacula/src/stored/autochanger.c | 17 -- bacula/src/stored/mount.c | 47 +++- bacula/src/stored/protos.h | 1 - 7 files changed, 275 insertions(+), 255 deletions(-) diff --git a/bacula/src/lib/lex.c b/bacula/src/lib/lex.c index 9f98b6c476..095ce50d37 100644 --- a/bacula/src/lib/lex.c +++ b/bacula/src/lib/lex.c @@ -65,7 +65,7 @@ int scan_to_next_not_eol(LEX * lc) /* * Format a scanner error message */ -static void s_err(const char *file, int line, LEX *lc, const char *msg, ...) +void s_err(const char *file, int line, LEX *lc, const char *msg, ...) { va_list arg_ptr; char buf[MAXSTRING]; @@ -80,10 +80,14 @@ static void s_err(const char *file, int line, LEX *lc, const char *msg, ...) _("Problem probably begins at line %d.\n"), lc->begin_line_no); } else { more[0] = 0; - } - e_msg(file, line, M_ERROR_TERM, 0, _("Config error: %s\n" + } + if (lc->line_no > 0) { + e_msg(file, line, M_ERROR_TERM, 0, _("Config error: %s\n" " : line %d, col %d of file %s\n%s\n%s"), - buf, lc->line_no, lc->col_no, lc->fname, lc->line, more); + buf, lc->line_no, lc->col_no, lc->fname, lc->line, more); + } else { + e_msg(file, line, M_ERROR_TERM, 0, _("Config error: %s\n"), buf); + } } diff --git a/bacula/src/lib/parse_conf.c b/bacula/src/lib/parse_conf.c index 5213d73aa7..3f76e4e3e5 100755 --- a/bacula/src/lib/parse_conf.c +++ b/bacula/src/lib/parse_conf.c @@ -9,24 +9,24 @@ * 1. The generic lexical scanner in lib/lex.c and lib/lex.h * * 2. The generic config scanner in lib/parse_conf.c and - * lib/parse_conf.h. - * These files contain the parser code, some utility - * routines, and the common store routines (name, int, - * string, time, int64, size, ...). + * lib/parse_conf.h. + * These files contain the parser code, some utility + * routines, and the common store routines (name, int, + * string, time, int64, size, ...). * * 3. The daemon specific file, which contains the Resource - * definitions as well as any specific store routines - * for the resource records. + * definitions as well as any specific store routines + * for the resource records. * * N.B. This is a two pass parser, so if you malloc() a string * in a "store" routine, you must ensure to do it during - * only one of the two passes, or to free it between. - * Also, note that the resource record is malloced and - * saved in save_resource() during pass 1. Anything that - * you want saved after pass two (e.g. resource pointers) - * must explicitly be done in save_resource. Take a look - * at the Job resource in src/dird/dird_conf.c to see how - * it is done. + * only one of the two passes, or to free it between. + * Also, note that the resource record is malloced and + * saved in save_resource() during pass 1. Anything that + * you want saved after pass two (e.g. resource pointers) + * must explicitly be done in save_resource. Take a look + * at the Job resource in src/dird/dird_conf.c to see how + * it is done. * * Kern Sibbald, January MM * @@ -73,11 +73,11 @@ extern RES **res_head; extern "C" CURES res_all; extern "C" int res_all_size; #else -extern CURES res_all; +extern CURES res_all; extern int res_all_size; #endif -extern brwlock_t res_lock; /* resource lock */ +extern brwlock_t res_lock; /* resource lock */ /* Forward referenced subroutines */ @@ -87,7 +87,7 @@ static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd); /* Common Resource definitions */ /* Message resource directives - * name handler value code flags default_value + * name handler value code flags default_value */ RES_ITEM msgs_items[] = { {"name", store_name, ITEM(res_msgs.hdr.name), 0, 0, 0}, @@ -104,7 +104,7 @@ RES_ITEM msgs_items[] = { {"director", store_msgs, ITEM(res_msgs), MD_DIRECTOR, 0, 0}, {"console", store_msgs, ITEM(res_msgs), MD_CONSOLE, 0, 0}, {"operator", store_msgs, ITEM(res_msgs), MD_OPERATOR, 0, 0}, - {NULL, NULL, NULL, 0, 0} + {NULL, NULL, NULL, 0, 0} }; struct s_mtypes { @@ -128,7 +128,7 @@ static struct s_mtypes msg_types[] = { {"security", M_SECURITY}, {"alert", M_ALERT}, {"all", M_MAX+1}, - {NULL, 0} + {NULL, 0} }; /* Used for certain KeyWord tables */ @@ -146,7 +146,7 @@ struct s_kw tapelabels[] = { {"bacula", B_BACULA_LABEL}, {"ansi", B_ANSI_LABEL}, {"ibm", B_IBM_LABEL}, - {NULL, 0} + {NULL, 0} }; @@ -183,7 +183,7 @@ void init_resource(int type, RES_ITEM *items, int pass) if (first && (errstat=rwl_init(&res_lock)) != 0) { Emsg1(M_ABORT, 0, _("Unable to initialize resource lock. ERR=%s\n"), - strerror(errstat)); + strerror(errstat)); } first = false; @@ -194,22 +194,22 @@ void init_resource(int type, RES_ITEM *items, int pass) for (i=0; items[i].name; i++) { Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name, (items[i].flags & ITEM_DEFAULT) ? "yes" : "no", - items[i].default_value); + items[i].default_value); if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) { - if (items[i].handler == store_yesno) { - *(int *)(items[i].value) |= items[i].code; - } else if (items[i].handler == store_pint || - items[i].handler == store_int) { - *(int *)(items[i].value) = items[i].default_value; - } else if (items[i].handler == store_int64) { - *(int64_t *)(items[i].value) = items[i].default_value; - } else if (items[i].handler == store_size) { - *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value; - } else if (items[i].handler == store_time) { - *(utime_t *)(items[i].value) = (utime_t)items[i].default_value; - } else if (pass == 1 && items[i].handler == store_addresses) { - init_default_addresses((dlist**)items[i].value, items[i].default_value); - } + if (items[i].handler == store_yesno) { + *(int *)(items[i].value) |= items[i].code; + } else if (items[i].handler == store_pint || + items[i].handler == store_int) { + *(int *)(items[i].value) = items[i].default_value; + } else if (items[i].handler == store_int64) { + *(int64_t *)(items[i].value) = items[i].default_value; + } else if (items[i].handler == store_size) { + *(uint64_t *)(items[i].value) = (uint64_t)items[i].default_value; + } else if (items[i].handler == store_time) { + *(utime_t *)(items[i].value) = (utime_t)items[i].default_value; + } else if (pass == 1 && items[i].handler == store_addresses) { + init_default_addresses((dlist**)items[i].value, items[i].default_value); + } } /* If this triggers, take a look at lib/parse_conf.h */ if (i >= MAX_RES_ITEMS) { @@ -232,67 +232,67 @@ void store_msgs(LEX *lc, RES_ITEM *item, int index, int pass) switch (item->code) { case MD_STDOUT: case MD_STDERR: - case MD_SYSLOG: /* syslog */ + case MD_SYSLOG: /* syslog */ case MD_CONSOLE: - scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL); - break; - case MD_OPERATOR: /* send to operator */ - case MD_DIRECTOR: /* send to Director */ - case MD_MAIL: /* mail */ - case MD_MAIL_ON_ERROR: /* mail if Job errors */ - if (item->code == MD_OPERATOR) { - cmd = res_all.res_msgs.operator_cmd; - } else { - cmd = res_all.res_msgs.mail_cmd; - } - dest = get_pool_memory(PM_MESSAGE); - dest[0] = 0; - dest_len = 0; - /* Pick up comma separated list of destinations */ - for ( ;; ) { - token = lex_get_token(lc, T_NAME); /* scan destination */ - dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2); - if (dest[0] != 0) { + scan_types(lc, (MSGS *)(item->value), item->code, NULL, NULL); + break; + case MD_OPERATOR: /* send to operator */ + case MD_DIRECTOR: /* send to Director */ + case MD_MAIL: /* mail */ + case MD_MAIL_ON_ERROR: /* mail if Job errors */ + if (item->code == MD_OPERATOR) { + cmd = res_all.res_msgs.operator_cmd; + } else { + cmd = res_all.res_msgs.mail_cmd; + } + dest = get_pool_memory(PM_MESSAGE); + dest[0] = 0; + dest_len = 0; + /* Pick up comma separated list of destinations */ + for ( ;; ) { + token = lex_get_token(lc, T_NAME); /* scan destination */ + dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2); + if (dest[0] != 0) { pm_strcat(dest, " "); /* separate multiple destinations with space */ - dest_len++; - } - pm_strcat(dest, lc->str); - dest_len += lc->str_len; + dest_len++; + } + pm_strcat(dest, lc->str); + dest_len += lc->str_len; Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest)); - token = lex_get_token(lc, T_SKIP_EOL); - if (token == T_COMMA) { - continue; /* get another destination */ - } - if (token != T_EQUALS) { + token = lex_get_token(lc, T_SKIP_EOL); + if (token == T_COMMA) { + continue; /* get another destination */ + } + if (token != T_EQUALS) { scan_err1(lc, _("expected an =, got: %s"), lc->str); - } - break; - } + } + break; + } Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd)); - scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd); - free_pool_memory(dest); + scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd); + free_pool_memory(dest); Dmsg0(900, "done with dest codes\n"); - break; - case MD_FILE: /* file */ - case MD_APPEND: /* append */ - dest = get_pool_memory(PM_MESSAGE); - /* Pick up a single destination */ - token = lex_get_token(lc, T_NAME); /* scan destination */ - pm_strcpy(dest, lc->str); - dest_len = lc->str_len; - token = lex_get_token(lc, T_SKIP_EOL); + break; + case MD_FILE: /* file */ + case MD_APPEND: /* append */ + dest = get_pool_memory(PM_MESSAGE); + /* Pick up a single destination */ + token = lex_get_token(lc, T_NAME); /* scan destination */ + pm_strcpy(dest, lc->str); + dest_len = lc->str_len; + token = lex_get_token(lc, T_SKIP_EOL); Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest)); - if (token != T_EQUALS) { + if (token != T_EQUALS) { scan_err1(lc, _("expected an =, got: %s"), lc->str); - } - scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL); - free_pool_memory(dest); + } + scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL); + free_pool_memory(dest); Dmsg0(900, "done with dest codes\n"); - break; + break; default: scan_err1(lc, _("Unknown item code: %d\n"), item->code); - break; + break; } } scan_to_eol(lc); @@ -313,43 +313,43 @@ static void scan_types(LEX *lc, MSGS *msg, int dest_code, char *where, char *cmd char *str; for (quit=0; !quit;) { - lex_get_token(lc, T_NAME); /* expect at least one type */ + lex_get_token(lc, T_NAME); /* expect at least one type */ found = FALSE; if (lc->str[0] == '!') { - is_not = TRUE; - str = &lc->str[1]; + is_not = TRUE; + str = &lc->str[1]; } else { - is_not = FALSE; - str = &lc->str[0]; + is_not = FALSE; + str = &lc->str[0]; } for (i=0; msg_types[i].name; i++) { - if (strcasecmp(str, msg_types[i].name) == 0) { - msg_type = msg_types[i].token; - found = TRUE; - break; - } + if (strcasecmp(str, msg_types[i].name) == 0) { + msg_type = msg_types[i].token; + found = TRUE; + break; + } } if (!found) { scan_err1(lc, _("message type: %s not found"), str); - /* NOT REACHED */ + /* NOT REACHED */ } - if (msg_type == M_MAX+1) { /* all? */ - for (i=1; i<=M_MAX; i++) { /* yes set all types */ - add_msg_dest(msg, dest_code, i, where, cmd); - } + if (msg_type == M_MAX+1) { /* all? */ + for (i=1; i<=M_MAX; i++) { /* yes set all types */ + add_msg_dest(msg, dest_code, i, where, cmd); + } } else { - if (is_not) { - rem_msg_dest(msg, dest_code, msg_type, where); - } else { - add_msg_dest(msg, dest_code, msg_type, where, cmd); - } + if (is_not) { + rem_msg_dest(msg, dest_code, msg_type, where); + } else { + add_msg_dest(msg, dest_code, msg_type, where, cmd); + } } if (lc->ch != ',') { - break; + break; } Dmsg0(900, "call lex_get_token() to eat comma\n"); - lex_get_token(lc, T_ALL); /* eat comma */ + lex_get_token(lc, T_ALL); /* eat comma */ } Dmsg0(900, "Done scan_types()\n"); } @@ -370,7 +370,7 @@ void store_name(LEX *lc, RES_ITEM *item, int index, int pass) /* Store the name both pass 1 and pass 2 */ if (*(item->value)) { scan_err2(lc, _("Attempt to redefine name \"%s\" to \"%s\"."), - *(item->value), lc->str); + *(item->value), lc->str); } *(item->value) = bstrdup(lc->str); scan_to_eol(lc); @@ -414,7 +414,7 @@ void store_dir(LEX *lc, RES_ITEM *item, int index, int pass) lex_get_token(lc, T_STRING); if (pass == 1) { if (lc->str[0] != '|') { - do_shell_expansion(lc->str, sizeof(lc->str)); + do_shell_expansion(lc->str, sizeof(lc->str)); } *(item->value) = bstrdup(lc->str); } @@ -439,7 +439,7 @@ void store_password(LEX *lc, RES_ITEM *item, int index, int pass) MD5Final(signature, &md5c); for (i = j = 0; i < sizeof(signature); i++) { sprintf(&sig[j], "%02x", signature[i]); - j += 2; + j += 2; } *(item->value) = bstrdup(sig); } @@ -461,11 +461,11 @@ void store_res(LEX *lc, RES_ITEM *item, int index, int pass) res = GetResWithName(item->code, lc->str); if (res == NULL) { scan_err3(lc, _("Could not find config Resource %s referenced on line %d : %s\n"), - lc->str, lc->line_no, lc->line); + lc->str, lc->line_no, lc->line); } if (*(item->value)) { scan_err3(lc, _("Attempt to redefine resource \"%s\" referenced on line %d : %s\n"), - item->name, lc->line_no, lc->line); + item->name, lc->line_no, lc->line); } *(item->value) = (char *)res; } @@ -488,38 +488,38 @@ void store_alist_res(LEX *lc, RES_ITEM *item, int index, int pass) alist *list; if (pass == 2) { - if (count == 0) { /* always store in item->value */ - i = 0; - if ((item->value)[i] == NULL) { - list = New(alist(10, not_owned_by_alist)); - } else { - list = (alist *)(item->value)[i]; - } + if (count == 0) { /* always store in item->value */ + i = 0; + if ((item->value)[i] == NULL) { + list = New(alist(10, not_owned_by_alist)); + } else { + list = (alist *)(item->value)[i]; + } } else { - /* Find empty place to store this directive */ - while ((item->value)[i] != NULL && i++ < count) { } - if (i >= count) { + /* Find empty place to store this directive */ + while ((item->value)[i] != NULL && i++ < count) { } + if (i >= count) { scan_err4(lc, _("Too many %s directives. Max. is %d. line %d: %s\n"), - lc->str, count, lc->line_no, lc->line); - } - list = New(alist(10, not_owned_by_alist)); + lc->str, count, lc->line_no, lc->line); + } + list = New(alist(10, not_owned_by_alist)); } for (;;) { - lex_get_token(lc, T_NAME); /* scan next item */ - res = GetResWithName(item->code, lc->str); - if (res == NULL) { + lex_get_token(lc, T_NAME); /* scan next item */ + res = GetResWithName(item->code, lc->str); + if (res == NULL) { scan_err3(lc, _("Could not find config Resource \"%s\" referenced on line %d : %s\n"), - item->name, lc->line_no, lc->line); - } + item->name, lc->line_no, lc->line); + } Dmsg5(900, "Append %p to alist %p size=%d i=%d %s\n", - res, list, list->size(), i, item->name); - list->append(res); - (item->value)[i] = (char *)list; + res, list, list->size(), i, item->name); + list->append(res); + (item->value)[i] = (char *)list; if (lc->ch != ',') { /* if no other item follows */ - break; /* get out */ - } - lex_get_token(lc, T_ALL); /* eat comma */ + break; /* get out */ + } + lex_get_token(lc, T_ALL); /* eat comma */ } } scan_to_eol(lc); @@ -536,14 +536,14 @@ void store_alist_str(LEX *lc, RES_ITEM *item, int index, int pass) if (pass == 2) { if (*(item->value) == NULL) { - list = New(alist(10, owned_by_alist)); + list = New(alist(10, owned_by_alist)); } else { - list = (alist *)(*(item->value)); + list = (alist *)(*(item->value)); } lex_get_token(lc, T_STRING); /* scan next item */ Dmsg4(900, "Append %s to alist %p size=%d %s\n", - lc->str, list, list->size(), item->name); + lc->str, list, list->size(), item->name); list->append(bstrdup(lc->str)); *(item->value) = (char *)list; } @@ -572,16 +572,16 @@ void store_defs(LEX *lc, RES_ITEM *item, int index, int pass) res = GetResWithName(item->code, lc->str); if (res == NULL) { scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"), - lc->str, lc->line_no, lc->line); + lc->str, lc->line_no, lc->line); } /* for each item not set, we copy the field from res */ #ifdef xxx for (int i=0; item->name;; i++, item++) { - if (bit_is_set(i, res->item_present)) { + if (bit_is_set(i, res->item_present)) { Dmsg2(900, "Item %d is present in %s\n", i, res->name); - } else { + } else { Dmsg2(900, "Item %d is not present in %s\n", i, res->name); - } + } } /* ***FIXME **** add code */ #endif @@ -662,13 +662,13 @@ void store_time(LEX *lc, RES_ITEM *item, int index, int pass) case T_UNQUOTED_STRING: bstrncpy(period, lc->str, sizeof(period)); if (lc->ch == ' ') { - token = lex_get_token(lc, T_ALL); - switch (token) { - case T_IDENTIFIER: - case T_UNQUOTED_STRING: - bstrncat(period, lc->str, sizeof(period)); - break; - } + token = lex_get_token(lc, T_ALL); + switch (token) { + case T_IDENTIFIER: + case T_UNQUOTED_STRING: + bstrncat(period, lc->str, sizeof(period)); + break; + } } if (!duration_to_utime(period, &utime)) { scan_err1(lc, _("expected a time period, got: %s"), period); @@ -713,9 +713,9 @@ void store_label(LEX *lc, RES_ITEM *item, int index, int pass) /* Store the label pass 2 so that type is defined */ for (i=0; tapelabels[i].name; i++) { if (strcasecmp(lc->str, tapelabels[i].name) == 0) { - *(int *)(item->value) = tapelabels[i].token; - i = 0; - break; + *(int *)(item->value) = tapelabels[i].token; + i = 0; + break; } } if (i != 0) { @@ -757,7 +757,13 @@ parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error) if ((lc = lex_open_file(lc, cf, scan_error)) == NULL) { lc = (LEX *)malloc(sizeof(LEX)); memset(lc, 0, sizeof(LEX)); - lc->scan_error = scan_error; + if (scan_error) { + lc->scan_error = scan_error; + } else { + lc->scan_error = s_err; + } + bstrncpy(lc->str, cf, sizeof(lc->str)); + lc->fname = lc->str; berrno be; scan_err2(lc, _("Cannot open config file %s: %s\n"), lc->str, be.strerror()); @@ -766,96 +772,96 @@ parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error) } while ((token=lex_get_token(lc, T_ALL)) != T_EOF) { Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token)); - switch (state) { - case p_none: - if (token == T_EOL) { - break; - } - if (token != T_IDENTIFIER) { + switch (state) { + case p_none: + if (token == T_EOL) { + break; + } + if (token != T_IDENTIFIER) { scan_err1(lc, _("Expected a Resource name identifier, got: %s"), lc->str); - return 0; - } - for (i=0; resources[i].name; i++) - if (strcasecmp(resources[i].name, lc->str) == 0) { - state = p_resource; - items = resources[i].items; - res_type = resources[i].rcode; - init_resource(res_type, items, pass); - break; - } - if (state == p_none) { + return 0; + } + for (i=0; resources[i].name; i++) + if (strcasecmp(resources[i].name, lc->str) == 0) { + state = p_resource; + items = resources[i].items; + res_type = resources[i].rcode; + init_resource(res_type, items, pass); + break; + } + if (state == p_none) { scan_err1(lc, _("expected resource name, got: %s"), lc->str); return 0; - } - break; - case p_resource: - switch (token) { - case T_BOB: - level++; - break; - case T_IDENTIFIER: - if (level != 1) { + } + break; + case p_resource: + switch (token) { + case T_BOB: + level++; + break; + case T_IDENTIFIER: + if (level != 1) { scan_err1(lc, _("not in resource definition: %s"), lc->str); - return 0; - } - for (i=0; items[i].name; i++) { - if (strcasecmp(items[i].name, lc->str) == 0) { - /* If the ITEM_NO_EQUALS flag is set we do NOT - * scan for = after the keyword */ - if (!(items[i].flags & ITEM_NO_EQUALS)) { - token = lex_get_token(lc, T_SKIP_EOL); + return 0; + } + for (i=0; items[i].name; i++) { + if (strcasecmp(items[i].name, lc->str) == 0) { + /* If the ITEM_NO_EQUALS flag is set we do NOT + * scan for = after the keyword */ + if (!(items[i].flags & ITEM_NO_EQUALS)) { + token = lex_get_token(lc, T_SKIP_EOL); Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token)); - if (token != T_EQUALS) { + if (token != T_EQUALS) { scan_err1(lc, _("expected an equals, got: %s"), lc->str); - return 0; - } - } + return 0; + } + } Dmsg1(900, "calling handler for %s\n", items[i].name); - /* Call item handler */ - items[i].handler(lc, &items[i], i, pass); - i = -1; - break; - } - } - if (i >= 0) { + /* Call item handler */ + items[i].handler(lc, &items[i], i, pass); + i = -1; + break; + } + } + if (i >= 0) { Dmsg2(900, "level=%d id=%s\n", level, lc->str); Dmsg1(900, "Keyword = %s\n", lc->str); scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n" "Perhaps you left the trailing brace off of the previous resource."), lc->str); - return 0; - } - break; + return 0; + } + break; - case T_EOB: - level--; - state = p_none; + case T_EOB: + level--; + state = p_none; Dmsg0(900, "T_EOB => define new resource\n"); - save_resource(res_type, items, pass); /* save resource */ - break; + save_resource(res_type, items, pass); /* save resource */ + break; - case T_EOL: - break; + case T_EOL: + break; - default: + default: scan_err2(lc, _("unexpected token %d %s in resource definition"), - token, lex_tok_to_str(token)); - return 0; - } - break; - default: + token, lex_tok_to_str(token)); + return 0; + } + break; + default: scan_err1(lc, _("Unknown parser state %d\n"), state); - return 0; - } + return 0; + } } if (state != p_none) { scan_err0(lc, _("End of conf file reached with unclosed resource.")); - return 0; + return 0; } if (debug_level >= 900 && pass == 2) { - int i; - for (i=r_first; i<=r_last; i++) { - dump_resource(i, res_head[i-r_first], prtmsg, NULL); - } + int i; + for (i=r_first; i<=r_last; i++) { + dump_resource(i, res_head[i-r_first], prtmsg, NULL); + } } lc = lex_close_file(lc); } @@ -865,7 +871,7 @@ parse_config(const char *cf, LEX_ERROR_HANDLER *scan_error) /********************************************************************* * - * Free configuration resources + * Free configuration resources * */ void free_config_resources() diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index ab636cc971..ec9b7e70df 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -150,6 +150,7 @@ int lex_get_char (LEX *lf); void lex_unget_char (LEX *lf); const char * lex_tok_to_str (int token); int lex_get_token (LEX *lf, int expect); +void s_err(const char *file, int line, LEX *lc, const char *msg, ...); /* message.c */ void my_name_is (int argc, char *argv[], const char *name); diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index a84c238a22..0fb5fcfa16 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -202,7 +202,7 @@ static bool do_get_volume_info(DCR *dcr) * VolStatus==Recycle) * false on failure * - * Volume information returned in jcr + * Volume information returned in dcr->VolCatInfo */ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) { diff --git a/bacula/src/stored/autochanger.c b/bacula/src/stored/autochanger.c index 37885f571e..84bfae83f1 100644 --- a/bacula/src/stored/autochanger.c +++ b/bacula/src/stored/autochanger.c @@ -210,23 +210,6 @@ static void unlock_changer(DCR *dcr) } -/* - * The Volume is not in the correct slot, so mark this - * Volume as not being in the Changer. - */ -void mark_volume_not_inchanger(DCR *dcr) -{ - JCR *jcr = dcr->jcr; - DEVICE *dev = dcr->dev; - Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n" -" Setting InChanger to zero in catalog.\n"), - dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot); - dcr->VolCatInfo.InChanger = false; - dev->VolCatInfo.InChanger = false; - Dmsg0(400, "update vol info in mount\n"); - dir_update_volume_info(dcr, true); /* set new status */ -} - /* * List the Volumes that are in the autoloader possibly * with their barcodes. diff --git a/bacula/src/stored/mount.c b/bacula/src/stored/mount.c index 086e7fbc33..c089b1268a 100644 --- a/bacula/src/stored/mount.c +++ b/bacula/src/stored/mount.c @@ -30,6 +30,8 @@ #include "bacula.h" /* pull in global headers */ #include "stored.h" /* pull in Storage Deamon headers */ +static void mark_volume_not_inchanger(DCR *dcr); + /* * If release is set, we rewind the current volume, @@ -113,8 +115,6 @@ mount_next_vol: * file. If it is a tape, we check the volume name * and move the tape to the end of data. * - * It assumes that the device is not already in use! - * */ if (autoload_device(dcr, 1, NULL) > 0) { autochanger = true; @@ -209,7 +209,7 @@ read_volume: recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0; break; /* got a Volume */ case VOL_NAME_ERROR: - VOLUME_CAT_INFO VolCatInfo; + VOLUME_CAT_INFO VolCatInfo, devVolCatInfo; /* If not removable, Volume is broken */ if (!dev_cap(dev, CAP_REM)) { @@ -229,25 +229,33 @@ read_volume: } /* * OK, we got a different volume mounted. First save the - * requested Volume info (jcr) structure, then query if + * requested Volume info (dcr) structure, then query if * this volume is really OK. If not, put back the desired - * volume name and continue. + * volume name, mark it not in changer and continue. */ memcpy(&VolCatInfo, &dcr->VolCatInfo, sizeof(VolCatInfo)); + memcpy(&devVolCatInfo, &dev->VolCatInfo, sizeof(devVolCatInfo)); /* Check if this is a valid Volume in the pool */ bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName)); if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE)) { + /* Restore desired volume name, note device info out of sync */ + /* This gets the info regardless of the Pool */ + if (autochanger && dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) { + mark_volume_not_inchanger(dcr); + } + memcpy(&dev->VolCatInfo, &devVolCatInfo, sizeof(dev->VolCatInfo)); bstrncpy(dev->BadVolName, dev->VolHdr.VolName, sizeof(dev->BadVolName)); Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n" " Current Volume \"%s\" not acceptable because:\n" " %s"), VolCatInfo.VolCatName, dev->VolHdr.VolName, jcr->dir_bsock->msg); - /* Restore desired volume name, note device info out of sync */ - memcpy(&dcr->VolCatInfo, &VolCatInfo, sizeof(dcr->VolCatInfo)); ask = true; goto mount_next_vol; } + /* This was not the volume we expected, but it is OK with + * the Director, so use it. + */ Dmsg1(100, "want new name=%s\n", dcr->VolumeName); memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0; @@ -276,6 +284,7 @@ read_volume: if (!write_new_volume_label_to_dev(dcr, dcr->VolumeName, dcr->pool_name)) { Dmsg0(100, "!write_vol_label\n"); + mark_volume_in_error(dcr); goto mount_next_vol; } Dmsg0(100, "dir_update_vol_info. Set Append\n"); @@ -293,9 +302,6 @@ read_volume: Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"), dcr->VolumeName, dev->print_name()); mark_volume_in_error(dcr); - if (autochanger) { - mark_volume_not_inchanger(dcr); - } goto mount_next_vol; } /* NOTE! Fall-through wanted. */ @@ -330,6 +336,7 @@ read_volume: */ if (dev->VolHdr.LabelType == PRE_LABEL || recycle) { if (!rewrite_volume_label(dcr, recycle)) { + mark_volume_in_error(dcr); goto mount_next_vol; } } else { @@ -391,11 +398,31 @@ void mark_volume_in_error(DCR *dcr) DEVICE *dev = dcr->dev; Jmsg(dcr->jcr, M_INFO, 0, _("Marking Volume \"%s\" in Error in Catalog.\n"), dcr->VolumeName); + memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus)); Dmsg0(100, "dir_update_vol_info. Set Error.\n"); dir_update_volume_info(dcr, false); } +/* + * The Volume is not in the correct slot, so mark this + * Volume as not being in the Changer. + */ +static void mark_volume_not_inchanger(DCR *dcr) +{ + JCR *jcr = dcr->jcr; + DEVICE *dev = dcr->dev; + Jmsg(jcr, M_ERROR, 0, _("Autochanger Volume \"%s\" not found in slot %d.\n" +" Setting InChanger to zero in catalog.\n"), + dcr->VolCatInfo.VolCatName, dcr->VolCatInfo.Slot); + memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); + dcr->VolCatInfo.InChanger = false; + dev->VolCatInfo.InChanger = false; + Dmsg0(400, "update vol info in mount\n"); + dir_update_volume_info(dcr, true); /* set new status */ +} + + /* * If we are reading, we come here at the end of the tape * and see if there are more volumes to be mounted. diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index e99e42f195..93171916f5 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -59,7 +59,6 @@ int authenticate_filed(JCR *jcr); /* From autochanger.c */ int autoload_device(DCR *dcr, int writing, BSOCK *dir); bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd); -void mark_volume_not_inchanger(DCR *dcr); char *edit_device_codes(DCR *dcr, char *omsg, const char *imsg, const char *cmd); /* From block.c */ -- 2.39.5