diff options
author | Peter Rajnoha <prajnoha@redhat.com> | 2012-02-15 11:39:38 +0000 |
---|---|---|
committer | Peter Rajnoha <prajnoha@redhat.com> | 2012-02-15 11:39:38 +0000 |
commit | bd364a70b5bd063d5756d992ea00797f671abe4c (patch) | |
tree | cd8971d067142e04df80cb8d4c505cf912d326a8 /libdm/libdm-common.c | |
parent | 2e8c7f297516c67e16aa4ea038638bd27ff53404 (diff) | |
download | lvm2-bd364a70b5bd063d5756d992ea00797f671abe4c.tar.gz lvm2-bd364a70b5bd063d5756d992ea00797f671abe4c.tar.xz lvm2-bd364a70b5bd063d5756d992ea00797f671abe4c.zip |
Add dm_task_get_name_mangled/unmangled to libdevmapper.
dm_task_get_name_mangled will always return mangled form of the name while
the dm_task_get_name_unmangled will always return unmangled form of the name
irrespective of the global setting (dm_set/get_name_mangling_mode).
This is handy in situations where we need to detect whether the name is already
mangled or not. Also display functions make use of it.
Diffstat (limited to 'libdm/libdm-common.c')
-rw-r--r-- | libdm/libdm-common.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c index 16053244..b5ebcfd8 100644 --- a/libdm/libdm-common.c +++ b/libdm/libdm-common.c @@ -393,6 +393,53 @@ bad2: return -1; } +/* + * Try to unmangle supplied string. + * Return value: -1 on error, 0 when no unmangling needed, 1 when unmangling applied + */ +int unmangle_name(const char *str, size_t len, char *buf, + size_t buf_len, dm_string_mangling_t mode) +{ + char str_rest[DM_NAME_LEN]; + size_t i, j; + int code; + int r = 0; + + if (!str || !buf) + return -1; + + /* Is there anything to do at all? */ + if (!*str || !len || mode == DM_STRING_MANGLING_NONE) + return 0; + + if (buf_len < DM_NAME_LEN) { + log_error(INTERNAL_ERROR "unmangle_name: supplied buffer too small"); + return -1; + } + + for (i = 0, j = 0; str[i]; i++, j++) { + if (str[i] == '\\' && str[i+1] == 'x') { + if (!sscanf(&str[i+2], "%2x%s", &code, str_rest)) { + log_debug("Hex encoding mismatch detected in \"%s\" " + "while trying to unmangle it.", str); + goto out; + } + buf[j] = (unsigned char) code; + + /* skip the encoded part we've just decoded! */ + i+= 3; + + /* unmangling applied */ + r = 1; + } else + buf[j] = str[i]; + } + +out: + buf[j] = '\0'; + return r; +} + static int _dm_task_set_name(struct dm_task *dmt, const char *name, dm_string_mangling_t mangling_mode) { @@ -490,6 +537,47 @@ const char *dm_task_get_name(const struct dm_task *dmt) return (dmt->dmi.v4->name); } +char *dm_task_get_name_mangled(const struct dm_task *dmt) +{ + const char *s = dm_task_get_name(dmt); + char buf[DM_NAME_LEN]; + char *rs = NULL; + int r; + + /* + * We're using 'auto mangling' here. If the name is already mangled, + * this is detected and we keep it as it is. If the name is not mangled, + * we do mangle it. This way we always get a mangled form of the name. + */ + if ((r = mangle_name(s, strlen(s), buf, sizeof(buf), + DM_STRING_MANGLING_AUTO)) < 0) + log_error("Failed to mangle device name \"%s\".", s); + else if (!(rs = r ? dm_strdup(buf) : dm_strdup(s))) + log_error("dm_task_get_name_mangled: dm_strdup failed"); + + return rs; +} + +char *dm_task_get_name_unmangled(const struct dm_task *dmt) +{ + const char *s = dm_task_get_name(dmt); + char buf[DM_NAME_LEN]; + char *rs = NULL; + int r; + + /* + * We just want to unmangle the string. + * Both auto and hex mode will do it. + */ + if ((r = unmangle_name(s, strlen(s), buf, sizeof(buf), + DM_STRING_MANGLING_AUTO)) < 0) + log_error("Failed to unmangle device name \"%s\".", s); + else if (!(rs = r ? dm_strdup(buf) : dm_strdup(s))) + log_error("dm_task_get_name_unmangled: dm_strdup failed"); + + return rs; +} + int dm_task_set_newname(struct dm_task *dmt, const char *newname) { dm_string_mangling_t mangling_mode = dm_get_name_mangling_mode(); |