bug-gnulib
[Top][All Lists]
Advanced

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

utimens on older linux


From: Eric Blake
Subject: utimens on older linux
Date: Wed, 25 Nov 2009 06:41:22 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090812 Thunderbird/2.0.0.23 Mnenhy/0.7.6.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

As discussed on coreutils; some Linux kernels support utimensat but not
symlink timestamps.  Now pushed.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAksNNAIACgkQ84KuGfSFAYDqBACeIbr23Cz1Pl8Bu7r8K1LS11E7
ffAAoNC7kXY7WeZm8Suzg2lCSkN0ZK6A
=6XKe
-----END PGP SIGNATURE-----
>From 0457832f3edc43cfec9edbc14aef7e4e3dee9c83 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Tue, 24 Nov 2009 10:07:57 -0700
Subject: [PATCH] utimens: work around older Linux failure with symlinks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Some Linux kernel versions support utimensat(,0) but not
utimensat(,AT_SYMLINK_NOFOLLOW), even for non-symlinks.  Had the
fallback code for regular files been reached, it would have truncated
timestamps.  But since glibc lutimes just wraps utimensat, and we
didn't expect ENOSYS from lutimes, the fallback wasn't even reached.

* lib/utimens.c (lutimensat_works_really): New variable.
(fdutimens, lutimens): Use it to manage kernels that support
nanosecond times on files, but not on symlinks.
Reported by Ondřej Vašík.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog     |    6 ++++++
 lib/utimens.c |   24 ++++++++++++++++--------
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 3af15c2..2b4cf53 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2009-11-25  Eric Blake  <address@hidden>

+       utimens: work around older Linux failure with symlinks
+       * lib/utimens.c (lutimensat_works_really): New variable.
+       (fdutimens, lutimens): Use it to manage kernels that support
+       nanosecond times on files, but not on symlinks.
+       Reported by Ondřej Vašík.
+
        utimes: fix configure grammar
        * m4/utimes.m4 (gl_FUNC_UTIMES): Delete spurious word.

diff --git a/lib/utimens.c b/lib/utimens.c
index eb63487..9e66ffc 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -54,10 +54,12 @@ struct utimbuf
 #undef utimensat

 #if HAVE_UTIMENSAT || HAVE_FUTIMENS
-/* Cache variable for whether syscall works; used to avoid calling the
-   syscall if we know it will just fail with ENOSYS.  0 = unknown, 1 =
-   yes, -1 = no.  */
+/* Cache variables for whether the utimensat syscall works; used to
+   avoid calling the syscall if we know it will just fail with ENOSYS.
+   There are some Linux kernel versions where a flag of 0 passes, but
+   not AT_SYMLINK_NOFOLLOW.  0 = unknown, 1 = yes, -1 = no.  */
 static int utimensat_works_really;
+static int lutimensat_works_really;
 #endif /* HAVE_UTIMENSAT || HAVE_UTIMENSAT */

 /* Solaris 9 mistakenly succeeds when given a non-directory with a
@@ -242,6 +244,7 @@ fdutimens (char const *file, int fd, struct timespec const 
timespec[2])
 # endif /* HAVE_FUTIMENS */
     }
   utimensat_works_really = -1;
+  lutimensat_works_really = -1;
 #endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */

   /* The platform lacks an interface to set file timestamps with
@@ -381,7 +384,7 @@ lutimens (char const *file, struct timespec const 
timespec[2])
      worry about bogus return values.  */

 #if HAVE_UTIMENSAT
-  if (0 <= utimensat_works_really)
+  if (0 <= lutimensat_works_really)
     {
       int result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
 # ifdef __linux__
@@ -398,10 +401,11 @@ lutimens (char const *file, struct timespec const 
timespec[2])
       if (result == 0 || errno != ENOSYS)
         {
           utimensat_works_really = 1;
+          lutimensat_works_really = 1;
           return result;
         }
     }
-  utimensat_works_really = -1;
+  lutimensat_works_really = -1;
 #endif /* HAVE_UTIMENSAT */

   /* The platform lacks an interface to set file timestamps with
@@ -416,7 +420,9 @@ lutimens (char const *file, struct timespec const 
timespec[2])
         return 0;
     }

-#if HAVE_LUTIMES
+  /* On Linux, lutimes is a thin wrapper around utimensat, so there is
+     no point trying lutimes if utimensat failed with ENOSYS.  */
+#if HAVE_LUTIMES && !HAVE_UTIMENSAT
   {
     struct timeval timeval[2];
     struct timeval const *t;
@@ -431,9 +437,11 @@ lutimens (char const *file, struct timespec const 
timespec[2])
     else
       t = NULL;

-    return lutimes (file, t);
+    result = lutimes (file, t);
+    if (result == 0 || errno != ENOSYS)
+      return result;
   }
-#endif /* HAVE_LUTIMES */
+#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */

   /* Out of luck for symlinks, but we still handle regular files.  */
   if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
-- 
1.6.5.rc1


reply via email to

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