locale-util: Update musl's default locale search paths

musl libc got a overhaul in it's locale support funded by NLnet,
as part the default search paths were set to search in
/etc/musl/locale, /usr/share/musl/locale, /share/musl/locale/.

Also change the behaviour on musl to search for multiple directories,
and include the old path as a fallback.

See https://www.openwall.com/lists/musl/2026/10/02/1

(cherry picked from commit 0f655ffc7b3318abae41869ca192e1817586a985)
This commit is contained in:
Achill Gilgenast
2026-10-16 17:24:51 +01:00
committed by Luca Boccassi
parent 3e39c54632
commit 934e31fac0
2 changed files with 39 additions and 23 deletions
+36 -22
View File
@@ -56,16 +56,11 @@ static char* normalize_locale(const char *name) {
return strdup(name);
}
static const char* get_locale_dir(void) {
return secure_getenv("SYSTEMD_LOCALE_DIRECTORY") ?:
#ifdef __GLIBC__
"/usr/lib/locale/";
#else
"/usr/share/i18n/locales/musl/";
#endif
static const char* get_locale_dir(void) {
return secure_getenv("SYSTEMD_LOCALE_DIRECTORY") ?: "/usr/lib/locale/";
}
#ifdef __GLIBC__
static int add_locales_from_archive(Set *locales) {
/* Stolen from glibc... */
@@ -201,26 +196,38 @@ static int add_locales_from_libdir(Set *locales) {
#else
static const char* const musl_locale_dirs[] = {
"/etc/musl/locale",
"/usr/share/musl/locale",
"/share/musl/locale",
"/usr/share/i18n/locales/musl", // compat with musl-locales 0.1.0
NULL
};
static int add_locales_for_musl(Set *locales) {
int r;
assert(locales);
_cleanup_closedir_ DIR *dir = opendir(get_locale_dir());
if (!dir)
return errno == ENOENT ? 0 : -errno;
const char *e = secure_getenv("SYSTEMD_LOCALE_DIRECTORY");
FOREACH_DIRENT(de, dir, return -errno) {
if (de->d_type != DT_REG)
STRV_FOREACH(d, e ? STRV_MAKE_CONST(e) : musl_locale_dirs) {
_cleanup_closedir_ DIR *dir = opendir(*d);
if (!dir)
continue;
char *z = normalize_locale(de->d_name);
if (!z)
return -ENOMEM;
FOREACH_DIRENT(de, dir, return -errno) {
if (de->d_type != DT_REG)
continue;
r = set_consume(locales, z);
if (r < 0)
return r;
char *z = normalize_locale(de->d_name);
if (!z)
return -ENOMEM;
r = set_consume(locales, z);
if (r < 0)
return r;
}
}
return 0;
@@ -330,11 +337,18 @@ int locale_is_installed(const char *name) {
/* musl's newlocale() always succeeds and provides a fake locale object even when the locale does
* not exist. Hence, we need to explicitly check if the locale file exists. */
_cleanup_free_ char *p = path_join(get_locale_dir(), name);
if (!p)
return -ENOMEM;
const char *e = secure_getenv("SYSTEMD_LOCALE_DIRECTORY");
return access(p, F_OK) >= 0;
STRV_FOREACH(d, e ? STRV_MAKE_CONST(e) : musl_locale_dirs) {
_cleanup_free_ char *p = path_join(*d, name);
if (!p)
return -ENOMEM;
if (access(p, F_OK) >= 0)
return true;
}
return false;
#endif
}