This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

glibc utimes glitch with coreutils 'touch'


In <http://mail.gnu.org/archive/html/bug-gnulib/2003-08/msg00038.html>
Jim Meyering <jim@meyering.net> writes:

> Here are the symptoms of the utimes failure I mentioned recently.

You're suffering from Debian bug 202243 ("utimes() broken"); see
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=202243>.  The patch
proposed there won't entirely fix the bug, though, since it causes
'utimes' to round instead of truncate.  Historically, utimes truncated
when it couldn't store the microseconds, and the coreutils 'touch' code in
<http://mail.gnu.org/archive/html/bug-coreutils/2003-08/msg00016.html>
relies on this truncation.

I tried to find out why glibc changed from truncation to rounding.
Ulrich Drepper checked in a new Linux version of utimes on 2003-07-12,
to support newer Linux kernels that have utimes support.  On older
kernels this new code attempted to round, even though the usual
practice with timestamps is to truncate when going to a lower
resolution.  I don't know why rounding was introduced here.

(Personally I wish Linux would let me set the file's timestamp to the
nearest nanosecond, as that would avoid all this mess entirely.)

I'll submit an alternate patch to coreutils so that it works around
this glibc glitch.  The simplest workaround is to not invoke utimes
when building with glibc; perhaps I can improve on that, but I don't
know.

I propose the following patch to fix glibc:

2003-08-09  Paul Eggert  <eggert@twinsun.com>

	Revert to utimes's previous (i.e., pre-2003-07-12) behavior of
	truncating fractional parts of timestamps that it can't use,
        instead of attempting to round.
	* sysdeps/unix/sysv/linux/utimes.c (__utimes):
	Fix actime and modtime computation to truncate microseconds
	rather than attempting to round.
	* sysdeps/unix/sysv/linux/futimes.c (__futimes): Likewise.
	* sysdeps/posix/utimes.c (__utimes): Likewise.

Index: sysdeps/unix/sysv/linux/utimes.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/utimes.c,v
retrieving revision 1.3
diff -p -u -r1.3 utimes.c
--- sysdeps/unix/sysv/linux/utimes.c	31 Jul 2003 19:04:13 -0000	1.3
+++ sysdeps/unix/sysv/linux/utimes.c	10 Aug 2003 06:15:53 -0000
@@ -47,8 +47,8 @@ __utimes (const char *file, const struct
   if (tvp != NULL)
     {
       times = &buf;
-      buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
-      buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
+      buf.actime = tvp[0].tv_sec + tvp[0].tv_usec / 1000000;
+      buf.modtime = tvp[1].tv_sec + tvp[1].tv_usec / 1000000;
     }
   else
     times = NULL;
Index: sysdeps/unix/sysv/linux/futimes.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/futimes.c,v
retrieving revision 1.6
diff -p -u -r1.6 futimes.c
--- sysdeps/unix/sysv/linux/futimes.c	31 Jul 2003 19:04:13 -0000	1.6
+++ sysdeps/unix/sysv/linux/futimes.c	10 Aug 2003 06:15:53 -0000
@@ -58,8 +58,8 @@ __futimes (int fd, const struct timeval 
   if (tvp != NULL)
     {
       times = &buf;
-      buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
-      buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
+      buf.actime = tvp[0].tv_sec + tvp[0].tv_usec / 1000000;
+      buf.modtime = tvp[1].tv_sec + tvp[1].tv_usec / 1000000;
     }
   else
     times = NULL;
Index: sysdeps/posix/utimes.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/posix/utimes.c,v
retrieving revision 1.7
diff -p -u -r1.7 utimes.c
--- sysdeps/posix/utimes.c	31 Jul 2003 19:04:13 -0000	1.7
+++ sysdeps/posix/utimes.c	10 Aug 2003 06:15:53 -0000
@@ -31,8 +31,8 @@ __utimes (const char *file, const struct
   if (tvp)
     {
       times = &buf;
-      buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
-      buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
+      buf.actime = tvp[0].tv_sec + tvp[0].tv_usec / 1000000;
+      buf.modtime = tvp[1].tv_sec + tvp[1].tv_usec / 1000000;
     }
   else
     times = NULL;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]