diff --git a/gnu-system.am b/gnu-system.am index aba8f8d..3aa9144 100644 --- a/gnu-system.am +++ b/gnu-system.am @@ -473,6 +473,7 @@ dist_patch_DATA = \ gnu/packages/patches/glibc-ldd-x86_64.patch \ gnu/packages/patches/glibc-locales.patch \ gnu/packages/patches/glibc-o-largefile.patch \ + gnu/packages/patches/glibc-versioned-locpath.patch \ gnu/packages/patches/gmp-arm-asm-nothumb.patch \ gnu/packages/patches/gnucash-price-quotes-perl.patch \ gnu/packages/patches/gnutls-doc-fix.patch \ diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm index 337fdae..443c54e 100644 --- a/gnu/packages/base.scm +++ b/gnu/packages/base.scm @@ -477,6 +477,7 @@ store.") (patches (map search-patch '("glibc-ldd-x86_64.patch" "glibc-guix-locpath.patch" + "glibc-versioned-locpath.patch" "glibc-o-largefile.patch"))))) (build-system gnu-build-system) @@ -510,16 +511,12 @@ store.") ;; Set the default locale path. In practice, $LOCPATH may be ;; defined to point whatever locales users want. However, setuid ;; binaries don't honor $LOCPATH, so they'll instead look into - ;; $libc_cv_localedir; we choose /run/current-system/locale/X.Y, + ;; $libc_cv_localedir; we choose /run/current-system/locale ;; with the idea that it is going to be populated by the sysadmin. - ;; The "X.Y" sub-directory is because locale data formats are - ;; incompatible across libc versions; see - ;; . ;; ;; `--localedir' is not honored, so work around it. ;; See . - (string-append "libc_cv_localedir=/run/current-system/locale/" - ,version) + "libc_cv_localedir=/run/current-system/locale" (string-append "--with-headers=" (assoc-ref %build-inputs "linux-headers") @@ -655,7 +652,8 @@ the 'share/locale' sub-directory of this package.") ;; Use $(libdir)/locale as is the case by default. (list (string-append "libc_cv_localedir=" (assoc-ref %outputs "out") - "/lib/locale"))))))))) + "/lib/locale/" + ,(package-version glibc)))))))))) (define-public glibc-utf8-locales (package @@ -664,7 +662,7 @@ the 'share/locale' sub-directory of this package.") (source #f) (build-system trivial-build-system) (arguments - '(#:modules ((guix build utils)) + `(#:modules ((guix build utils)) #:builder (begin (use-modules (srfi srfi-1) (guix build utils)) @@ -672,7 +670,8 @@ the 'share/locale' sub-directory of this package.") (let* ((libc (assoc-ref %build-inputs "glibc")) (gzip (assoc-ref %build-inputs "gzip")) (out (assoc-ref %outputs "out")) - (localedir (string-append out "/lib/locale"))) + (localedir (string-append out "/lib/locale/" + ,version))) ;; 'localedef' needs 'gzip'. (setenv "PATH" (string-append libc "/bin:" gzip "/bin")) diff --git a/gnu/packages/patches/glibc-versioned-locpath.patch b/gnu/packages/patches/glibc-versioned-locpath.patch new file mode 100644 index 0000000..b643399 --- /dev/null +++ b/gnu/packages/patches/glibc-versioned-locpath.patch @@ -0,0 +1,47 @@ +The format of locale data can be incompatible between libc versions, and +loading incompatible data can lead to 'setlocale' returning EINVAL at best +or triggering an assertion failure at worst. See +https://lists.gnu.org/archive/html/guix-devel/2015-09/msg00717.html +for background information. + +To address that, this patch changes libc to look for locale data in +version-specific sub-directories. So, if LOCPATH=/foo:/bar, locale data +is searched for in /foo/X.Y and /bar/X.Y, where X.Y is the libc version +number. + +That way, a single 'LOCPATH' setting can work even if different libc versions +coexist on the system. + +--- a/intl/l10nflist.c ++++ b/intl/l10nflist.c +@@ -25,6 +25,10 @@ + # include + #endif + ++#ifdef _LIBC ++# include ++#endif ++ + #include + + #if defined _LIBC || defined HAVE_ARGZ_H +@@ -164,6 +168,9 @@ _nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list, + + /* Allocate room for the full file name. */ + abs_filename = (char *) malloc (dirlist_len ++#ifdef _LIBC ++ + strlen (VERSION) + 1 ++#endif + + strlen (language) + + ((mask & XPG_TERRITORY) != 0 + ? strlen (territory) + 1 : 0) +@@ -185,6 +192,10 @@ _nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list, + memcpy (abs_filename, dirlist, dirlist_len); + __argz_stringify (abs_filename, dirlist_len, ':'); + cp = abs_filename + (dirlist_len - 1); ++#ifdef _LIBC ++ *cp++ = '/'; ++ cp = stpcpy (cp, VERSION); ++#endif + *cp++ = '/'; + cp = stpcpy (cp, language);