From: Bruno Haible Date: Sat, 2 Jan 2021 15:54:21 +0000 (+0100) Subject: renameatu: Fix test failures on macOS. X-Git-Tag: v1.0~3234 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=b4ef486ff5110e4e0714ab77166b5884922be071;p=gnulib.git renameatu: Fix test failures on macOS. Reported by Martin Storsjö in . * 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/ChangeLog b/ChangeLog index 4dd088d871..6d95f49900 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2021-01-02 Bruno Haible + + renameatu: Fix test failures on macOS. + Reported by Martin Storsjö in + . + * 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. + 2021-01-02 Bruno Haible getgroups test: Avoid warning with glibc >= 2.32 and gcc >= 10. diff --git a/lib/renameatu.c b/lib/renameatu.c index 974d23455c..c493a38dc1 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: