bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH] fdutimensat: add an atflag parameter


From: Eric Blake
Subject: [PATCH] fdutimensat: add an atflag parameter
Date: Thu, 16 Sep 2010 17:28:36 -0600

* lib/fdutimensat.c (fdutimensat): Add new parameter.
* lib/utimens.h (fdutimensat): Update prototype.
* tests/test-fdutimensat.c: Adjust test to match.
* NEWS: Document the change.
Suggested by Paul Eggert.

Signed-off-by: Eric Blake <address@hidden>
---

> > Makes sense, and easy enough to fix.  It's a gnulib API, so with proper
> > notice in NEWS, we can add a parameter and adjust all callers.
> OK; could you do that please?  I don't know who else is using it.
> In the meantime tar can wait until it's in.  Thanks.

Sure. In fact, coreutils wasn't (quite) using the old interface,
so my coreutils patch to touch.c will be to use this newer
interface (it is certainly easier than choosing between
lutimens/gl_futimens on the fly, where gl_futimens was the
older function name before fdutimensat).

 ChangeLog                |    9 +++++++++
 NEWS                     |    3 +++
 lib/fdutimensat.c        |   21 ++++++++++++++++++---
 lib/utimens.h            |    3 ++-
 tests/test-fdutimensat.c |   24 ++++++++++++++++++------
 5 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a628946..7843aae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,15 @@
        * lib/stdlib.in.h: Clarify the MirBSD bug regarding WEXITSTATUS.
        * doc/posix-headers/stdlib.texi (stdlib.h): Likewise.

+2010-09-16  Eric Blake  <address@hidden>
+
+       fdutimensat: add an atflag parameter
+       * lib/fdutimensat.c (fdutimensat): Add new parameter.
+       * lib/utimens.h (fdutimensat): Update prototype.
+       * tests/test-fdutimensat.c: Adjust test to match.
+       * NEWS: Document the change.
+       Suggested by Paul Eggert.
+
 2010-09-15  Eric Blake  <address@hidden>

        stdlib: work around MirBSD WEXITSTATUS bug
diff --git a/NEWS b/NEWS
index 712408f..7d01eef 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ User visible incompatible changes

 Date        Modules         Changes

+2010-09-16  fdutimensat     The function now takes a new parameter; old users
+                            can safely pass atflag=0 for no semantic change.
+
 2010-09-13  regex           The module is not guaranteeing anymore support for
                             64-bit regoff_t on 64-bit systems.  The size of
                             regoff_t will always be 32-bit unless the program
diff --git a/lib/fdutimensat.c b/lib/fdutimensat.c
index 7c08a52..77f893b 100644
--- a/lib/fdutimensat.c
+++ b/lib/fdutimensat.c
@@ -35,16 +35,31 @@
    use just futimes (or equivalent) instead of utimes (or equivalent),
    and fail if on an old system without futimes (or equivalent).
    If TIMESPEC is null, set the time stamps to the current time.
+   ATFLAG must be 0 if FD is non-negative; otherwise it may be
+   AT_SYMLINK_NOFOLLOW to operate on FILE as a symlink.
    Return 0 on success, -1 (setting errno) on failure.  */

 int
