bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] year2038: support glibc 2.34 _TIME_BITS=64


From: Paul Eggert
Subject: [PATCH] year2038: support glibc 2.34 _TIME_BITS=64
Date: Thu, 1 Jul 2021 19:33:32 -0700

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 c325d80b2..b00dfd1fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 2021-07-01  Paul Eggert  <eggert@cs.ucla.edu>
 
+       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 def6cba3e..345afb189 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 6d04b45b8..13572b47e 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 f1bac719e..b9be347c7 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 cadb16dc9..172a4da96 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 2534622fc..635ef124f 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 <time.h>
+  /* 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 <https://sourceware.org/glibc/wiki/Y2038ProofnessDesign>.
+  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 <time.h>
-            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 fcae113db..8eb438a8e 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.30.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]