Hi, This patch works around 2 more issues with GNU/Hurd's renameat/renameat2 functions. When renaming directories, they misbehave if the source or target have a trailing slash.
I wrote small test programs in the glibc bug reports [1] [2]. This patch fixes tests/test-renameat and tests/test-renameat2 in Gnulib. And fixes tests/mv/backup-dir and tests/mv/trailing-slash in Coreutils. Collin [1] https://sourceware.org/PR33607 [2] https://sourceware.org/PR33608
>From fc86d6efdf00ba60106a4c67d36dd0bfc447cf13 Mon Sep 17 00:00:00 2001 Message-ID: <fc86d6efdf00ba60106a4c67d36dd0bfc447cf13.1762494876.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Thu, 6 Nov 2025 21:18:12 -0800 Subject: [PATCH] renameat, renameatu: Work around GNU/Hurd bugs. * lib/renameatu.c (renameatu): Handle RENAME_TRAILING_SLASH_SOURCE_BUG and RENAME_TRAILING_SLASH_DEST_BUG when renameat2 is called. * doc/glibc-functions/renameat2.texi: Mention the bugs. * doc/posix-functions/renameat.texi: Likewise. --- ChangeLog | 8 ++++++++ doc/glibc-functions/renameat2.texi | 10 ++++++++++ doc/posix-functions/renameat.texi | 15 +++++++++++++++ lib/renameatu.c | 14 +++++++++++++- 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f3a5d317fd..2aa4a2b31d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2025-11-06 Collin Funk <[email protected]> + + renameat, renameatu: Work around GNU/Hurd bugs. + * lib/renameatu.c (renameatu): Handle RENAME_TRAILING_SLASH_SOURCE_BUG + and RENAME_TRAILING_SLASH_DEST_BUG when renameat2 is called. + * doc/glibc-functions/renameat2.texi: Mention the bugs. + * doc/posix-functions/renameat.texi: Likewise. + 2025-11-06 Paul Eggert <[email protected]> stdio-windows: fix <stdarg.h> include position diff --git a/doc/glibc-functions/renameat2.texi b/doc/glibc-functions/renameat2.texi index 7d3240bcc6..b4fa607eeb 100644 --- a/doc/glibc-functions/renameat2.texi +++ b/doc/glibc-functions/renameat2.texi @@ -25,6 +25,16 @@ @node renameat2 platforms: @c https://sourceware.org/PR32570 GNU/Hurd with glibc 2.41. +@item +@code{renameat2 (ATFDCWD, "dir", AT_FDCWD, "new/" ...)} fails with +@code{errno} set to @code{ENOENT}, on some platforms: +@c https://sourceware.org/PR33607 +GNU/Hurd with glibc 2.42. +@item +@code{renameat2 (ATFDCWD, "dir/", AT_FDCWD, "new" ...)} fails with +@code{errno} set to @code{ENOTDIR}, on some platforms: +@c https://sourceware.org/PR33608 +GNU/Hurd with glibc 2.42. @end itemize @mindex renameatu diff --git a/doc/posix-functions/renameat.texi b/doc/posix-functions/renameat.texi index 70caa69d32..ad06184c56 100644 --- a/doc/posix-functions/renameat.texi +++ b/doc/posix-functions/renameat.texi @@ -30,6 +30,21 @@ @node renameat This function ignores trailing slashes on symlinks on some platforms, such that @code{renameat(fd,"link/",fd,"new")} corrupts @file{link}: Solaris 9. +@item +@code{renameat (AT_FDCWD, "file", AT_FDCWD, "new/")} succeeds instead of +failing and setting @code{errno} to @code{ENOTDIR}, on some platforms: +@c https://sourceware.org/PR32570 +GNU/Hurd with glibc 2.41. +@item +@code{renameat (ATFDCWD, "dir", AT_FDCWD, "new/")} fails with +@code{errno} set to @code{ENOENT}, on some platforms: +@c https://sourceware.org/PR33607 +GNU/Hurd with glibc 2.42. +@item +@code{renameat (ATFDCWD, "dir/", AT_FDCWD, "new")} fails with +@code{errno} set to @code{ENOTDIR}, on some platforms: +@c https://sourceware.org/PR33608 +GNU/Hurd with glibc 2.42. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/renameatu.c b/lib/renameatu.c index 89653cb3e8..29c4839269 100644 --- a/lib/renameatu.c +++ b/lib/renameatu.c @@ -117,7 +117,19 @@ renameatu (int fd1, char const *src, int fd2, char const *dst, err = errno; #endif - if (! (ret_val < 0 && (err == EINVAL || err == ENOSYS || err == ENOTSUP))) + + if (! (ret_val < 0 && (err == EINVAL || err == ENOSYS || err == ENOTSUP +#if RENAME_TRAILING_SLASH_SOURCE_BUG + || ! (err == ENOTDIR + && ! (0 < strlen (src) + && src[strlen (src) - 1] == '/')) +#endif +#if RENAME_TRAILING_SLASH_DEST_BUG + || ! (err == ENOENT + && ! (0 < strlen (dst) + && dst[strlen (dst) - 1] == '/')) +#endif + ))) return ret_val; #if HAVE_RENAMEAT -- 2.51.1
