summaryrefslogtreecommitdiff
path: root/src/gl/m4/year2038.m4
blob: 2e4427e6fac10550c99748abebf31b61e6afda2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# year2038.m4 serial 8
dnl Copyright (C) 2017-2022 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

dnl Attempt to ensure that 'time_t' can go past the year 2038 and that
dnl the functions 'time', 'stat', etc. work with post-2038 timestamps.

m4_ifdef([AC_SYS_YEAR2038], [
  AC_DEFUN([gl_YEAR2038_EARLY])
  AC_DEFUN([gl_YEAR2038], [AC_SYS_YEAR2038])
  AC_DEFUN([gl_YEAR2038_BODY], [_AC_SYS_YEAR2038])
], [

AC_DEFUN([gl_YEAR2038_EARLY],
[
  AC_REQUIRE([AC_CANONICAL_HOST])
  case "$host_os" in
    mingw*)
      AC_DEFINE([__MINGW_USE_VC2005_COMPAT], [1],
        [For 64-bit time_t on 32-bit mingw.])
      ;;
  esac
])

# gl_YEAR2038_TEST_INCLUDES
# -------------------------
AC_DEFUN([gl_YEAR2038_TEST_INCLUDES],
[[
  #include <time.h>
  /* Check that time_t can represent 2**32 - 1 correctly.  */
  #define LARGE_TIME_T \\
    ((time_t) (((time_t) 1 << 30) - 1 + 3 * ((time_t) 1 << 30)))
  int verify_time_t_range[(LARGE_TIME_T / 65537 == 65535
                           && LARGE_TIME_T % 65537 == 0)
                          ? 1 : -1];
]])

# gl_YEAR2038_BODY(REQUIRE-YEAR2038-SAFE)
-----------------------------------------
AC_DEFUN([gl_YEAR2038_BODY],
[
 AC_ARG_ENABLE([year2038],
   [  --disable-year2038      omit support for timestamps past the year 2038])
 AS_IF([test "$enable_year2038" != no],
 [
  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 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
  dnl   - __time32_t on 32-bit mingw,
  dnl   - __time64_t on 64-bit mingw and on MSVC (since MSVC 8).
  dnl But when compiling with -D__MINGW_USE_VC2005_COMPAT, time_t is an
  dnl alias of __time64_t.
  dnl And when compiling with -D_USE_32BIT_TIME_T, time_t is an alias of
  dnl __time32_t.
  AC_CACHE_CHECK([for time_t past the year 2038], [gl_cv_type_time_t_y2038],
    [AC_COMPILE_IFELSE(
       [AC_LANG_SOURCE([gl_YEAR2038_TEST_INCLUDES])],
       [gl_cv_type_time_t_y2038=yes], [gl_cv_type_time_t_y2038=no])
    ])
  if test "$gl_cv_type_time_t_y2038" = 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_y2038=yes
    fi
  fi
  if test $gl_cv_type_time_t_y2038 = no; then
    AC_COMPILE_IFELSE(
      [AC_LANG_SOURCE(
         [[#ifdef _USE_32BIT_TIME_T
             int ok;
           #else
             error fail
           #endif
         ]])],
      [AC_MSG_FAILURE(
         [The 'time_t' type stops working after January 2038.
          Remove _USE_32BIT_TIME_T from the compiler flags.])],
      [# If not cross-compiling and $1 says we should check,
       # and 'touch' works with a large timestamp, then evidently wider time_t
       # is desired and supported, so fail and ask the builder to fix the
       # problem.  Otherwise, just warn the builder.
       m4_ifval([$1],
         [if test $cross_compiling = no \
             && TZ=UTC0 touch -t 210602070628.15 conftest.time 2>/dev/null; then
            case `TZ=UTC0 LC_ALL=C ls -l conftest.time 2>/dev/null` in
              *'Feb  7  2106'* | *'Feb  7 17:10'*)
                AC_MSG_FAILURE(
                  [The 'time_t' type stops working after January 2038,
                   and your system appears to support a wider 'time_t'.
                   Try configuring with 'CC="${CC} -m64"'.
                   To build with a 32-bit time_t anyway (not recommended),
                   configure with '--disable-year2038'.]);;
            esac
            rm -f conftest.time
          fi])
       if test "$gl_warned_about_y2038" != yes; then
         AC_MSG_WARN(
           [The 'time_t' type stops working after January 2038,
            and this package needs a wider 'time_t' type
            if there is any way to access timestamps after that.
            Configure with 'CC="${CC} -m64"' perhaps?])
         gl_warned_about_y2038=yes
       fi
      ])
  fi])
])

AC_DEFUN([gl_YEAR2038],
[
  gl_YEAR2038_BODY([require-year2038-safe])
])

]) # m4_ifndef AC_SYS_YEAR2038