From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 25 Mar 2021 03:40:46 +0000 (-0700)
Subject: renameatu: work around macOS 11.2 renameatx_np bug
X-Git-Tag: v1.0~3004
X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=a37df18aae6c52fab2c7efebff28585e5365268e;p=gnulib.git

renameatu: work around macOS 11.2 renameatx_np bug

* lib/renameatu.c (renameatu) [RENAME_EXCL]: Use lstatat test here too.
---

diff --git a/ChangeLog b/ChangeLog
index b2004479a2..af9eb725cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2021-03-24  Paul Eggert  <eggert@cs.ucla.edu>
+
+	renameatu: work around macOS 11.2 renameatx_np bug
+	* lib/renameatu.c (renameatu) [RENAME_EXCL]: Use lstatat test here too.
+
 2021-03-22  Bruno Haible  <bruno@clisp.org>
 
 	clean-temp-simple: Fix a rare memory leak.
diff --git a/lib/renameatu.c b/lib/renameatu.c
index c493a38dc1..38438a4ef1 100644
--- a/lib/renameatu.c
+++ b/lib/renameatu.c
@@ -122,18 +122,19 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
             | (flags & RENAME_NOREPLACE ? RENAME_EXCL : 0));
 # endif
 
-# if !defined RENAME_EXCL
   if ((flags & RENAME_NOREPLACE) != 0)
     {
       /* This has a race between the call to lstatat and the calls to
-         renameat below.  */
+         renameat below.  This lstatat is needed even if RENAME_EXCL
+         is defined, because RENAME_EXCL is buggy on macOS 11.2:
+         renameatx_np (fd, "X", fd, "X", RENAME_EXCL) incorrectly
+         succeeds when X exists.  */
       if (lstatat (fd2, dst, &dst_st) == 0 || errno == EOVERFLOW)
         return errno_fail (EEXIST);
       if (errno != ENOENT)
         return -1;
       dst_found_nonexistent = true;
     }
-# endif
 
   /* Let strace see any ENOENT failure.  */
   src_len = strlen (src);