From af32ee824ee18255839f9812b8ed61aa5257a82b Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 16 Mar 2024 22:27:48 -0700 Subject: [PATCH] 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. --- ChangeLog | 7 +++++++ doc/glibc-functions/renameat2.texi | 2 ++ lib/renameatu.c | 8 ++++++++ tests/test-renameatu.c | 7 +++++++ 4 files changed, 24 insertions(+) diff --git a/ChangeLog b/ChangeLog index 258691d551..9deed7d1d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2024-03-16 Paul Eggert + + 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 gnulib-tool.py: Follow gnulib-tool changes, part 59. diff --git a/doc/glibc-functions/renameat2.texi b/doc/glibc-functions/renameat2.texi index a59b797260..15cf9d1d7f 100644 --- a/doc/glibc-functions/renameat2.texi +++ b/doc/glibc-functions/renameat2.texi @@ -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. diff --git a/lib/renameatu.c b/lib/renameatu.c index 174081c16b..6893232516 100644 --- a/lib/renameatu.c +++ b/lib/renameatu.c @@ -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); } diff --git a/tests/test-renameatu.c b/tests/test-renameatu.c index 68faeb83e7..9f3a71f0d9 100644 --- a/tests/test-renameatu.c +++ b/tests/test-renameatu.c @@ -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); -- 2.39.5