mirror of
https://git.savannah.gnu.org/git/guix.git
synced 2025-02-12 06:41:27 +01:00
gnu: glibc: Catch all cases of a glibc user not requesting 64-bit offsets and
then using readdir regardless. * gnu/packages/base.scm (glibc)[arguments]#<:phases>[patch-dirent]: Catch all cases of a glibc user not requesting 64-bit offsets and then using readdir regardless.
This commit is contained in:
parent
0585a0d0d1
commit
6d513b776a
1 changed files with 64 additions and 0 deletions
|
@ -782,6 +782,70 @@ the store.")
|
|||
|
||||
#:tests? #f ; XXX
|
||||
#:phases (modify-phases %standard-phases
|
||||
(add-after 'unpack 'patch-dirent
|
||||
(lambda* (#:key outputs #:allow-other-keys)
|
||||
;; Linux kernel file offsets are always 64 bits.
|
||||
;; But userspace can be built to use 32 bit offsets.
|
||||
;;
|
||||
;; "struct dirent", returned by readdir, uses d_off to store
|
||||
;; such an "offset" that it got from the Linux kernel.
|
||||
;; In the case of ext4 that "offset" is actually a 64 bit
|
||||
;; hash value.
|
||||
;;
|
||||
;; Therefore, there are cases where such an offset that it got
|
||||
;; from the Linux kernel does not fit in the "struct dirent"
|
||||
;; field "d_off".
|
||||
;;
|
||||
;; If the guest system's glibc is 32 bit AND uses 32 bit
|
||||
;; file offsets it is going to be very confused.
|
||||
;; It does check whether d_off fits into the structure
|
||||
;; it gives back to the user--and it doesn't fit. Hence readdir
|
||||
;; fails, with errno == EOVERFLOW (which is undocumented and thus
|
||||
;; an API error).
|
||||
;; This manifests itself in simple directory reads not working
|
||||
;; anymore in parts of cmake, for example.
|
||||
;;
|
||||
;; This manifested in Guix when building stuff for
|
||||
;; ARMHF on a x86_64 build host using QEMU transparent emulation.
|
||||
;;
|
||||
;; There is a very simple and complete way to avoid this problem:
|
||||
;; Just always use 64 bit offsets in user space programs (also
|
||||
;; on 32 bit machines). The Linux kernel does that already
|
||||
;; anyway.
|
||||
;;
|
||||
;; Note: We might want to avoid using 64 bit when bootstrapping
|
||||
;; using mescc (since mescc doesn't directly support 64 bit
|
||||
;; values)--but then bootstrapping has to be done on a
|
||||
;; file system other than ext4, or on ext4 with the feature
|
||||
;; "dir_index" disabled.
|
||||
;;
|
||||
;; The change below does not affect 64 bit users.
|
||||
;;
|
||||
;; See <https://issues.guix.gnu.org/43513>.
|
||||
(let ((port (open-file "dirent/dirent.h" "a")))
|
||||
(display "
|
||||
#ifndef _LIBC
|
||||
#if __SIZEOF_LONG__ < 8
|
||||
#ifndef __USE_FILE_OFFSET64
|
||||
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 32
|
||||
#warning \"Using -D_FILE_OFFSET_BITS=32 and using readdir is a bad idea, see <https://bugzilla.kernel.org/show_bug.cgi?id=205957>\"
|
||||
#else
|
||||
#undef readdir
|
||||
#define readdir @READDIR_WITHOUT_FILE_OFFSET64_IS_A_REALLY_BAD_IDEA@
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
" port)
|
||||
(close-port port))
|
||||
;; This file includes <dirent.h> and thus checks sanity already.
|
||||
;; TODO: Check dirent/scandir-tail.c, dirent/scandir64-tail.c.
|
||||
(substitute* "posix/glob.c"
|
||||
(("(#[ ]*define[ ][ ]*readdir)") "
|
||||
#undef readdir
|
||||
#define readdir"))
|
||||
#t))
|
||||
|
||||
(add-before
|
||||
'configure 'pre-configure
|
||||
(lambda* (#:key inputs native-inputs outputs
|
||||
|
|
Loading…
Add table
Reference in a new issue