bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 1/2] renameat2: port to Solaris 10


From: Paul Eggert
Subject: [PATCH 1/2] renameat2: port to Solaris 10
Date: Thu, 27 Jul 2017 18:03:36 -0700

* lib/renameat2.c (rename_noreplace): Use lstat, not faccessat
with AT_SYMLINK_NOFOLLOW (which is not portable).
(renameat): Undef before using, to avoid endless recursion when
the replacement renameat calls renameat2 which calls the
replacement renameat.
(renameat2): Use lstatat, not faccessat with AT_SYMLINK_NOFOLLOW.
* modules/renameat2 (Depends-on): Remove faccessat.
* modules/renameat-tests (test_renameat_LDADD):
* modules/renameat2-tests (test_renameat2_LDADD):
Remove $(LIB_EACCESS).
---
 ChangeLog               | 12 ++++++++++++
 lib/renameat2.c         | 37 +++++++++++++++++++++++--------------
 modules/renameat-tests  |  2 +-
 modules/renameat2       |  1 -
 modules/renameat2-tests |  2 +-
 5 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index d922e31..ec39037 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2017-07-27  Paul Eggert  <address@hidden>
 
+       renameat2: port to Solaris 10
+       * lib/renameat2.c (rename_noreplace): Use lstat, not faccessat
+       with AT_SYMLINK_NOFOLLOW (which is not portable).
+       (renameat): Undef before using, to avoid endless recursion when
+       the replacement renameat calls renameat2 which calls the
+       replacement renameat.
+       (renameat2): Use lstatat, not faccessat with AT_SYMLINK_NOFOLLOW.
+       * modules/renameat2 (Depends-on): Remove faccessat.
+       * modules/renameat-tests (test_renameat_LDADD):
+       * modules/renameat2-tests (test_renameat2_LDADD):
+       Remove $(LIB_EACCESS).
+
        renameat2: new module
        Although the Linux syscall renameat2 is not in glibc (yet?), it is
        useful to have access to its RENAME_NOREPLACE flag.
diff --git a/lib/renameat2.c b/lib/renameat2.c
index 19df58c..e223653 100644
--- a/lib/renameat2.c
+++ b/lib/renameat2.c
@@ -51,14 +51,15 @@ errno_fail (int e)
 static int
 rename_noreplace (char const *src, char const *dst)
 {
-  /* This has a race between the call to faccessat and the call to rename.  */
-  int r = faccessat (AT_FDCWD, dst, F_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW);
-  reurn (r == 0 ? errno_fail (EEXIST)
-         : errno == ENOENT ? rename (src, dst)
-         : r);
+  /* This has a race between the call to lstat and the call to rename.  */
+  struct stat st;
+  return (lstat (dst, &st) == 0 ? errno_fail (EEXIST)
+          : errno == ENOENT ? rename (src, dst)
+          : -1);
 }
 #endif
 
+#undef renameat
 
 /* Rename FILE1, in the directory open on descriptor FD1, to FILE2, in
    the directory open on descriptor FD2.  If possible, do it without
@@ -91,20 +92,23 @@ renameat2 (int fd1, char const *src, int fd2, char const 
*dst,
   int rename_errno = ENOTDIR;
   struct stat src_st;
   struct stat dst_st;
+  bool dst_found_nonexistent = false;
 
   if (flags != 0)
     {
-      int r;
       /* RENAME_NOREPLACE is the only flag currently supported.  */
       if (flags & ~RENAME_NOREPLACE)
         return errno_fail (ENOTSUP);
-      /* This has a race between the call to faccessat and the
-         call to renameat.  */
-      r = faccessat (fd2, dst, F_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW);
-      if (r == 0)
-        return errno_fail (EEXIST);
-      if (errno != ENOENT)
-        return r;
+      else
+        {
+          /* This has a race between the call to lstatat and the calls to
+             renameat below.  */
+          if (lstatat (fd2, dst, &dst_st) == 0)
+            return errno_fail (EEXIST);
+          if (errno != ENOENT)
+            return -1;
+          dst_found_nonexistent = true;
+        }
     }
 
   /* Let strace see any ENOENT failure.  */
@@ -124,7 +128,12 @@ renameat2 (int fd1, char const *src, int fd2, char const 
*dst,
      before calling rename.  */
   if (lstatat (fd1, src, &src_st))
     return -1;
-  if (lstatat (fd2, dst, &dst_st))
+  if (dst_found_nonexistent)
+    {
+      if (!S_ISDIR (src_st.st_mode))
+        return errno_fail (ENOENT);
+    }
+  else if (lstatat (fd2, dst, &dst_st))
     {
       if (errno != ENOENT || !S_ISDIR (src_st.st_mode))
         return -1;
diff --git a/modules/renameat-tests b/modules/renameat-tests
index 4e9bf2f..970ebd7 100644
--- a/modules/renameat-tests
+++ b/modules/renameat-tests
@@ -17,4 +17,4 @@ configure.ac:
 Makefile.am:
 TESTS += test-renameat
 check_PROGRAMS += test-renameat
-test_renameat_LDADD = $(LDADD) $(LIB_EACCESS) @LIBINTL@
+test_renameat_LDADD = $(LDADD) @LIBINTL@
diff --git a/modules/renameat2 b/modules/renameat2
index f0ce195..54f72e1 100644
--- a/modules/renameat2
+++ b/modules/renameat2
@@ -10,7 +10,6 @@ m4/renameat.m4
 Depends-on:
 stdio
 extensions
-faccessat
 fcntl-h
 filenamecat-lgpl [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
 openat-h         [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
diff --git a/modules/renameat2-tests b/modules/renameat2-tests
index efcc33d..accf3c4 100644
--- a/modules/renameat2-tests
+++ b/modules/renameat2-tests
@@ -17,4 +17,4 @@ configure.ac:
 Makefile.am:
 TESTS += test-renameat2
 check_PROGRAMS += test-renameat2
-test_renameat2_LDADD = $(LDADD) $(LIB_EACCESS) @LIBINTL@
+test_renameat2_LDADD = $(LDADD) @LIBINTL@
-- 
2.7.4




reply via email to

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