diff --git a/lib/euidaccess.c b/lib/euidaccess.c index aee693571c9..4f512f5af54 100644 --- a/lib/euidaccess.c +++ b/lib/euidaccess.c @@ -29,8 +29,11 @@ #include #include #include - -#include "root-uid.h" +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# include +#else +# include "root-uid.h" +#endif #if HAVE_LIBGEN_H # include @@ -84,7 +87,9 @@ euidaccess (const char *file, int mode) return accessx (file, mode, ACC_SELF); #elif HAVE_EACCESS /* FreeBSD */ return eaccess (file, mode); -#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */ +#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ /* mingw */ + return _access (file, mode); +#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, BeOS */ uid_t uid = getuid (); gid_t gid = getgid (); diff --git a/lib/time_rz.c b/lib/time_rz.c index c1eca888f2c..5293c7cf8dc 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -286,6 +286,21 @@ revert_tz (timezone_t tz) struct tm * localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) { +#ifdef HAVE_LOCALTIME_INFLOOP_BUG + /* The -67768038400665599 comes from: + https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html + On affected platforms the greatest POSIX-compatible time_t value + that could return nonnull is 67768036191766798 (when + TZ="XXX24:59:59" it resolves to the year 2**31 - 1 + 1900, on + 12-31 at 23:59:59), so test for that too while we're in the + neighborhood. */ + if (! (-67768038400665599 <= *t && *t <= 67768036191766798)) + { + errno = EOVERFLOW; + return NULL; + } +#endif + if (!tz) return gmtime_r (t, tm); else diff --git a/m4/time_rz.m4 b/m4/time_rz.m4 index 43781489786..af9fa02b57d 100644 --- a/m4/time_rz.m4 +++ b/m4/time_rz.m4 @@ -13,6 +13,38 @@ AC_DEFUN([gl_TIME_RZ], AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS]) AC_REQUIRE([AC_STRUCT_TIMEZONE]) + # Mac OS X 10.6 loops forever with some time_t values less + # than -67768038400665599. See Bug#27706, Bug#27736, and + # https://lists.gnu.org/r/bug-gnulib/2017-07/msg00142.html + AC_CACHE_CHECK([whether localtime loops forever near extrema], + [gl_cv_func_localtime_infloop_bug], + [gl_cv_func_localtime_infloop_bug=no + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + ]], [[ + time_t t = -67768038400665600; + struct tm *tm; + char *tz = getenv ("TZ"); + if (! (tz && strcmp (tz, "QQQ0") == 0)) + return 0; + alarm (2); + tm = localtime (&t); + /* Use TM and *TM to suppress over-optimization. */ + return tm && tm->tm_isdst; + ]])], + [TZ=QQQ0 ./conftest$EXEEXT || gl_cv_func_localtime_infloop_bug=yes], + [], + [gl_cv_func_localtime_infloop_bug="guessing no"])]) + if test "$gl_cv_func_localtime_infloop_bug" = yes; then + AC_DEFINE([HAVE_LOCALTIME_INFLOOP_BUG], 1, + [Define if localtime-like functions can loop forever on + extreme arguments.]) + fi + AC_CHECK_TYPES([timezone_t], [], [], [[#include ]]) if test "$ac_cv_type_timezone_t" = yes; then HAVE_TIMEZONE_T=1