From: Paul Eggert Date: Thu, 28 Dec 2023 19:15:56 +0000 (-0800) Subject: stat-time: fix macOS bug with negative file times X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Fstable-202301;p=gnulib.git stat-time: fix macOS bug with negative file times macOS has a bug similar (but not identical) to Solaris when file timestamps are negative: tv_nsec might go negative. Problem reported on Darwin 8.11.0 for GNU Tar by Gordon Steemson in: https://lists.gnu.org/r/bug-tar/2023-12/msg00001.html This was evidently Mac OS X 10.4.11; I reproduced it on Darwin 21.6.0 (macOS 12.5). * lib/stat-time.h (STAT_TIMESPEC_OFFSETOF): New macro. (stat_time_normalize): Also normalize timestamps on macOS. * m4/fstat.m4 (gl_FUNC_FSTAT): * m4/fstatat.m4 (gl_FUNC_FSTATAT): * m4/lstat.m4 (gl_FUNC_LSTAT): * m4/stat.m4 (gl_FUNC_STAT): Also replace on macOS. --- diff --git a/ChangeLog b/ChangeLog index 4c418233a0..c7c47be014 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2023-12-28 Paul Eggert + + stat-time: fix macOS bug with negative file times + macOS has a bug similar (but not identical) to Solaris when + file timestamps are negative: tv_nsec might go negative. + Problem reported on Darwin 8.11.0 for GNU Tar by Gordon Steemson in: + https://lists.gnu.org/r/bug-tar/2023-12/msg00001.html + This was evidently Mac OS X 10.4.11; I reproduced it on + Darwin 21.6.0 (macOS 12.5). + * lib/stat-time.h (STAT_TIMESPEC_OFFSETOF): New macro. + (stat_time_normalize): Also normalize timestamps on macOS. + * m4/fstat.m4 (gl_FUNC_FSTAT): + * m4/fstatat.m4 (gl_FUNC_FSTATAT): + * m4/lstat.m4 (gl_FUNC_LSTAT): + * m4/stat.m4 (gl_FUNC_STAT): + Also replace on macOS. + 2023-12-10 Pádraig Brady bootstrap: fix option propagation with --bootstrap-sync diff --git a/doc/posix-functions/fstatat.texi b/doc/posix-functions/fstatat.texi index a37ee428b6..664ffe7728 100644 --- a/doc/posix-functions/fstatat.texi +++ b/doc/posix-functions/fstatat.texi @@ -26,10 +26,11 @@ For symlinks, when the argument ends in a slash, some platforms don't dereference the argument: Solaris 9. @item -On Solaris 11.4, when this function yields a timestamp with a +On macOS 12.6, when this function yields a timestamp with a nonpositive @code{tv_sec} value, @code{tv_nsec} might be in the range -@minus{}1000000000..@minus{}1, representing a negative nanoseconds -offset from @code{tv_sec}. +@minus{}999999999..@minus{}1, representing a negative nanoseconds +offset from @code{tv_sec}. Solaris 11.4 is similar, except that +@code{tv_sec} might also be @minus{}1000000000. @end itemize Portability problems not fixed by Gnulib: diff --git a/doc/posix-functions/lstat.texi b/doc/posix-functions/lstat.texi index 31b7759d95..eb666f88ea 100644 --- a/doc/posix-functions/lstat.texi +++ b/doc/posix-functions/lstat.texi @@ -26,10 +26,11 @@ On some platforms, @code{lstat("file/",buf)} succeeds instead of failing with @code{ENOTDIR}. macOS 11.1, Solaris 9. @item -On Solaris 11.4, when this function yields a timestamp with a +On macOS 12.6, when this function yields a timestamp with a nonpositive @code{tv_sec} value, @code{tv_nsec} might be in the range -@minus{}1000000000..@minus{}1, representing a negative nanoseconds -offset from @code{tv_sec}. +@minus{}999999999..@minus{}1, representing a negative nanoseconds +offset from @code{tv_sec}. Solaris 11.4 is similar, except that +@code{tv_sec} might also be @minus{}1000000000. @item On Windows platforms (excluding Cygwin), symlinks are not supported, so @code{lstat} does not exist. diff --git a/doc/posix-functions/stat.texi b/doc/posix-functions/stat.texi index 0e3f56a96d..2f4d277843 100644 --- a/doc/posix-functions/stat.texi +++ b/doc/posix-functions/stat.texi @@ -35,10 +35,11 @@ On some platforms, @code{stat(".",buf)} and @code{stat("./",buf)} give different results: mingw, MSVC 14. @item -On Solaris 11.4, when this function yields a timestamp with a +On macOS 12.6, when this function yields a timestamp with a nonpositive @code{tv_sec} value, @code{tv_nsec} might be in the range -@minus{}1000000000..@minus{}1, representing a negative nanoseconds -offset from @code{tv_sec}. +@minus{}999999999..@minus{}1, representing a negative nanoseconds +offset from @code{tv_sec}. Solaris 11.4 is similar, except that +@code{tv_sec} might also be @minus{}1000000000. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/stat-time.h b/lib/stat-time.h index 92aa1e64e2..50cfa61eff 100644 --- a/lib/stat-time.h +++ b/lib/stat-time.h @@ -49,11 +49,13 @@ extern "C" { #if _GL_WINDOWS_STAT_TIMESPEC || defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC # if _GL_WINDOWS_STAT_TIMESPEC || defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim) +# define STAT_TIMESPEC_OFFSETOF(st_xtim) offsetof (struct stat, st_xtim) # else # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec) # endif #elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC # define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec) +# define STAT_TIMESPEC_OFFSETOF(st_xtim) offsetof (struct stat, st_xtim##espec) #elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC # define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec) #elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC @@ -202,20 +204,21 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) } /* If a stat-like function returned RESULT, normalize the timestamps - in *ST, in case this platform suffers from the Solaris 11 bug where + in *ST, if this platform suffers from a macOS and Solaris bug where tv_nsec might be negative. Return the adjusted RESULT, setting errno to EOVERFLOW if normalization overflowed. This function is intended to be private to this .h file. */ _GL_STAT_TIME_INLINE int stat_time_normalize (int result, _GL_UNUSED struct stat *st) { -#if defined __sun && defined STAT_TIMESPEC +#if (((defined __APPLE__ && defined __MACH__) || defined __sun) \ + && defined STAT_TIMESPEC_OFFSETOF) if (result == 0) { long int timespec_hz = 1000000000; - short int const ts_off[] = { offsetof (struct stat, st_atim), - offsetof (struct stat, st_mtim), - offsetof (struct stat, st_ctim) }; + short int const ts_off[] = { STAT_TIMESPEC_OFFSETOF (st_atim), + STAT_TIMESPEC_OFFSETOF (st_mtim), + STAT_TIMESPEC_OFFSETOF (st_ctim) }; int i; for (i = 0; i < sizeof ts_off / sizeof *ts_off; i++) { diff --git a/m4/fstat.m4 b/m4/fstat.m4 index 7cb2edb001..eb55bcd2a8 100644 --- a/m4/fstat.m4 +++ b/m4/fstat.m4 @@ -1,4 +1,4 @@ -# fstat.m4 serial 8 +# fstat.m4 serial 8.1 dnl Copyright (C) 2011-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,10 +10,10 @@ AC_DEFUN([gl_FUNC_FSTAT], AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) case "$host_os" in - mingw* | solaris*) + darwin* | mingw* | solaris*) + dnl macOS and Solaris stat can return a negative tv_nsec. dnl On MinGW, the original stat() returns st_atime, st_mtime, dnl st_ctime values that are affected by the time zone. - dnl Solaris stat can return a negative tv_nsec. REPLACE_FSTAT=1 ;; esac diff --git a/m4/fstatat.m4 b/m4/fstatat.m4 index 083076911f..84f82a2a69 100644 --- a/m4/fstatat.m4 +++ b/m4/fstatat.m4 @@ -1,4 +1,4 @@ -# fstatat.m4 serial 4 +# fstatat.m4 serial 5 dnl Copyright (C) 2004-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -50,7 +50,7 @@ AC_DEFUN([gl_FUNC_FSTATAT], esac case $host_os in - solaris*) + darwin* | solaris*) REPLACE_FSTATAT=1 ;; esac diff --git a/m4/lstat.m4 b/m4/lstat.m4 index 7e667fb187..125a73a16e 100644 --- a/m4/lstat.m4 +++ b/m4/lstat.m4 @@ -1,4 +1,4 @@ -# serial 33 +# serial 33.1 # Copyright (C) 1997-2001, 2003-2023 Free Software Foundation, Inc. # @@ -18,7 +18,7 @@ AC_DEFUN([gl_FUNC_LSTAT], if test $ac_cv_func_lstat = yes; then AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK]) case $host_os,$gl_cv_func_lstat_dereferences_slashed_symlink in - solaris* | *no) + darwin* | solaris* | *no) REPLACE_LSTAT=1 ;; esac diff --git a/m4/stat.m4 b/m4/stat.m4 index 4d241e27a1..65ba607355 100644 --- a/m4/stat.m4 +++ b/m4/stat.m4 @@ -1,4 +1,4 @@ -# serial 18 +# serial 18.1 # Copyright (C) 2009-2023 Free Software Foundation, Inc. # @@ -59,8 +59,8 @@ AC_DEFUN([gl_FUNC_STAT], help when passed a file name with a trailing slash]);; esac case $host_os in - dnl Solaris stat can return a negative tv_nsec. - solaris*) + dnl macOS and Solaris stat can return a negative tv_nsec. + darwin* | solaris*) REPLACE_FSTAT=1 ;; esac ;;