diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -617,6 +617,16 @@ dnl Check for pthread compile/link requirements AX_PTHREAD +# Check for off_t vs off64_t before AC_SYS_LARGEFILE gets called as it will +# change the output +AC_MSG_CHECKING(for if type off_t equals off64_t) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], + [[ static_assert(std::is_same::value, ""); ]])], + [ AC_MSG_RESULT(yes); need_wrap_fcntl=no; AC_DEFINE(OFF_T_EQUALS_OFF64_T, 1,[Define this symbol if type off_t equals off64_t]) ], + [ AC_MSG_RESULT(no); need_wrap_fcntl=yes] +) + # The following macro will add the necessary defines to bitcoin-config.h, but # they also need to be passed down to any subprojects. Pull the results out of # the cache and add them to CPPFLAGS. @@ -663,6 +673,10 @@ AC_DEFINE_UNQUOTED(FDELT_TYPE, $fdelt_type,[parameter and return value type for __fdelt_chk]) AX_CHECK_LINK_FLAG([[-Wl,--wrap=__divmoddi4]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=__divmoddi4"]) AX_CHECK_LINK_FLAG([[-Wl,--wrap=log2f]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=log2f"]) + if test x$need_wrap_fcntl = xyes; then + AX_CHECK_LINK_FLAG([[-Wl,--wrap=fcntl]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=fcntl"]) + AX_CHECK_LINK_FLAG([[-Wl,--wrap=fcntl64]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=fcntl64"]) + fi else AC_SEARCH_LIBS([clock_gettime],[rt]) fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -298,6 +298,10 @@ add_linker_flags(-Wl,--wrap=__divmoddi4) add_linker_flags(-Wl,--wrap=log2f) + if(NOT OFF_T_EQUALS_OFF64_T) + add_linker_flags(-Wl,--wrap=fcntl -Wl,--wrap=fcntl64) + endif() + target_sources(util PRIVATE compat/glibc_compat.cpp) endif() diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp --- a/src/compat/glibc_compat.cpp +++ b/src/compat/glibc_compat.cpp @@ -6,6 +6,7 @@ #include #endif +#include #include #include @@ -66,3 +67,48 @@ extern "C" float __wrap_log2f(float x) { return log2f_old(x); } + +/* + * Starting with GLIBC_2.28, the `fcntl()` function has a new variant + * `fcntl64()`: + * https://gitlab.com/freedesktop-sdk/mirrors/glibc/commit/06ab719d30b01da401150068054d3b8ea93dd12f + * (link to a mirror, glibc has no online source browser). + * + * See also the release notes for the 2.28 version: + * https://www.sourceware.org/ml/libc-alpha/2018-08/msg00003.html + * + * This is intended to fix a bug related to large file support on architectures + * where off_t and off64_t are not the same underlying type. + * To remain compatible with the previous versions, the GLIBC offers a + * compatibility symbol for these architectures. We can link the new `fcntl()` + * and `fcntl64()` against this symbol with the help of a wrapper. + */ +#if defined(HAVE_CONFIG_H) && !defined(OFF_T_EQUALS_OFF64_T) +extern "C" int fcntl_old(int fd, int cmd, ...); +#ifdef __i386__ +__asm(".symver fcntl_old,fcntl@GLIBC_2.0"); +#elif defined(__amd64__) +__asm(".symver fcntl_old,fcntl@GLIBC_2.2.5"); +#elif defined(__arm__) +__asm(".symver fcntl_old,fcntl@GLIBC_2.4"); +#elif defined(__aarch64__) +__asm(".symver fcntl_old,fcntl@GLIBC_2.17"); +#endif + +extern "C" int __wrap_fcntl(int fd, int cmd, ...) { + int ret; + va_list vargs; + va_start(vargs, cmd); + ret = fcntl_old(fd, cmd, va_arg(vargs, void *)); + va_end(vargs); + return ret; +} +extern "C" int __wrap_fcntl64(int fd, int cmd, ...) { + int ret; + va_list vargs; + va_start(vargs, cmd); + ret = fcntl_old(fd, cmd, va_arg(vargs, void *)); + va_end(vargs); + return ret; +} +#endif diff --git a/src/config/CMakeLists.txt b/src/config/CMakeLists.txt --- a/src/config/CMakeLists.txt +++ b/src/config/CMakeLists.txt @@ -158,6 +158,15 @@ } " CHAR_EQUALS_INT8) +check_cxx_source_compiles(" + #include + #include + int main() { + static_assert(std::is_same::value, \"\"); + return 0; + } +" OFF_T_EQUALS_OFF64_T) + check_cxx_source_compiles(" __attribute__((visibility(\"default\"))) int main() { return 0; diff --git a/src/config/bitcoin-config.h.cmake.in b/src/config/bitcoin-config.h.cmake.in --- a/src/config/bitcoin-config.h.cmake.in +++ b/src/config/bitcoin-config.h.cmake.in @@ -53,6 +53,7 @@ #cmakedefine HAVE_SYSCTL_ARND 1 #cmakedefine CHAR_EQUALS_INT8 0 +#cmakedefine OFF_T_EQUALS_OFF64_T 1 #cmakedefine HAVE_FUNC_ATTRIBUTE_VISIBILITY 1 #cmakedefine HAVE_FUNC_ATTRIBUTE_DLLEXPORT 1