On Cygwin 3.4.6, but not on Cygwin 3.5.3, I see a test failure: FAIL: test-renameatu.exe
The cause is that the renameat2 function, which was added in Cygwin 2.9.0, does not fail as expected when the RENAME_NOREPLACE flag is specified and source and destination are the same. The workaround is simply to not use renameat2 in this case. Done through this patch. It fixes the test failure. 2024-05-23 Bruno Haible <br...@clisp.org> renameatu: Work around Cygwin 3.4.6 bug. * m4/renameat.m4 (gl_FUNC_RENAMEAT): Test whether renameat2 works, and define HAVE_WORKING_RENAMEAT2 if so. * lib/renameatu.c (renameatu): Test HAVE_WORKING_RENAMEAT2 instead of HAVE_RENAMEAT2. * doc/glibc-functions/renameat2.texi: Mention the Cygwin bug. diff --git a/doc/glibc-functions/renameat2.texi b/doc/glibc-functions/renameat2.texi index ba577f4e2a..9588225f39 100644 --- a/doc/glibc-functions/renameat2.texi +++ b/doc/glibc-functions/renameat2.texi @@ -13,9 +13,12 @@ Portability problems not fixed by Gnulib: @itemize @item -This function exists only on Linux and is therefore -missing on many platforms: -glibc 2.27, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android API level 29. +This function is missing on many platforms: +glibc 2.27, macOS 11.1, FreeBSD 14.0, NetBSD 10.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, Solaris 11.4, Cygwin 2.8.x, mingw, MSVC 14, Android API level 29. +@item +This function succeeds when the @code{RENAME_NOREPLACE} flag is specified +and the source and destination are the same file, on some platforms: +Cygwin 3.4.6. @end itemize The @code{renameatu} module addresses some of these portability issues. diff --git a/lib/renameatu.c b/lib/renameatu.c index 815e3e0da9..437fc8f71a 100644 --- a/lib/renameatu.c +++ b/lib/renameatu.c @@ -106,7 +106,7 @@ renameatu (int fd1, char const *src, int fd2, char const *dst, int ret_val = -1; int err = EINVAL; -#ifdef HAVE_RENAMEAT2 +#if HAVE_WORKING_RENAMEAT2 ret_val = renameat2 (fd1, src, fd2, dst, flags); err = errno; #elif defined SYS_renameat2 diff --git a/m4/renameat.m4 b/m4/renameat.m4 index 565400f5db..adf1f6bdd0 100644 --- a/m4/renameat.m4 +++ b/m4/renameat.m4 @@ -1,5 +1,5 @@ # renameat.m4 -# serial 4 +# serial 5 dnl Copyright (C) 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -14,6 +14,7 @@ AC_DEFUN([gl_FUNC_RENAMEAT] AC_REQUIRE([gl_FUNC_OPENAT]) AC_REQUIRE([gl_FUNC_RENAME]) AC_REQUIRE([gl_STDIO_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_CHECK_HEADERS([linux/fs.h]) AC_CHECK_FUNCS_ONCE([renameat]) @@ -24,4 +25,39 @@ AC_DEFUN([gl_FUNC_RENAMEAT] REPLACE_RENAMEAT=1 fi gl_CHECK_FUNCS_ANDROID([renameat2], [[#include <stdio.h>]]) + if test $ac_cv_func_renameat2 = yes; then + AC_CACHE_CHECK([whether renameat2 works], + [gl_cv_func_renameat2_works], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include <fcntl.h> + #include <stdio.h> + int main () + { + /* This test fails on Cygwin 3.4.6. */ + if (renameat2 (AT_FDCWD, "conftest.c", AT_FDCWD, "conftest.c", + RENAME_NOREPLACE) == 0) + return 1; + return 0; + } + ]])], + [gl_cv_func_renameat2_works=yes], + [gl_cv_func_renameat2_works=no], + [case "$host_os" in + # Guess yes on Linux. + linux*) gl_cv_func_renameat2_works="guessing yes" ;; + # Guess no on Cygwin. + cygwin*) gl_cv_func_renameat2_works="guessing no" ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_renameat2_works="$gl_cross_guess_normal" ;; + esac + ]) + ]) + case "$gl_cv_func_renameat2_works" in + *yes) + AC_DEFINE([HAVE_WORKING_RENAMEAT2], [1], + [Define if the renameat2 function exists and it works.]) + ;; + esac + fi ])