bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Cc: "Martin Storsjö" <martin@martin.st>
Subject: renameatu: Fix test failures on macOS
Date: Sat, 02 Jan 2021 17:03:16 +0100	[thread overview]
Message-ID: <2292620.QaEihNl2m5@omega> (raw)
In-Reply-To: <alpine.DEB.2.23.453.2012011509530.4295@cone.martin.st>

On macOS 10.13, I'm seeing these test failures (for a long time already).

FAIL: test-renameat
===================

../../gltests/test-rename.h:619: assertion 'func (BASE "link2/", BASE "link2") == -1' failed
FAIL test-renameat (exit status: 134)

FAIL: test-renameatu
====================

../../gltests/test-rename.h:619: assertion 'func (BASE "link2/", BASE "link2") == -1' failed
FAIL test-renameatu (exit status: 134)

This was also reported by Martin Storsjö.

The situation is that config.h contains:

#define HAVE_RENAMEAT 1
/* #undef HAVE_RENAMEAT2 */
/* #undef RENAME_DEST_EXISTS_BUG */
/* #undef RENAME_HARD_LINK_BUG */
#define RENAME_TRAILING_SLASH_DEST_BUG 1
#define RENAME_TRAILING_SLASH_SOURCE_BUG 1

But the invocation of 'renameatx_np' right at the beginning of renameatu()
assumes that it works without bugs. Which it doesn't.

This patch fixes both test failures.


2021-01-02  Bruno Haible  <bruno@clisp.org>

	renameatu: Fix test failures on macOS.
	Reported by Martin Storsjö <martin@martin.st> in
	<https://lists.gnu.org/archive/html/bug-gnulib/2020-12/msg00003.html>.
	* lib/renameatu.c (renameatu): Don't call renameatx_np right away.
	Instead, treat it as a variant of renameat, with all possible bugs that
	renameat might have.

diff --git a/lib/renameatu.c b/lib/renameatu.c
index 974d234..c493a38 100644
--- a/lib/renameatu.c
+++ b/lib/renameatu.c
@@ -86,14 +86,6 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
 #elif defined SYS_renameat2
   ret_val = syscall (SYS_renameat2, fd1, src, fd2, dst, flags);
   err = errno;
-#elif defined RENAME_EXCL
-  if (! (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE)))
-    {
-      ret_val = renameatx_np (fd1, src, fd2, dst,
-                             ((flags & RENAME_EXCHANGE ? RENAME_SWAP : 0)
-                              | (flags & RENAME_NOREPLACE ? RENAME_EXCL : 0)));
-      err = errno;
-    }
 #endif
 
   if (! (ret_val < 0 && (err == EINVAL || err == ENOSYS || err == ENOTSUP)))
@@ -101,6 +93,9 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
 
 #if HAVE_RENAMEAT
   {
+# if defined RENAME_EXCL                /* macOS */
+  unsigned int uflags;
+# endif
   size_t src_len;
   size_t dst_len;
   char *src_temp = (char *) src;
@@ -112,33 +107,52 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
   struct stat dst_st;
   bool dst_found_nonexistent = false;
 
-  if (flags != 0)
+  /* Check the flags.  */
+# if defined RENAME_EXCL
+  /* We can support RENAME_EXCHANGE and RENAME_NOREPLACE.  */
+  if (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE))
+# else
+  /* RENAME_NOREPLACE is the only flag currently supported.  */
+  if (flags & ~RENAME_NOREPLACE)
+# endif
+    return errno_fail (ENOTSUP);
+
+# if defined RENAME_EXCL
+  uflags = ((flags & RENAME_EXCHANGE ? RENAME_SWAP : 0)
+            | (flags & RENAME_NOREPLACE ? RENAME_EXCL : 0));
+# endif
+
+# if !defined RENAME_EXCL
+  if ((flags & RENAME_NOREPLACE) != 0)
     {
-      /* RENAME_NOREPLACE is the only flag currently supported.  */
-      if (flags & ~RENAME_NOREPLACE)
-        return errno_fail (ENOTSUP);
-      else
-        {
-          /* This has a race between the call to lstatat and the calls to
-             renameat below.  */
-          if (lstatat (fd2, dst, &dst_st) == 0 || errno == EOVERFLOW)
-            return errno_fail (EEXIST);
-          if (errno != ENOENT)
-            return -1;
-          dst_found_nonexistent = true;
-        }
+      /* This has a race between the call to lstatat and the calls to
+         renameat below.  */
+      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);
   dst_len = strlen (dst);
   if (!src_len || !dst_len)
+# if defined RENAME_EXCL
+    return renameatx_np (fd1, src, fd2, dst, uflags);
+# else
     return renameat (fd1, src, fd2, dst);
+# endif
 
   src_slash = src[src_len - 1] == '/';
   dst_slash = dst[dst_len - 1] == '/';
   if (!src_slash && !dst_slash)
+# if defined RENAME_EXCL
+    return renameatx_np (fd1, src, fd2, dst, uflags);
+# else
     return renameat (fd1, src, fd2, dst);
+# endif
 
   /* Presence of a trailing slash requires directory semantics.  If
      the source does not exist, or if the destination cannot be turned
@@ -211,7 +225,11 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
      on Solaris, since all other systems either lack renameat or honor
      trailing slash correctly.  */
 
+# if defined RENAME_EXCL
+  ret_val = renameatx_np (fd1, src_temp, fd2, dst_temp, uflags);
+# else
   ret_val = renameat (fd1, src_temp, fd2, dst_temp);
+# endif
   rename_errno = errno;
   goto out;
  out:



  parent reply	other threads:[~2021-01-02 16:03 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-01 13:14 Issues with posix functions on modern macOS/Xcode Martin Storsjö
2020-12-01 13:50 ` Martin Storsjö
2020-12-01 18:58 ` Bruno Haible
2020-12-02 18:56 ` Bruno Haible
2021-01-02 20:43   ` Bruno Haible
2021-03-21  2:57     ` Bruno Haible
2021-03-21 13:58       ` Bruno Haible
2020-12-02 21:52 ` strsignal on macOS Bruno Haible
2020-12-03 20:59 ` fprintf-posix " Bruno Haible
2020-12-04 23:24 ` utime " Bruno Haible
2021-01-02 16:03 ` Bruno Haible [this message]
2021-01-02 18:06 ` utimens: Fix test failures " Bruno Haible

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2292620.QaEihNl2m5@omega \
    --to=bruno@clisp.org \
    --cc=bug-gnulib@gnu.org \
    --cc=martin@martin.st \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).