From 13f45806268bca2c20caee4d042f12dfe68f5a1f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Jul 2019 13:37:13 +0200 Subject: [PATCH] locale-util: normalize UTF-8 locale names Let's generate out lists in the format people expect. --- src/basic/locale-util.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index ce9daffa7b4..17302abf58e 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -27,6 +27,40 @@ #include "strv.h" #include "utf8.h" +static char *normalize_locale(const char *name) { + const char *e; + + /* Locale names are weird: glibc has some magic rules when looking for the charset name on disk: it + * lowercases everything, and removes most special chars. This means the official .UTF-8 suffix + * becomes .utf8 when looking things up on disk. When enumerating locales, let's do the reverse + * operation, and go back to ".UTF-8" which appears to be the more commonly accepted name. We only do + * that for UTF-8 however, since it's kinda the only charset that matters. */ + + e = endswith(name, ".utf8"); + if (e) { + _cleanup_free_ char *prefix = NULL; + + prefix = strndup(name, e - name); + if (!prefix) + return NULL; + + return strjoin(prefix, ".UTF-8"); + } + + e = strstr(name, ".utf8@"); + if (e) { + _cleanup_free_ char *prefix = NULL; + + prefix = strndup(name, e - name); + if (!prefix) + return NULL; + + return strjoin(prefix, ".UTF-8@", e + 6); + } + + return strdup(name); +} + static int add_locales_from_archive(Set *locales) { /* Stolen from glibc... */ @@ -107,7 +141,7 @@ static int add_locales_from_archive(Set *locales) { if (!utf8_is_valid((char*) p + e[i].name_offset)) continue; - z = strdup((char*) p + e[i].name_offset); + z = normalize_locale((char*) p + e[i].name_offset); if (!z) { r = -ENOMEM; goto finish; @@ -144,7 +178,7 @@ static int add_locales_from_libdir (Set *locales) { if (entry->d_type != DT_DIR) continue; - z = strdup(entry->d_name); + z = normalize_locale(entry->d_name); if (!z) return -ENOMEM; -- 2.47.3