bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH] stat-time: fix macOS bug with negative file times


From: Paul Eggert
Subject: [PATCH] stat-time: fix macOS bug with negative file times
Date: Thu, 28 Dec 2023 11:18:50 -0800

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.
---
 ChangeLog                        | 17 +++++++++++++++++
 doc/posix-functions/fstat.texi   |  7 ++++---
 doc/posix-functions/fstatat.texi |  7 ++++---
 doc/posix-functions/lstat.texi   |  7 ++++---
 doc/posix-functions/stat.texi    |  7 ++++---
 lib/stat-time.h                  | 13 ++++++++-----
 m4/fstat.m4                      |  6 +++---
 m4/fstatat.m4                    |  4 ++--
 m4/lstat.m4                      |  4 ++--
 m4/stat.m4                       |  6 +++---
 10 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 46c2f77242..746a1ea70f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2023-12-28  Paul Eggert  <eggert@cs.ucla.edu>
+
+       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-19  Bruno Haible  <bruno@clisp.org>
 
        jit/cache: Fix compilation error on m68k, sparc, etc.
diff --git a/doc/posix-functions/fstat.texi b/doc/posix-functions/fstat.texi
index b4c2431ff4..e8ef324553 100644
--- a/doc/posix-functions/fstat.texi
+++ b/doc/posix-functions/fstat.texi
@@ -21,10 +21,11 @@ access files that happen to have a 64-bit inode number.  
This can occur with
 file systems such as XFS (typically on large disks) and NFS.
 @xref{Large File Support}.
 @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
 The @code{st_atime}, @code{st_ctime}, @code{st_mtime} fields are affected by
 the current time zone and by the DST flag of the current time zone on some
diff --git a/doc/posix-functions/fstatat.texi b/doc/posix-functions/fstatat.texi
index 49d394addf..e959a5cc73 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 f0a6ffb572..95f740ce09 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 b64bdd3a01..f655451392 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 75eb27e549..1488182163 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -52,11 +52,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
@@ -194,20 +196,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 382741f412..769e7d6e58 100644
--- a/m4/fstat.m4
+++ b/m4/fstat.m4
@@ -1,4 +1,4 @@
-# fstat.m4 serial 9
+# fstat.m4 serial 10
 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* | windows* | solaris*)
+    darwin* | mingw* | windows* | 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 977386348a..76932d55a8 100644
--- a/m4/lstat.m4
+++ b/m4/lstat.m4
@@ -1,4 +1,4 @@
-# serial 35
+# serial 36
 
 # 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 81bd16a8f4..6e7be3d1c5 100644
--- a/m4/stat.m4
+++ b/m4/stat.m4
@@ -1,4 +1,4 @@
-# serial 20
+# serial 21
 
 # Copyright (C) 2009-2023 Free Software Foundation, Inc.
 #
@@ -61,8 +61,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
       ;;
-- 
2.40.1




reply via email to

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