From dc09dc0888485698a8e74205b9df43159aef0f61 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 1 Jul 2021 19:29:57 -0700 Subject: [PATCH] year2038: support glibc 2.34 _TIME_BITS=64 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit In glibc 2.34 on Linux kernels where time_t is traditionally 32-bit, defining _FILE_OFFSET_BITS=64 and _TIME_BITS=64 makes time_t 64-bit. Apps must define both macros. Gnulib applications that use either the largefile or the year2038 modules will want this behavior; largefile because it deals with the off_t and ino_t components of struct stat already, and so should also deal with time_t. * NEWS, doc/largefile.texi, doc/posix-headers/time.texi: Mention this. * m4/largefile.m4: Override two macros even in Autoconf 2.70 and later. (_AC_SYS_LARGEFILE_MACRO_VALUE): #undef $1 before #defining it, in case some other Gnulib macro has #defined it. (AC_SYS_LARGEFILE): Use AS_IF and AS_CASE to propagate AC_REQUIREs. Invoke gl_YEAR2038_BODY if we need to set _FILE_OFFSET_BITS=64. * m4/year2038.m4 (gl_YEAR2038_TEST_INCLUDES): New macro. (gl_YEAR2038_BODY): New macro, with gl_YEAR2038’s old body; this macro is designed to be used directly instead of being AC_REQUIREd. It takes an argument specifying whether 64-bit is required. Set _TIME_BITS=64 if this makes a difference in time_t width when setting _FILE_OFFSET_BITS=64. Do not warn about 32-bit time_t more than once. * modules/largefile (Files): Add year2038.m4. (Depends-on): Require gl_YEAR2038_EARLY. --- ChangeLog | 24 ++++++++++++++ NEWS | 4 +++ doc/largefile.texi | 5 +-- doc/posix-headers/time.texi | 13 ++++++-- m4/largefile.m4 | 28 +++++++++-------- m4/year2038.m4 | 63 +++++++++++++++++++++++++++++-------- modules/largefile | 7 +++++ 7 files changed, 113 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index c325d80b20..b00dfd1fd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,29 @@ 2021-07-01 Paul Eggert + year2038: support glibc 2.34 _TIME_BITS=64 + In glibc 2.34 on Linux kernels where time_t is traditionally 32-bit, + defining _FILE_OFFSET_BITS=64 and _TIME_BITS=64 makes time_t 64-bit. + Apps must define both macros. Gnulib applications that use either + the largefile or the year2038 modules will want this behavior; + largefile because it deals with the off_t and ino_t components of + struct stat already, and so should also deal with time_t. + * NEWS, doc/largefile.texi, doc/posix-headers/time.texi: + Mention this. + * m4/largefile.m4: Override two macros even in Autoconf 2.70 and later. + (_AC_SYS_LARGEFILE_MACRO_VALUE): #undef $1 before #defining it, in + case some other Gnulib macro has #defined it. + (AC_SYS_LARGEFILE): Use AS_IF and AS_CASE to propagate AC_REQUIREs. + Invoke gl_YEAR2038_BODY if we need to set _FILE_OFFSET_BITS=64. + * m4/year2038.m4 (gl_YEAR2038_TEST_INCLUDES): New macro. + (gl_YEAR2038_BODY): New macro, with gl_YEAR2038’s old body; this + macro is designed to be used directly instead of being + AC_REQUIREd. It takes an argument specifying whether 64-bit is + required. Set _TIME_BITS=64 if this makes a difference in time_t + width when setting _FILE_OFFSET_BITS=64. Do not warn about + 32-bit time_t more than once. + * modules/largefile (Files): Add year2038.m4. + (Depends-on): Require gl_YEAR2038_EARLY. + relocatable-prog-wrapper: add m4 files Add .m4 files needed for standalone relocatable-prog-wrapper, so that ‘./gnulib-tool --test relocatable-prog-wrapper’ does not fail diff --git a/NEWS b/NEWS index def6cba3ef..345afb1891 100644 --- a/NEWS +++ b/NEWS @@ -66,6 +66,10 @@ User visible incompatible changes Date Modules Changes +2021-07-01 largefile AC_SYS_LARGEFILE now also arranges for time_t + to be 64-bit on 32-bit GNU/Linux platforms + that support it (glibc 2.34 or later). + 2021-03-21 fatal-signal The function at_fatal_signal now returns an error indicator. diff --git a/doc/largefile.texi b/doc/largefile.texi index 6d04b45b8a..13572b47e5 100644 --- a/doc/largefile.texi +++ b/doc/largefile.texi @@ -1,8 +1,9 @@ @node Large File Support @section Large File Support -The module provides support for files larger than 2 GB. -To this effect, it ensures that @code{off_t} is a 64-bit integer type +The module provides support for files larger than 2 GB, or with device +or inode numbers or timestamps exceeding 32 bits. To this effect, it +ensures that types like @code{off_t} and @code{time_t} are 64-bit when possible, at least on the following platforms: glibc, Mac OS X, FreeBSD, NetBSD, OpenBSD, AIX, HP-UX, IRIX, Solaris, Cygwin, mingw, MSVC. diff --git a/doc/posix-headers/time.texi b/doc/posix-headers/time.texi index f1bac719e3..b9be347c77 100644 --- a/doc/posix-headers/time.texi +++ b/doc/posix-headers/time.texi @@ -8,6 +8,12 @@ Gnulib module: time Portability problems fixed by Gnulib: @itemize @item +On some platforms where @code{time_t} defaults to 32-bit but can be +changed to 64-bit, functions like @code{stat} can fail with +@code{errno == EOVERFLOW} when a 32-bit timestamp is out of range, +such as with a file timestamp in the far future or past: +glibc 2.34. +@item @samp{struct timespec} is not defined on some platforms. @item The macro @code{TIME_UTC} is not defined on many platforms: @@ -21,9 +27,10 @@ NetBSD 5.0. Portability problems not fixed by Gnulib: @itemize @item -On platforms with 32-bit @code{time_t}, functions like @code{stat} can -fail with @code{errno == EOVERFLOW} when a timestamp is out of range, -such as with a file timestamp in the far future or past; on others, +On platforms where @code{time_t} is always 32-bit, functions like +@code{stat} can fail with @code{errno == EOVERFLOW} when a timestamp +is out of range, such as with a file timestamp in the far future or +past; on other such platforms, the functions silently return the low-order 32 bits of the correct timestamp. These platforms will be obsolete when 32-bit @code{time_t} rolls around, which will occur in 2038 for the typical case when diff --git a/m4/largefile.m4 b/m4/largefile.m4 index cadb16dc97..172a4da96a 100644 --- a/m4/largefile.m4 +++ b/m4/largefile.m4 @@ -22,7 +22,8 @@ AC_DEFUN([gl_SET_LARGEFILE_SOURCE], esac ]) -# The following implementation works around a problem in autoconf <= 2.69; +# Work around a problem in Autoconf through at least 2.71 on glibc 2.34+ +# with _TIME_BITS. Also, work around a problem in autoconf <= 2.69: # AC_SYS_LARGEFILE does not configure for large inodes on Mac OS X 10.5, # or configures them incorrectly in some cases. m4_version_prereq([2.70], [], [ @@ -40,6 +41,7 @@ m4_define([_AC_SYS_LARGEFILE_TEST_INCLUDES], && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]];[]dnl ]) +])# m4_version_prereq 2.70 # _AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, VALUE, @@ -54,7 +56,8 @@ m4_define([_AC_SYS_LARGEFILE_MACRO_VALUE], [AC_LANG_PROGRAM([$5], [$6])], [$3=no; break]) m4_ifval([$6], [AC_LINK_IFELSE], [AC_COMPILE_IFELSE])( - [AC_LANG_PROGRAM([#define $1 $2 + [AC_LANG_PROGRAM([#undef $1 +#define $1 $2 $5], [$6])], [$3=$2; break]) $3=unknown @@ -80,9 +83,8 @@ rm -rf conftest*[]dnl AC_DEFUN([AC_SYS_LARGEFILE], [AC_ARG_ENABLE(largefile, [ --disable-largefile omit support for large files]) -if test "$enable_largefile" != no; then - - AC_CACHE_CHECK([for special C compiler options needed for large files], +AS_IF([test "$enable_largefile" != no], + [AC_CACHE_CHECK([for special C compiler options needed for large files], ac_cv_sys_largefile_CC, [ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then @@ -107,15 +109,15 @@ if test "$enable_largefile" != no; then ac_cv_sys_file_offset_bits, [Number of bits in a file offset, on hosts where this is settable.], [_AC_SYS_LARGEFILE_TEST_INCLUDES]) - if test $ac_cv_sys_file_offset_bits = unknown; then - _AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1, - ac_cv_sys_large_files, - [Define for large files, on AIX-style hosts.], - [_AC_SYS_LARGEFILE_TEST_INCLUDES]) - fi -fi + AS_CASE([$ac_cv_sys_file_offset_bits], + [unknown], + [_AC_SYS_LARGEFILE_MACRO_VALUE([_LARGE_FILES], [1], + [ac_cv_sys_large_files], + [Define for large files, on AIX-style hosts.], + [_AC_SYS_LARGEFILE_TEST_INCLUDES])], + [64], + [gl_YEAR2038_BODY([false])])]) ])# AC_SYS_LARGEFILE -])# m4_version_prereq 2.70 # Enable large files on systems where this is implemented by Gnulib, not by the # system headers. diff --git a/m4/year2038.m4 b/m4/year2038.m4 index 2534622fc2..635ef124fc 100644 --- a/m4/year2038.m4 +++ b/m4/year2038.m4 @@ -1,4 +1,4 @@ -# year2038.m4 serial 3 +# year2038.m4 serial 4 dnl Copyright (C) 2017-2021 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,13 +18,29 @@ AC_DEFUN([gl_YEAR2038_EARLY], esac ]) -AC_DEFUN([gl_YEAR2038], +# gl_YEAR2038_TEST_INCLUDES +# ------------------------- +AC_DEFUN([gl_YEAR2038_TEST_INCLUDES], +[[ + #include + /* Check that time_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_TIME_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ + #define LARGE_TIME_T (((time_t) 1 << 31 << 31) - 1 + ((time_t) 1 << 31 << 31)) + int verify_time_t_range[(LARGE_TIME_T % 2147483629 == 721 + && LARGE_TIME_T % 2147483647 == 1) + ? 1 : -1]; +]]) + +# gl_YEAR2038_BODY(REQUIRE-64-BIT) +---------------------------------- +AC_DEFUN([gl_YEAR2038_BODY], [ dnl On many systems, time_t is already a 64-bit type. dnl On those systems where time_t is still 32-bit, it requires kernel - dnl and libc support to make it 64-bit. For glibc on Linux/x86, this - dnl is work in progress; see - dnl . + dnl and libc support to make it 64-bit. For glibc 2.34 and later on Linux, + dnl defining _TIME_BITS=64 and _FILE_OFFSET_BITS=64 is needed on x86 and ARM. dnl dnl On native Windows, the system include files define types __time32_t dnl and __time64_t. By default, time_t is an alias of @@ -36,13 +52,28 @@ AC_DEFUN([gl_YEAR2038], dnl __time32_t. AC_CACHE_CHECK([for 64-bit time_t], [gl_cv_type_time_t_64], [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include - int verify_time_t_size[sizeof (time_t) >= 8 ? 1 : -1]; - ]], - [[]])], + [AC_LANG_SOURCE([gl_YEAR2038_TEST_INCLUDES])], [gl_cv_type_time_t_64=yes], [gl_cv_type_time_t_64=no]) ]) + if test "$gl_cv_type_time_t_64" = no; then + AC_CACHE_CHECK([for 64-bit time_t with _TIME_BITS=64], + [gl_cv_type_time_t_bits_macro], + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[#define _TIME_BITS 64 + #define _FILE_OFFSET_BITS 64 + ]gl_YEAR2038_TEST_INCLUDES])], + [gl_cv_type_time_t_bits_macro=yes], + [gl_cv_type_time_t_bits_macro=no]) + ]) + if test "$gl_cv_type_time_t_bits_macro" = yes; then + AC_DEFINE([_TIME_BITS], [64], + [Number of bits in a timestamp, on hosts where this is settable.]) + dnl AC_SYS_LARGFILE also defines this; it's OK if we do too. + AC_DEFINE([_FILE_OFFSET_BITS], [64], + [Number of bits in a file offset, on hosts where this is settable.]) + gl_cv_type_time_t_64=yes + fi + fi if test $gl_cv_type_time_t_64 = no; then AC_COMPILE_IFELSE( [AC_LANG_SOURCE( @@ -53,18 +84,24 @@ AC_DEFUN([gl_YEAR2038], #endif ]])], [AC_MSG_FAILURE([This package requires a 64-bit 'time_t' type. Remove _USE_32BIT_TIME_T from the compiler flags.])], - [# If TIME_T_32_BIT_OK is "no" (the default) and not cross-compiling + [# If not cross-compiling and $1 says we should check, # and 'touch' works with a large timestamp, then evidently 64-bit time_t # is desired and supported, so fail and ask the builder to fix the # problem. Otherwise, just warn the builder. - if test "${TIME_T_32_BIT_OK-no}" = no \ + if $1 \ && test $cross_compiling = no \ && TZ=UTC0 touch -t 210602070628.16 conftest.time 2>/dev/null; then rm -f conftest.time AC_MSG_FAILURE([This package requires a 64-bit 'time_t' type, which your system appears to support. You might try configuring with 'CPPFLAGS="-m64" LDFLAGS="-m64"'. To build with a 32-bit time_t anyway (not recommended), configure with 'TIME_T_32_BIT_OK=yes'.]) - else + elif test "$gl_warned_about_64_bit_time_t" != yes; then AC_MSG_WARN([This package requires a 64-bit 'time_t' type if there is any way to access timestamps outside the year range 1901-2038 on your platform. Perhaps you should configure with 'CPPFLAGS="-m64" LDFLAGS="-m64"'?]) + gl_warned_about_64_bit_time_t=yes fi ]) fi ]) + +AC_DEFUN([gl_YEAR2038], +[ + gl_YEAR2038_BODY([test "${TIME_T_32_BIT_OK-no}" = no]) +]) diff --git a/modules/largefile b/modules/largefile index fcae113dbe..8eb438a8e9 100644 --- a/modules/largefile +++ b/modules/largefile @@ -1,13 +1,20 @@ Description: Support for files larger than 2 GB. +Comment: +This module should not be used as a dependency from a test module, +otherwise when this module occurs as a tests-related module, it will +have side effects on the compilation of the main modules in lib/. + Files: m4/largefile.m4 +m4/year2038.m4 Depends-on: configure.ac-early: AC_REQUIRE([AC_SYS_LARGEFILE]) +AC_REQUIRE([gl_YEAR2038_EARLY]) configure.ac: AC_REQUIRE([gl_LARGEFILE]) -- 2.39.5