From 97b023f94f1d79a19bc0489c0d167bdaebb765fd Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 3 Apr 2009 16:46:45 +0200 Subject: fix volume label parsing Not probing volumes ourselves and reading from the udev db (commit 79b92dbdf65b8c978d5a8f6fb2b421aac83c3de3) caused a regression: udevadm info's ID_FS_LABEL is mangled, e. g. spaces appear as '_'. Use ID_FS_LABEL_ENC instead and use a new hal/util.c function hal_util_decode_escape() to decode those. https://launchpad.net/bugs/347370 --- hald/linux/coldplug.c | 7 +++++-- hald/linux/osspec.c | 10 +++++++--- hald/util.c | 33 +++++++++++++++++++++++++++++++++ hald/util.h | 2 ++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/hald/linux/coldplug.c b/hald/linux/coldplug.c index 16fa34ce..276382d8 100644 --- a/hald/linux/coldplug.c +++ b/hald/linux/coldplug.c @@ -159,6 +159,7 @@ hal_util_init_sysfs_to_udev_map (void) int udevinfo_exitcode; UdevInfo *info = NULL; char *p; + int len; sysfs_to_udev_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, udev_info_free); @@ -252,8 +253,10 @@ hal_util_init_sysfs_to_udev_map (void) info->fsversion = &line[17]; } else if (strncmp(line, "E: ID_FS_UUID=", 14) == 0) { info->fsuuid = &line[14]; - } else if (strncmp(line, "E: ID_FS_LABEL=", 15) == 0) { - info->fslabel = &line[15]; + } else if (strncmp(line, "E: ID_FS_LABEL_ENC=", 19) == 0) { + len = strlen (&line[15]); + info->fslabel = g_malloc0 (len + 1); + hal_util_decode_escape (&line[19], info->fslabel, len + 1); } } diff --git a/hald/linux/osspec.c b/hald/linux/osspec.c index 4599c7cf..56e3b654 100644 --- a/hald/linux/osspec.c +++ b/hald/linux/osspec.c @@ -128,7 +128,7 @@ hald_udev_data (GIOChannel *source, GIOCondition condition, gpointer user_data) while (bufpos < sizeof (buf)) { size_t keylen; char *key; - char *str; + char *str, *dstr; key = &buf[bufpos]; keylen = strlen(key); @@ -206,11 +206,15 @@ hald_udev_data (GIOChannel *source, GIOCondition condition, gpointer user_data) g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid)); g_free (str); } - } else if (strncmp(key, "ID_FS_LABEL=", 12) == 0) { - if ((str = hal_util_strdup_valid_utf8(&key[12])) != NULL ) { + } else if (strncmp(key, "ID_FS_LABEL_ENC=", 16) == 0) { + dstr = g_malloc0 (keylen - 15); + hal_util_decode_escape (&key[16], dstr, sizeof(hotplug_event->sysfs.fslabel)); + + if ((str = hal_util_strdup_valid_utf8(dstr)) != NULL ) { g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel)); g_free (str); } + g_free (dstr); } } diff --git a/hald/util.c b/hald/util.c index c7f80abe..7fa3011b 100644 --- a/hald/util.c +++ b/hald/util.c @@ -1228,3 +1228,36 @@ is_valid_interface_name (const char *name) { return TRUE; } +static int +hexdigit (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a'; + if (c >= 'A' && c <= 'F') + return c - 'A'; + HAL_ERROR (("'%c' is not a valid hex digit", c)); + return 0; +} + +/* Decode string with \xNN escapes */ +void +hal_util_decode_escape (const char* src, char* result, int maxlen) +{ + int len; + + if (src == NULL || maxlen == 0) + return; + + for (len = 0; len < maxlen && *src; ++len) { + /* note that C's short-circuiting avoids reading past \0 */ + if (*src == '\\' && src[1] == 'x' && isalnum (src[2]) && isalnum (src[3])) { + result[len] = (hexdigit(src[2]) << 4) | hexdigit(src[3]); + src += 4; + } else + result[len] = *src++; + } +} + + diff --git a/hald/util.h b/hald/util.h index 5377e359..c2a1584b 100644 --- a/hald/util.h +++ b/hald/util.h @@ -117,4 +117,6 @@ char *hal_util_readlink (const char *link); gboolean is_valid_interface_name (const char *name); +void hal_util_decode_escape (const char* src, char* result, int maxlen); + #endif /* UTIL_H */ -- cgit v1.2.3