
There is a nixpkgs' glibc patch that makes it look at environment variables to locate the locale-archive. It has a fallback to /usr/lib/locale/locale-archive, which is a pretty good one since nearly all non-nixos systems use that exact path since glibc hard codes it looking at PREFIX/lib/locale/locale-archive. IE debian/EL/Arch/Gentoo and others all use the same path for locale-archive. That hard coding in glibc is why nixpkgs even has this patch in the first place. Other wise you would need to rebuild every single package whenever you wanted to change the locale-archive at runtime. The problem with that final fallback is that glibc in nixpkgs includes a minimal locale-archive with just C.UTF-8. It does this so tests that require UTF-8 support can work in nixpkgs. The current patch will _always_ find the minimal locale-archive and never actually fall back to the system one. This can be very confusing, especially when looking at the patch and wondering why your CI system is throwing locale errors. Eventually you realize that some test sanitizes the environment, but still confused since it should fall back to the system's locale-archive. On systems that do not set LOCALE_ARCHIVE and do not have /usr/lib/locale/locale-archive then we fall back to that super minimal locale-archive included with the default nixpkgs' glibc. Testing: == Before == % env -u LOCALE_ARCHIVE_2_27 -u LOCALE_ARCHIVE LANG=en_US.UTF-8 /nix/store/gdq185xa4cmka46nv67vkmjlmkd9yr1k-cowsay-3.8.3/bin/cowsay hello perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = "", LC_ALL = (unset), LANG = "en_US.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). _______ < hello > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || == After == % env -u LOCALE_ARCHIVE_2_27 -u LOCALE_ARCHIVE LANG=en_US.UTF-8 /nix/store/hhc2gzs6gax4frk8985w2ada2ra35zyw-cowsay-3.8.3/bin/cowsay hello _______ < hello > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || === On NixOS === % env -u LOCALE_ARCHIVE_2_27 -u LOCALE_ARCHIVE LANG=en_US.UTF-8 /nix/store/hhc2gzs6gax4frk8985w2ada2ra35zyw-cowsay-3.8.3/bin/cowsay hello perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LC_CTYPE = (unset), LC_NUMERIC = (unset), LC_COLLATE = (unset), LC_TIME = (unset), LC_MESSAGES = (unset), LC_MONETARY = (unset), LC_ADDRESS = (unset), LC_IDENTIFICATION = (unset), LC_MEASUREMENT = (unset), LC_PAPER = (unset), LC_TELEPHONE = (unset), LC_NAME = (unset), LANG = "en_US.UTF-8" are supported and installed on your system. perl: warning: Falling back to the standard locale ("C"). _______ < hello > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || === Still can get the minimal locale-archive included with glibc === % env -u LOCALE_ARCHIVE_2_27 -u LOCALE_ARCHIVE LANG=C.UTF-8 /nix/store/hhc2gzs6gax4frk8985w2ada2ra35zyw-cowsay-3.8.3/bin/cowsay hello _______ < hello > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
122 lines
3.7 KiB
Diff
122 lines
3.7 KiB
Diff
diff --git a/locale/loadarchive.c b/locale/loadarchive.c
|
|
index 512769eaec..171dbb4ad9 100644
|
|
--- a/locale/loadarchive.c
|
|
+++ b/locale/loadarchive.c
|
|
@@ -123,6 +123,23 @@ calculate_head_size (const struct locarhead *h)
|
|
return MAX (namehash_end, MAX (string_end, locrectab_end));
|
|
}
|
|
|
|
+static int
|
|
+open_locale_archive (void)
|
|
+{
|
|
+ int fd = -1;
|
|
+ char *versioned_path = getenv ("LOCALE_ARCHIVE_2_27");
|
|
+ char *path = getenv ("LOCALE_ARCHIVE");
|
|
+ if (versioned_path)
|
|
+ fd = __open_nocancel (versioned_path, O_RDONLY|O_LARGEFILE|O_CLOEXEC);
|
|
+ if (path && fd < 0)
|
|
+ fd = __open_nocancel (path, O_RDONLY|O_LARGEFILE|O_CLOEXEC);
|
|
+ if (fd < 0)
|
|
+ fd = __open_nocancel ("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE|O_CLOEXEC);
|
|
+ if (fd < 0)
|
|
+ fd = __open_nocancel (archfname, O_RDONLY|O_LARGEFILE|O_CLOEXEC);
|
|
+ return fd;
|
|
+}
|
|
+
|
|
|
|
/* Find the locale *NAMEP in the locale archive, and return the
|
|
internalized data structure for its CATEGORY data. If this locale has
|
|
@@ -202,7 +219,7 @@ _nl_load_locale_from_archive (int category, const char **namep)
|
|
archmapped = &headmap;
|
|
|
|
/* The archive has never been opened. */
|
|
- fd = __open_nocancel (archfname, O_RDONLY|O_LARGEFILE|O_CLOEXEC);
|
|
+ fd = open_locale_archive ();
|
|
if (fd < 0)
|
|
/* Cannot open the archive, for whatever reason. */
|
|
return NULL;
|
|
@@ -397,8 +414,7 @@ _nl_load_locale_from_archive (int category, const char **namep)
|
|
if (fd == -1)
|
|
{
|
|
struct __stat64_t64 st;
|
|
- fd = __open_nocancel (archfname,
|
|
- O_RDONLY|O_LARGEFILE|O_CLOEXEC);
|
|
+ fd = open_locale_archive();
|
|
if (fd == -1)
|
|
/* Cannot open the archive, for whatever reason. */
|
|
return NULL;
|
|
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
|
|
index ca0a95be99..e484783402 100644
|
|
--- a/locale/programs/locale.c
|
|
+++ b/locale/programs/locale.c
|
|
@@ -633,6 +633,24 @@ nameentcmp (const void *a, const void *b)
|
|
}
|
|
|
|
|
|
+static int
|
|
+open_locale_archive (void)
|
|
+{
|
|
+ int fd = -1;
|
|
+ char *versioned_path = getenv ("LOCALE_ARCHIVE_2_27");
|
|
+ char *path = getenv ("LOCALE_ARCHIVE");
|
|
+ if (versioned_path)
|
|
+ fd = open64 (versioned_path, O_RDONLY);
|
|
+ if (path && fd < 0)
|
|
+ fd = open64 (path, O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ fd = open64 ("/usr/lib/locale/locale-archive", O_RDONLY);
|
|
+ if (fd < 0)
|
|
+ fd = open64 (ARCHIVE_NAME, O_RDONLY);
|
|
+ return fd;
|
|
+}
|
|
+
|
|
+
|
|
static int
|
|
write_archive_locales (void **all_datap, char *linebuf)
|
|
{
|
|
@@ -645,7 +663,7 @@ write_archive_locales (void **all_datap, char *linebuf)
|
|
int fd, ret = 0;
|
|
uint32_t cnt;
|
|
|
|
- fd = open64 (ARCHIVE_NAME, O_RDONLY);
|
|
+ fd = open_locale_archive ();
|
|
if (fd < 0)
|
|
return 0;
|
|
|
|
diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
|
|
index f38e835c52..779a3199fc 100644
|
|
--- a/locale/programs/locarchive.c
|
|
+++ b/locale/programs/locarchive.c
|
|
@@ -117,6 +117,22 @@ prepare_address_space (int fd, size_t total, size_t *reserved, int *xflags,
|
|
}
|
|
|
|
|
|
+static int
|
|
+open_locale_archive (const char * archivefname, int flags)
|
|
+{
|
|
+ int fd = -1;
|
|
+ char *versioned_path = getenv ("LOCALE_ARCHIVE_2_27");
|
|
+ char *path = getenv ("LOCALE_ARCHIVE");
|
|
+ if (versioned_path)
|
|
+ fd = open64 (versioned_path, flags);
|
|
+ if (path && fd < 0)
|
|
+ fd = open64 (path, flags);
|
|
+ if (fd < 0)
|
|
+ fd = open64 (archivefname, flags);
|
|
+ return fd;
|
|
+}
|
|
+
|
|
+
|
|
static void
|
|
create_archive (const char *archivefname, struct locarhandle *ah)
|
|
{
|
|
@@ -578,7 +594,7 @@ open_archive (struct locarhandle *ah, bool readonly)
|
|
while (1)
|
|
{
|
|
/* Open the archive. We must have exclusive write access. */
|
|
- fd = open64 (archivefname, readonly ? O_RDONLY : O_RDWR);
|
|
+ fd = open_locale_archive (archivefname, readonly ? O_RDONLY : O_RDWR);
|
|
if (fd == -1)
|
|
{
|
|
/* Maybe the file does not yet exist? If we are opening
|