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 <egg...@cs.ucla.edu> 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 <egg...@cs.ucla.edu> + + 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 <br...@clisp.org> 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