-fdutimensat (int dir, char const *file, int fd, struct timespec const ts[2])
+fdutimensat (int dir, char const *file, int fd, struct timespec const ts[2],
+             int atflag)
 {
   int result = 1;
+  if (atflag & ~AT_SYMLINK_NOFOLLOW)
+    {
+      errno = EINVAL;
+      return -1;
+    }
   if (0 <= fd)
-    result = futimens (fd, ts);
+    {
+      if (atflag)
+        {
+          errno = EINVAL;
+          return -1;
+        }
+      result = futimens (fd, ts);
+    }
   if (file && (fd < 0 || (result == -1 && errno == ENOSYS)))
-    result = utimensat (dir, file, ts, 0);
+    result = utimensat (dir, file, ts, atflag);
   if (result == 1)
     {
       errno = EBADF;
diff --git a/lib/utimens.h b/lib/utimens.h
index bb0326d..f651bee 100644
--- a/lib/utimens.h
+++ b/lib/utimens.h
@@ -8,7 +8,8 @@ int lutimens (char const *, struct timespec const [2]);
 # include <fcntl.h>
 # include <sys/stat.h>

-int fdutimensat (int dir, char const *name, int fd, struct timespec const [2]);
+int fdutimensat (int dir, char const *name, int fd, struct timespec const [2],
+                 int atflag);

 /* Using this function makes application code slightly more readable.  */
 static inline int
diff --git a/tests/test-fdutimensat.c b/tests/test-fdutimensat.c
index 949ca47..67f03bb 100644
--- a/tests/test-fdutimensat.c
+++ b/tests/test-fdutimensat.c
@@ -40,7 +40,7 @@ static int dfd = AT_FDCWD;
 static int
 do_futimens (int fd, struct timespec const times[2])
 {
-  return fdutimensat (dfd, NULL, fd, times);
+  return fdutimensat (dfd, NULL, fd, times, 0);
 }

 /* Test the use of file descriptors alongside a name.  */
@@ -52,7 +52,7 @@ do_fdutimens (char const *name, struct timespec const 
times[2])
   if (fd < 0)
     fd = openat (dfd, name, O_RDONLY);
   errno = 0;
-  result = fdutimensat (dfd, name, fd, times);
+  result = fdutimensat (dfd, name, fd, times, 0);
   if (0 <= fd)
     {
       int saved_errno = errno;
@@ -69,11 +69,18 @@ do_lutimens (const char *name, struct timespec const 
times[2])
   return lutimensat (dfd, name, times);
 }

+/* Wrap fdutimensat to behave like lutimens.  */
+static int
+do_lutimens1 (const char *name, struct timespec const times[2])
+{
+  return fdutimensat (dfd, name, -1, times, AT_SYMLINK_NOFOLLOW);
+}
+
 /* Wrap fdutimensat to behave like utimens.  */
 static int
 do_utimens (const char *name, struct timespec const times[2])
 {
-  return fdutimensat (dfd, name, -1, times);
+  return fdutimensat (dfd, name, -1, times, 0);
 }

 int
@@ -94,12 +101,14 @@ main (void)
   result3 = test_lutimens (do_lutimens, (result1 + result2) == 0);
   /* We expect 0/0, 0/77, or 77/77, but not 77/0.  */
   ASSERT (result1 <= result3);
+  ASSERT (test_lutimens (do_lutimens1, (result1 + result2) == 0) == result3);
   dfd = open (".", O_RDONLY);
   ASSERT (0 <= dfd);
   ASSERT (test_utimens (do_utimens, false) == result1);
   ASSERT (test_utimens (do_fdutimens, false) == result1);
   ASSERT (test_futimens (do_futimens, false) == result2);
   ASSERT (test_lutimens (do_lutimens, false) == result3);
+  ASSERT (test_lutimens (do_lutimens1, false) == result3);

   /* Directory relative tests.  */
   ASSERT (mkdir (BASE "dir", 0700) == 0);
@@ -107,12 +116,15 @@ main (void)
   fd = creat ("file", 0600);
   ASSERT (0 <= fd);
   errno = 0;
-  ASSERT (fdutimensat (fd, ".", AT_FDCWD, NULL) == -1);
+  ASSERT (fdutimensat (fd, ".", fd, NULL, AT_SYMLINK_NOFOLLOW) == -1);
+  ASSERT (errno == EINVAL);
+  errno = 0;
+  ASSERT (fdutimensat (fd, ".", AT_FDCWD, NULL, 0) == -1);
   ASSERT (errno == ENOTDIR);
   {
     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
     struct stat st;
-    ASSERT (fdutimensat (dfd, BASE "dir/file", fd, ts) == 0);
+    ASSERT (fdutimensat (dfd, BASE "dir/file", fd, ts, 0) == 0);
     ASSERT (stat ("file", &st) == 0);
     ASSERT (st.st_atime == Y2K);
     ASSERT (get_stat_atime_ns (&st) == 0);
@@ -122,7 +134,7 @@ main (void)
   ASSERT (close (fd) == 0);
   ASSERT (close (dfd) == 0);
   errno = 0;
-  ASSERT (fdutimensat (dfd, ".", -1, NULL) == -1);
+  ASSERT (fdutimensat (dfd, ".", -1, NULL, 0) == -1);
   ASSERT (errno == EBADF);

   /* Cleanup.  */
-- 
1.7.2.3




reply via email to

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