bug-gnulib
[Top][All Lists]
Advanced

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

Re: NFS timestamps


From: Paul Eggert
Subject: Re: NFS timestamps
Date: Mon, 27 Dec 2010 00:28:30 -0800
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101208 Thunderbird/3.1.7

On 12/26/2010 02:46 AM, Bruno Haible wrote:
>>>     <http://lists.gnu.org/archive/html/bug-gnulib/2010-11/msg00113.html>.
>>
> With your patch, I still get "checking whether the utimes function works... 
> yes"
> and the same failures:
> test-futimens.h:108: assertion failed
> FAIL: test-futimens

Ah, sorry, I see now that I was trying to fix just the first problem
noted in the November email (called a "side note" there), and
completely missed the second, more important problem.  I just now
pushed the following to try to fix the main problem.  Can you please
try this on your host?


>From 967e0448234ceede5d399ffbb3ca9759ed31071b Mon Sep 17 00:00:00 2001
From: Paul Eggert <address@hidden>
Date: Mon, 27 Dec 2010 00:21:02 -0800
Subject: [PATCH] utimens: work around glibc rounding bug on older Linux kernels

* lib/utimens.c (fdutimens): If invoking futimesat or futimes
on Linux with a glibc whose utimes might not work, then work
around a longstanding glibc bug involving rounding rather than
truncated time stamps.  Reported for Linux 2.4.21 by Bruno Haible in
<http://lists.gnu.org/archive/html/bug-gnulib/2010-11/msg00113.html>.
---
 ChangeLog     |    9 +++++++++
 lib/utimens.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8de6347..859685b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-12-27  Paul Eggert  <address@hidden>
+
+       utimens: work around glibc rounding bug on older Linux kernels
+       * lib/utimens.c (fdutimens): If invoking futimesat or futimes
+       on Linux with a glibc whose utimes might not work, then work
+       around a longstanding glibc bug involving rounding rather than
+       truncated time stamps.  Reported for Linux 2.4.21 by Bruno Haible in
+       <http://lists.gnu.org/archive/html/bug-gnulib/2010-11/msg00113.html>.
+
 2010-12-26  Bruno Haible  <address@hidden>
 
        inet_ntop: Hide mismatch of declaration on NonStop Kernel.
diff --git a/lib/utimens.c b/lib/utimens.c
index 088c4ba..99b2290 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -330,12 +330,53 @@ fdutimens (int fd, char const *file, struct timespec 
const timespec[2])
            worth optimizing, and who knows what other messed-up systems
            are out there?  So play it safe and fall back on the code
            below.  */
-# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
-        if (futimesat (fd, NULL, t) == 0)
-          return 0;
-# elif HAVE_FUTIMES
+
+# if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
+#  if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
+#   undef futimes
+#   define futimes(fd, t) futimesat (fd, NULL, t)
+#  endif
         if (futimes (fd, t) == 0)
-          return 0;
+          {
+#  if __linux__ && __GLIBC__ && ! HAVE_WORKING_UTIMES
+            /* Work around a longstanding glibc bug, still present as
+               of 2010-12-27.  On older Linux kernels that lack both
+               utimensat and utimes, glibc's futimes rounds instead of
+               truncating when falling back on utime.  The same bug
+               occurs in futimesat with a null 2nd arg.  */
+            if (t)
+              {
+                bool abig = 500000 <= t[0].tv_usec;
+                bool mbig = 500000 <= t[1].tv_usec;
+                if ((abig | mbig) && fstat (fd, &st) == 0)
+                  {
+                    /* If these two subtractions overflow, they'll
+                       track the overflows inside the buggy glibc.  */
+                    time_t adiff = st.st_atime - t[0].tv_sec;
+                    time_t mdiff = st.st_mtime - t[1].tv_sec;
+
+                    struct timeval *tt = NULL;
+                    struct timeval truncated_timeval[2];
+                    truncated_timeval[0] = t[0];
+                    truncated_timeval[1] = t[1];
+                    if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
+                      {
+                        tt = truncated_timeval;
+                        tt[0].tv_usec = 0;
+                      }
+                    if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
+                      {
+                        tt = truncated_timeval;
+                        tt[1].tv_usec = 0;
+                      }
+                    if (tt)
+                      futimes (fd, tt);
+                  }
+              }
+#  endif
+
+            return 0;
+          }
 # endif
       }
 #endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
-- 
1.7.2





reply via email to

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