From cffd63468149a2364c62cc1697c7167c8c733998 Mon Sep 17 00:00:00 2001 From: Peter Rajnoha Date: Thu, 23 Sep 2010 12:02:33 +0000 Subject: [PATCH] Add escape sequence for ':' and '@' found in device names used as PVs. --- WHATS_NEW | 1 + lib/metadata/metadata.c | 1 + lib/misc/lvm-string.c | 54 ++++++++++++++++++++++++++++++++++------- lib/misc/lvm-string.h | 9 +++++++ tools/pvchange.c | 4 ++- tools/pvck.c | 1 + tools/pvcreate.c | 2 ++ tools/pvmove.c | 17 ++++++------- tools/pvremove.c | 1 + tools/toollib.c | 28 ++++++++++----------- tools/vgsplit.c | 1 + 11 files changed, 86 insertions(+), 33 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 4bbeb0a11..4f8c611a4 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.74 - ===================================== + Add escape sequence for ':' and '@' found in device names used as PVs. Replace alloca with dm_malloc in _aligned_io. Fix partial mode operations for lvm1 metadata format. Track recursive filter iteration to avoid refreshing while in use. (2.02.56) diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index d14c33c74..405b08978 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -677,6 +677,7 @@ int vg_extend(struct volume_group *vg, int pv_count, char **pv_names, /* attach each pv */ for (i = 0; i < pv_count; i++) { + unescape_colons_and_at_signs(pv_names[i], NULL, NULL); if (!vg_extend_single_pv(vg, pv_names[i], pp)) goto bad; } diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c index 82a3e948c..960157e96 100644 --- a/lib/misc/lvm-string.c +++ b/lib/misc/lvm-string.c @@ -109,19 +109,31 @@ static void _quote_characters(char **out, const char *src, } /* - * Unquote orig_char in string. - * Also unquote quote_char. + * Unquote each character given in orig_char array and unquote quote_char + * as well. The array ends up with '\0' character. Also save the first + * occurence of each character from orig_char that was found unquoted in + * arr_substr_first_unquoted array. This way we can process several + * characters in one go. */ -static void _unquote_characters(char *src, const int orig_char, - const int quote_char) +static void _unquote_characters(char *src, const int orig_chars[], + const int quote_char, + char *arr_substr_first_unquoted[]) { char *out = src; + int c; + int i; while (*src) { - if (*src == quote_char && - (*(src + 1) == orig_char || *(src + 1) == quote_char)) - src++; - + for (i = 0; (c = orig_chars[i]); i++) { + if (*src == quote_char && + (*(src + 1) == c || *(src + 1) == quote_char)) { + src++; + break; + } + else if (arr_substr_first_unquoted && (*src == c) && + !arr_substr_first_unquoted[i]) + arr_substr_first_unquoted[i] = out; + } *out++ = *src++; } @@ -217,7 +229,31 @@ char *escape_double_quotes(char *out, const char *src) */ void unescape_double_quotes(char *src) { - _unquote_characters(src, '\"', '\\'); + const int orig_chars[] = {'\"', '\0'}; + + _unquote_characters(src, orig_chars, '\\', NULL); +} + +/* + * Unescape colons and "at" signs in situ and save the substrings + * starting at the position of the first unescaped colon and the + * first unescaped "at" sign. This is normally used to unescape + * device names used as PVs. + */ +void unescape_colons_and_at_signs(char *src, + char **substr_first_unquoted_colon, + char **substr_first_unquoted_at_sign) +{ + const int orig_chars[] = {':', '@', '\0'}; + char *arr_substr_first_unquoted[] = {NULL, NULL, NULL}; + + _unquote_characters(src, orig_chars, '\\', arr_substr_first_unquoted); + + if (substr_first_unquoted_colon) + *substr_first_unquoted_colon = arr_substr_first_unquoted[0]; + + if (substr_first_unquoted_at_sign) + *substr_first_unquoted_at_sign = arr_substr_first_unquoted[1]; } /* diff --git a/lib/misc/lvm-string.h b/lib/misc/lvm-string.h index 35d924588..a41717874 100644 --- a/lib/misc/lvm-string.h +++ b/lib/misc/lvm-string.h @@ -60,4 +60,13 @@ char *escape_double_quotes(char *out, const char *src); */ void unescape_double_quotes(char *src); +/* + * Unescape colons and at signs in situ and save the substring starting + * at the position of the first unescaped colon and the first unescaped + * "at" sign. + */ +void unescape_colons_and_at_signs(char *src, + char **substr_first_unquoted_colon, + char **substr_first_unquoted_at_sign); + #endif diff --git a/tools/pvchange.c b/tools/pvchange.c index 47b2a2717..0758cb65b 100644 --- a/tools/pvchange.c +++ b/tools/pvchange.c @@ -195,7 +195,8 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv) int total = 0; struct volume_group *vg; - const char *pv_name, *vg_name; + const char *vg_name; + char *pv_name; struct pv_list *pvl; struct dm_list *vgnames; @@ -223,6 +224,7 @@ int pvchange(struct cmd_context *cmd, int argc, char **argv) log_verbose("Using physical volume(s) on command line"); for (; opt < argc; opt++) { pv_name = argv[opt]; + unescape_colons_and_at_signs(pv_name, NULL, NULL); vg_name = find_vgname_from_pvname(cmd, pv_name); if (!vg_name) { log_error("Failed to read physical volume %s", diff --git a/tools/pvck.c b/tools/pvck.c index 1b878d14a..2ec75976f 100644 --- a/tools/pvck.c +++ b/tools/pvck.c @@ -31,6 +31,7 @@ int pvck(struct cmd_context *cmd, int argc, char **argv) /* FIXME: warning and/or check if in use? */ log_verbose("Scanning %s", argv[i]); + unescape_colons_and_at_signs(argv[i], NULL, NULL); pv_analyze(cmd, argv[i], arg_uint64_value(cmd, labelsector_ARG, UINT64_C(0))); diff --git a/tools/pvcreate.c b/tools/pvcreate.c index 23ff02faa..3dc3a3bd0 100644 --- a/tools/pvcreate.c +++ b/tools/pvcreate.c @@ -109,6 +109,8 @@ int pvcreate(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } + unescape_colons_and_at_signs(argv[i], NULL, NULL); + if (!pvcreate_single(cmd, argv[i], &pp)) { stack; ret = ECMD_FAILED; diff --git a/tools/pvmove.c b/tools/pvmove.c index 0346ca347..ce48c68ee 100644 --- a/tools/pvmove.c +++ b/tools/pvmove.c @@ -644,17 +644,16 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv) } if (argc) { - pv_name = argv[0]; + if (!(pv_name = dm_pool_strdup(cmd->mem, argv[0]))) { + log_error("Failed to clone PV name"); + return ECMD_FAILED; + } + + unescape_colons_and_at_signs(pv_name, &colon, NULL); /* Drop any PE lists from PV name */ - if ((colon = strchr(pv_name, ':'))) { - if (!(pv_name = dm_pool_strndup(cmd->mem, pv_name, - (unsigned) (colon - - pv_name)))) { - log_error("Failed to clone PV name"); - return ECMD_FAILED; - } - } + if (colon) + *colon = '\0'; if (!arg_count(cmd, abort_ARG) && (ret = _set_up_pvmove(cmd, pv_name, argc, argv)) != diff --git a/tools/pvremove.c b/tools/pvremove.c index c57df64c6..51530691e 100644 --- a/tools/pvremove.c +++ b/tools/pvremove.c @@ -144,6 +144,7 @@ int pvremove(struct cmd_context *cmd, int argc, char **argv) } for (i = 0; i < argc; i++) { + unescape_colons_and_at_signs(argv[i], NULL, NULL); r = pvremove_single(cmd, argv[i], NULL); if (r > ret) ret = r; diff --git a/tools/toollib.c b/tools/toollib.c index 5da30f46b..02c496248 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -680,7 +680,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv, struct dm_list *pvslist, *vgnames; struct dm_list tags; struct str_list *sll; - char *tagname; + char *at_sign, *tagname; int scanned = 0; struct dm_list mdas; @@ -694,8 +694,9 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv, if (argc) { log_verbose("Using physical volume(s) on command line"); for (; opt < argc; opt++) { - if (*argv[opt] == '@') { - tagname = argv[opt] + 1; + unescape_colons_and_at_signs(argv[opt], NULL, &at_sign); + if (at_sign && (at_sign == argv[opt])) { + tagname = at_sign + 1; if (!validate_name(tagname)) { log_error("Skipping invalid tag %s", @@ -1093,8 +1094,8 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int struct dm_list *r; struct pv_list *pvl; struct dm_list tags, arg_pvnames; - const char *pvname = NULL; - char *colon, *tagname; + char *pvname = NULL; + char *colon, *at_sign, *tagname; int i; /* Build up list of PVs */ @@ -1108,8 +1109,10 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int dm_list_init(&arg_pvnames); for (i = 0; i < argc; i++) { - if (*argv[i] == '@') { - tagname = argv[i] + 1; + unescape_colons_and_at_signs(argv[i], &colon, &at_sign); + + if (at_sign && (at_sign == argv[i])) { + tagname = at_sign + 1; if (!validate_name(tagname)) { log_error("Skipping invalid tag %s", tagname); continue; @@ -1128,13 +1131,10 @@ struct dm_list *create_pv_list(struct dm_pool *mem, struct volume_group *vg, int pvname = argv[i]; - if ((colon = strchr(pvname, ':'))) { - if (!(pvname = dm_pool_strndup(mem, pvname, - (unsigned) (colon - - pvname)))) { - log_error("Failed to clone PV name"); - return NULL; - } + if (colon && !(pvname = dm_pool_strndup(mem, pvname, + (unsigned) (colon - pvname)))) { + log_error("Failed to clone PV name"); + return NULL; } if (!(pvl = find_pv_in_vg(vg, pvname))) { diff --git a/tools/vgsplit.c b/tools/vgsplit.c index 63de1b86d..e6a65111c 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -394,6 +394,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) /* Move PVs across to new structure */ for (opt = 0; opt < argc; opt++) { + unescape_colons_and_at_signs(argv[opt], NULL, NULL); if (!move_pv(vg_from, vg_to, argv[opt])) goto_bad; } -- 2.43.5