From 084a8bdcbcc0b84ea983d9390861906c1bd04340 Mon Sep 17 00:00:00 2001 From: Dave Wysochanski Date: Wed, 25 Apr 2007 20:38:39 +0000 Subject: [PATCH] Add support functions for analysis of config sections, and hence, on-disk LVM2 metadata. -- --- WHATS_NEW | 1 + lib/config/config.c | 73 +++++++++++++++++++++++++++++++++++++++++---- lib/config/config.h | 2 ++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 0f3e9f1d5..5212f281d 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.25 - ================================= + Add support functions for analysis of config sections Update pvck to read labels on disk, with --labelsector parameter Add count_chars and count_chars_len functions Add /sys/block listings to lvm_dump.sh diff --git a/lib/config/config.c b/lib/config/config.c index 6c7128a41..fdfc3b5ef 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -19,6 +19,7 @@ #include "device.h" #include "str_list.h" #include "toolcontext.h" +#include "lvm-string.h" #include #include @@ -26,6 +27,9 @@ #include #include +#define SECTION_B_CHAR '{' +#define SECTION_E_CHAR '}' + enum { TOK_INT, TOK_FLOAT, @@ -474,7 +478,7 @@ static struct config_node *_file(struct parser *p) static struct config_node *_section(struct parser *p) { - /* IDENTIFIER '{' VALUE* '}' */ + /* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */ struct config_node *root, *n, *l = NULL; if (!(root = _create_node(p))) { stack; @@ -623,12 +627,12 @@ static void _get_token(struct parser *p, int tok_prev) p->t = TOK_INT; /* fudge so the fall through for floats works */ switch (*p->te) { - case '{': + case SECTION_B_CHAR: p->t = TOK_SECTION_B; p->te++; break; - case '}': + case SECTION_E_CHAR: p->t = TOK_SECTION_E; p->te++; break; @@ -708,8 +712,9 @@ static void _get_token(struct parser *p, int tok_prev) default: p->t = TOK_IDENTIFIER; while ((p->te != p->fe) && (*p->te) && !isspace(*p->te) && - (*p->te != '#') && (*p->te != '=') && (*p->te != '{') && - (*p->te != '}')) + (*p->te != '#') && (*p->te != '=') && + (*p->te != SECTION_B_CHAR) && + (*p->te != SECTION_E_CHAR)) p->te++; break; } @@ -1146,3 +1151,61 @@ int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft, return 1; } + +/* + * Convert a token type to the char it represents. + */ +static char _token_type_to_char(int type) +{ + switch (type) { + case TOK_SECTION_B: + return SECTION_B_CHAR; + case TOK_SECTION_E: + return SECTION_E_CHAR; + default: + return 0; + } +} + +/* + * Returns: + * # of 'type' tokens in 'str'. + */ +static unsigned _count_tokens (const char *str, unsigned len, int type) +{ + char c; + + c = _token_type_to_char(type); + + return(count_chars_len(str, len, c)); +} + +/* + * Heuristic function to make a quick guess as to whether a text + * region probably contains a valid config "section". (Useful for + * scanning areas of the disk for old metadata.) + * Config sections contain various tokens, may contain other sections + * and strings, and are delimited by begin (type 'TOK_SECTION_B') and + * end (type 'TOK_SECTION_E') tokens. As a quick heuristic, we just + * count the number of begin and end tokens, and see if they are + * non-zero and the counts match. + * Full validation of the section should be done with another function + * (for example, read_config_fd). + * + * Returns: + * 0 - probably is not a valid config section + * 1 - probably _is_ a valid config section + */ +unsigned maybe_config_section(const char *str, unsigned len) +{ + int begin_count; + int end_count; + + begin_count = _count_tokens(str, len, TOK_SECTION_B); + end_count = _count_tokens(str, len, TOK_SECTION_E); + + if (begin_count && end_count && (begin_count - end_count == 0)) + return 1; + else + return 0; +} diff --git a/lib/config/config.h b/lib/config/config.h index f51190fff..c5d594b35 100644 --- a/lib/config/config.h +++ b/lib/config/config.h @@ -108,4 +108,6 @@ int get_config_uint64(const struct config_node *cn, const char *path, int get_config_str(const struct config_node *cn, const char *path, char **result); +unsigned maybe_config_section(const char *str, unsigned len); + #endif