changeset 12157:7fb8a2ac5948

utimens: validate futimens usage 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>
author Eric Blake <ebb9@byu.net>
date Tue, 06 Oct 2009 12:23:32 -0600
parents 3c7d1f073266
children 899dd13e9f8b
files ChangeLog lib/utimens.c modules/utimens
diffstat 3 files changed, 23 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -55,9 +55,22 @@
    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 @@
 #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 @@
 #else
     {
       struct utimbuf utimbuf;
-      struct utimbuf const *ut;
+      struct utimbuf *ut;
       if (timespec)
         {
           utimbuf.actime = timespec[0].tv_sec;
--- a/modules/utimens
+++ b/modules/utimens
@@ -9,6 +9,7 @@
 m4/utimes.m4
 
 Depends-on:
+dup2
 errno
 sys_time
 time