From d73ba2caa10b8e9f51ff4239cc32eeb4e0de4279 Mon Sep 17 00:00:00 2001 Message-Id: From: Josselin Poiret Date: Sat, 13 May 2023 14:10:43 +0200 Subject: [PATCH] Add versioned locpath From: Josselin Poiret --- locale/newlocale.c | 15 ++-------- locale/setlocale.c | 68 +++++++++++++++++++++++++++++++++++++------- string/Makefile | 1 + string/argz-suffix.c | 56 ++++++++++++++++++++++++++++++++++++ string/argz.h | 10 +++++++ 5 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 string/argz-suffix.c diff --git a/locale/newlocale.c b/locale/newlocale.c index 108d2428bf..6218e0fa77 100644 --- a/locale/newlocale.c +++ b/locale/newlocale.c @@ -29,6 +29,7 @@ /* Lock for protecting global data. */ __libc_rwlock_define (extern , __libc_setlocale_lock attribute_hidden) +extern error_t compute_locale_search_path (char **, size_t *); /* Use this when we come along an error. */ #define ERROR_RETURN \ @@ -47,7 +48,6 @@ __newlocale (int category_mask, const char *locale, locale_t base) locale_t result_ptr; char *locale_path; size_t locale_path_len; - const char *locpath_var; int cnt; size_t names_len; @@ -101,17 +101,8 @@ __newlocale (int category_mask, const char *locale, locale_t base) locale_path = NULL; locale_path_len = 0; - locpath_var = getenv ("LOCPATH"); - if (locpath_var != NULL && locpath_var[0] != '\0') - { - if (__argz_create_sep (locpath_var, ':', - &locale_path, &locale_path_len) != 0) - return NULL; - - if (__argz_add_sep (&locale_path, &locale_path_len, - _nl_default_locale_path, ':') != 0) - return NULL; - } + if (compute_locale_search_path (&locale_path, &locale_path_len) != 0) + return NULL; /* Get the names for the locales we are interested in. We either allow a composite name or a single name. */ diff --git a/locale/setlocale.c b/locale/setlocale.c index dd73fa4248..d8eb799384 100644 --- a/locale/setlocale.c +++ b/locale/setlocale.c @@ -213,12 +213,65 @@ setdata (int category, struct __locale_data *data) } } +/* Return in *LOCALE_PATH and *LOCALE_PATH_LEN the locale data search path as + a colon-separated list. Return ENOMEN on error, zero otherwise. */ +error_t +compute_locale_search_path (char **locale_path, size_t *locale_path_len) +{ + char* guix_locpath_var = getenv ("GUIX_LOCPATH"); + char *locpath_var = getenv ("LOCPATH"); + + if (guix_locpath_var != NULL && guix_locpath_var[0] != '\0') + { + /* Entries in 'GUIX_LOCPATH' take precedence over 'LOCPATH'. These + entries are systematically prefixed with "/X.Y" where "X.Y" is the + libc version. */ + if (__argz_create_sep (guix_locpath_var, ':', + locale_path, locale_path_len) != 0 + || __argz_suffix_entries (locale_path, locale_path_len, + "/" VERSION) != 0) + goto bail_out; + } + + if (locpath_var != NULL && locpath_var[0] != '\0') + { + char *reg_locale_path = NULL; + size_t reg_locale_path_len = 0; + + if (__argz_create_sep (locpath_var, ':', + ®_locale_path, ®_locale_path_len) != 0) + goto bail_out; + + if (__argz_append (locale_path, locale_path_len, + reg_locale_path, reg_locale_path_len) != 0) + goto bail_out; + + free (reg_locale_path); + } + + if (*locale_path != NULL) + { + /* Append the system default locale directory. */ + if (__argz_add_sep (locale_path, locale_path_len, + _nl_default_locale_path, ':') != 0) + goto bail_out; + } + + return 0; + + bail_out: + free (*locale_path); + *locale_path = NULL; + *locale_path_len = 0; + + return ENOMEM; +} + char * setlocale (int category, const char *locale) { char *locale_path; size_t locale_path_len; - const char *locpath_var; char *composite; /* Sanity check for CATEGORY argument. */ @@ -249,17 +302,10 @@ setlocale (int category, const char *locale) locale_path = NULL; locale_path_len = 0; - locpath_var = getenv ("LOCPATH"); - if (locpath_var != NULL && locpath_var[0] != '\0') + if (compute_locale_search_path (&locale_path, &locale_path_len) != 0) { - if (__argz_create_sep (locpath_var, ':', - &locale_path, &locale_path_len) != 0 - || __argz_add_sep (&locale_path, &locale_path_len, - _nl_default_locale_path, ':') != 0) - { - __libc_rwlock_unlock (__libc_setlocale_lock); - return NULL; - } + __libc_rwlock_unlock (__libc_setlocale_lock); + return NULL; } if (category == LC_ALL) diff --git a/string/Makefile b/string/Makefile index 3eced0d027..a7e68729ad 100644 --- a/string/Makefile +++ b/string/Makefile @@ -51,6 +51,7 @@ routines := \ argz-next \ argz-replace \ argz-stringify \ + argz-suffix \ basename \ bcopy \ bzero \ diff --git a/string/argz-suffix.c b/string/argz-suffix.c new file mode 100644 index 0000000000..505b0f248c --- /dev/null +++ b/string/argz-suffix.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ludovic Courtès . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + + +error_t +__argz_suffix_entries (char **argz, size_t *argz_len, const char *suffix) + +{ + size_t suffix_len = strlen (suffix); + size_t count = __argz_count (*argz, *argz_len); + size_t new_argz_len = *argz_len + count * suffix_len; + char *new_argz = malloc (new_argz_len); + + if (new_argz) + { + char *p = new_argz, *entry; + + for (entry = *argz; + entry != NULL; + entry = argz_next (*argz, *argz_len, entry)) + { + p = stpcpy (p, entry); + p = stpcpy (p, suffix); + p++; + } + + free (*argz); + *argz = new_argz; + *argz_len = new_argz_len; + + return 0; + } + else + return ENOMEM; +} +weak_alias (__argz_suffix_entries, argz_suffix_entries) diff --git a/string/argz.h b/string/argz.h index cbc588a8e6..bc6e484c9d 100644 --- a/string/argz.h +++ b/string/argz.h @@ -108,6 +108,16 @@ extern error_t argz_replace (char **__restrict __argz, const char *__restrict __str, const char *__restrict __with, unsigned int *__restrict __replace_count); + +/* Suffix each entry of ARGZ & ARGZ_LEN with SUFFIX. Return 0 on success, + and ENOMEN if memory cannot be allocated. */ +extern error_t __argz_suffix_entries (char **__restrict __argz, + size_t *__restrict __argz_len, + const char *__restrict __suffix); +extern error_t argz_suffix_entries (char **__restrict __argz, + size_t *__restrict __argz_len, + const char *__restrict __suffix); + /* Returns the next entry in ARGZ & ARGZ_LEN after ENTRY, or NULL if there are no more. If entry is NULL, then the first entry is returned. This -- 2.40.1