utimens: validate futimens usage
authorEric Blake <ebb9@byu.net>
Tue, 6 Oct 2009 18:23:32 +0000 (12:23 -0600)
committerEric Blake <ebb9@byu.net>
Sat, 10 Oct 2009 14:28:00 +0000 (08:28 -0600)
Using gl_futimens(fd,NULL,times) as an implementation for futimens
won't work unless we reliably detect EBADF for out-of-range fd.
Also catches a Linux bug with futimens(AT_FDCWD,NULL) changing ".".
mingw <utime.h> has a bug where utime's second argument is not const.

* lib/utimens.c (gl_futimens): Require valid fd up front, using
fewer syscalls on failure later on.  Avoid compiler warning on
mingw.
* modules/utimens (Depends-on): Add dup2.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/utimens.c
modules/utimens

index 16e99df..ffbfe70 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2009-10-10  Eric Blake  <ebb9@byu.net>
 
+       utimens: validate futimens usage
+       * lib/utimens.c (gl_futimens): Require valid fd up front, using
+       fewer syscalls on failure later on.  Avoid compiler warning on
+       mingw.
+       * modules/utimens (Depends-on): Add dup2.
+
        utimens: add test
        * modules/utimens-tests: New test.
        * tests/test-utimens.h: New file.
index 10d2c82..b1ac350 100644 (file)
@@ -55,9 +55,22 @@ struct utimbuf
    Return 0 on success, -1 (setting errno) on failure.  */
 
 int
-gl_futimens (int fd _UNUSED_PARAMETER_,
-             char const *file, struct timespec const timespec[2])
+gl_futimens (int fd, char const *file, struct timespec const timespec[2])
 {
+  /* Require that at least one of FD or FILE are valid.  Works around
+     a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
+     than failing.  */
+  if (!file)
+    {
+      if (fd < 0)
+        {
+          errno = EBADF;
+          return -1;
+        }
+      if (dup2 (fd, fd) != fd)
+        return -1;
+    }
+
   /* Some Linux-based NFS clients are buggy, and mishandle time stamps
      of files in NFS file systems in some cases.  We have no
      configure-time test for this, but please see
@@ -163,17 +176,6 @@ gl_futimens (int fd _UNUSED_PARAMETER_,
 #if ! (HAVE_FUTIMESAT || (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
         errno = ENOSYS;
 #endif
-
-        /* Prefer EBADF to ENOSYS if both error numbers apply.  */
-        if (errno == ENOSYS)
-          {
-            int fd2 = dup (fd);
-            int dup_errno = errno;
-            if (0 <= fd2)
-              close (fd2);
-            errno = (fd2 < 0 && dup_errno == EBADF ? EBADF : ENOSYS);
-          }
-
         return -1;
       }
 
@@ -182,7 +184,7 @@ gl_futimens (int fd _UNUSED_PARAMETER_,
 #else
     {
       struct utimbuf utimbuf;
-      struct utimbuf const *ut;
+      struct utimbuf *ut;
       if (timespec)
         {
           utimbuf.actime = timespec[0].tv_sec;
index 4251485..48fbe8e 100644 (file)
@@ -9,6 +9,7 @@ m4/utimens.m4
 m4/utimes.m4
 
 Depends-on:
+dup2
 errno
 sys_time
 time