renameatu: support RENAME_EXCHANGE on macOS
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 17 Mar 2024 05:27:48 +0000 (22:27 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 17 Mar 2024 05:29:02 +0000 (22:29 -0700)
* lib/renameatu.c (renameat2ish, renameatu) [RENAME_SWAP]:
Use macOS RENAME_SWAP to implement GNU/Linux RENAME_EXCHANGE.
* tests/test-renameatu.c (main): Add a test for RENAME_EXCHANGE.

ChangeLog
doc/glibc-functions/renameat2.texi
lib/renameatu.c
tests/test-renameatu.c

index 258691d55137f1a94f99138fcd2675e76f92fc02..9deed7d1d9467071eb4be6a6f8d83a16963f5b3e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-03-16  Paul Eggert  <eggert@cs.ucla.edu>
+
+       renameatu: support RENAME_EXCHANGE on macOS
+       * lib/renameatu.c (renameat2ish, renameatu) [RENAME_SWAP]:
+       Use macOS RENAME_SWAP to implement GNU/Linux RENAME_EXCHANGE.
+       * tests/test-renameatu.c (main): Add a test for RENAME_EXCHANGE.
+
 2024-03-16  Collin Funk  <collin.funk1@gmail.com>
 
        gnulib-tool.py: Follow gnulib-tool changes, part 59.
index a59b797260aa1c93865e1490d7b429338e671a4b..15cf9d1d7f0d99c7d6c82036df335aa06fab601b 100644 (file)
@@ -17,3 +17,5 @@ This function exists only on Linux and is therefore
 missing on many platforms:
 glibc 2.27, macOS 11.1, FreeBSD 14.0, NetBSD 9.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android API level 29.
 @end itemize
+
+The @code{renameatu} module addresses some of these portability issues.
index 174081c16b0d3c3cc122274ed7fc564738f81fe6..6893232516a202074f1dbc32d573242d87d8d304 100644 (file)
@@ -70,6 +70,10 @@ static int
 renameat2ish (int fd1, char const *src, int fd2, char const *dst,
               unsigned int flags)
 {
+# ifdef RENAME_SWAP
+  if (flags & RENAME_EXCHANGE)
+    return renameatx_np (fd1, src, fd2, dst, RENAME_SWAP);
+# endif
 # ifdef RENAME_EXCL
   if (flags)
     {
@@ -145,6 +149,10 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
       dst_found_nonexistent = true;
       break;
 
+    case RENAME_EXCHANGE:
+#ifdef RENAME_SWAP
+      break;
+#endif
     default:
       return errno_fail (ENOTSUP);
     }
index 68faeb83e70a37a5619331ff234bee2b814c537e..9f3a71f0d9680fdbe094fbeb04e62771afc09509 100644 (file)
@@ -205,6 +205,13 @@ main (void)
            == -1)
           && errno == EEXIST);
 
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "sub2", dfd, BASE "sub1", RENAME_EXCHANGE) < 0
+          ? errno == EINVAL || errno == ENOSYS || errno == ENOTSUP
+          : (renameatu (dfd, BASE "sub1/file", dfd, BASE "sub2/file",
+                        RENAME_NOREPLACE)
+             == 0));
+
   /* Cleanup.  */
   ASSERT (close (dfd) == 0);
   ASSERT (unlink (BASE "sub2/file") == 0);