aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2018-07-05 18:59:02 +0200
committerFlorian Weimer <fweimer@redhat.com>2018-07-05 19:00:10 +0200
commitd6da5cb6a8e0e8a9ce92b7d951a254cf325248d7 (patch)
tree4c8f50e0ec6b6780eb1eb4dd2b496f0a1b1411d3
parent1002d708232dda9ebff65f6c1409fa067a01b6e0 (diff)
downloadglibc-d6da5cb6a8e0e8a9ce92b7d951a254cf325248d7.zip
glibc-d6da5cb6a8e0e8a9ce92b7d951a254cf325248d7.tar.gz
glibc-d6da5cb6a8e0e8a9ce92b7d951a254cf325248d7.tar.bz2
Add renameat2 function [BZ #17662]
The implementation falls back to renameat if renameat2 is not available in the kernel (or in the kernel headers) and the flags argument is zero. Without kernel support, a non-zero argument returns EINVAL, not ENOSYS. This mirrors what the kernel does for invalid renameat2 flags.
-rw-r--r--ChangeLog31
-rw-r--r--NEWS9
-rw-r--r--include/stdio.h3
-rw-r--r--libio/stdio.h12
-rw-r--r--manual/filesys.texi1
-rw-r--r--stdio-common/Makefile3
-rw-r--r--stdio-common/Versions3
-rw-r--r--stdio-common/renameat.c5
-rw-r--r--stdio-common/renameat2.c30
-rw-r--r--stdio-common/tst-renameat2.c204
-rw-r--r--sysdeps/mach/hurd/i386/libc.abilist1
-rw-r--r--sysdeps/mach/hurd/renameat.c4
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/alpha/kernel-features.h5
-rw-r--r--sysdeps/unix/sysv/linux/alpha/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/arm/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/hppa/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/i386/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/ia64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h5
-rw-r--r--sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/kernel-features.h5
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/nios2/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/renameat.c4
-rw-r--r--sysdeps/unix/sysv/linux/renameat2.c44
-rw-r--r--sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/sh/kernel-features.h5
-rw-r--r--sysdeps/unix/sysv/linux/sh/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/kernel-features.h5
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist1
45 files changed, 400 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e8308e..2792725 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2018-07-05 Florian Weimer <fweimer@redhat.com>
+
+ [BZ # 17662]
+ * libio/stdio.h [__USE_GNU] (RENAME_NOREPLACE, RENAME_EXCHANGE)
+ (RENAME_WHITEOUT): Define.
+ [__USE_GNU] (renameat2): Declare.
+ * stdio-common/Makefile (routines): Add renameat2.
+ (tests): Add tst-renameat2.
+ * stdio-common/Versions (GLIBC_2_28): Export renameat2.
+ * stdio-common/renameat2.c: New file.
+ * stdio-common/tst-renameat2.c: Likewise.
+ * sysdeps/unix/sysv/linux/renameat2.c: Likewise.
+ * manual/filesys.texi (Temporary Files): Note that renameat2 is
+ undocumented.
+ * sysdeps/unix/sysv/linux/kernel-features.h
+ [__LINUX_KERNEL_VERSION >= 0x030F00] (__ASSUME_RENAMEAT2): Define.
+ * sysdeps/unix/sysv/linux/alpha/kernel-features.h
+ [__LINUX_KERNEL_VERSION < 0x031100] (__ASSUME_RENAMEAT2): Undefine.
+ * sysdeps/unix/sysv/linux/microblaze/kernel-features.h
+ [__LINUX_KERNEL_VERSION < 0x031100] (__ASSUME_RENAMEAT2): Undefine.
+ * sysdeps/unix/sysv/linux/sh/kernel-features.h
+ [__LINUX_KERNEL_VERSION < 0x040800] (__ASSUME_RENAMEAT2): Undefine.
+ * sysdeps/unix/sysv/linux/sparc/kernel-features.h
+ [__LINUX_KERNEL_VERSION < 0x031000] (__ASSUME_RENAMEAT2): Undefine.
+ * include/stdio.h (__renameat): Add alias for renameat.
+ * stdio-common/renameat.c (__renameat): Rename from renameat.
+ Add hidden definition and alias.
+ * sysdeps/unix/sysv/linux/renameat.c: Likewise.
+ * sysdeps/mach/hurd/renameat.c: Likewise.
+ * sysdeps/**/libc*.abilist: Add renameat2.
+
2018-07-04 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* posix/bug-regex33.c: Fix build after regex sync.
diff --git a/NEWS b/NEWS
index b1ce067..5d25391 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,15 @@ Major new features:
* Building and running on GNU/Hurd systems now works without out-of-tree
patches.
+* The renameat2 function has been added, a variant of the renameat function
+ which has a flags argument. If the flags are zero, the renameat2 function
+ acts like renameat. If the flag is not zero and there is no kernel
+ support for renameat2, the function will fail with an errno value of
+ EINVAL. This is different from the existing gnulib function renameatu,
+ which performs a plain rename operation in case of a RENAME_NOREPLACE
+ flags and a non-existing destination (and therefore has a race condition
+ that can clobber the destination inadvertently).
+
* IDN domain names in getaddrinfo and getnameinfo now use the system libidn2
library if installed. libidn2 version 2.0.5 or later is recommended. If
libidn2 is not available, internationalized domain names are not encoded
diff --git a/include/stdio.h b/include/stdio.h
index f140813..3ba0edc 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -237,5 +237,8 @@ __putc_unlocked (int __c, FILE *__stream)
}
# endif
+extern __typeof (renameat) __renameat;
+libc_hidden_proto (__renameat)
+
# endif /* not _ISOMAC */
#endif /* stdio.h */
diff --git a/libio/stdio.h b/libio/stdio.h
index 731f8e5..739e086 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -153,6 +153,18 @@ extern int renameat (int __oldfd, const char *__old, int __newfd,
const char *__new) __THROW;
#endif
+#ifdef __USE_GNU
+/* Flags for renameat2. */
+# define RENAME_NOREPLACE (1 << 0)
+# define RENAME_EXCHANGE (1 << 1)
+# define RENAME_WHITEOUT (1 << 2)
+
+/* Rename file OLD relative to OLDFD to NEW relative to NEWFD, with
+ additional flags. */
+extern int renameat2 (int __oldfd, const char *__old, int __newfd,
+ const char *__new, unsigned int __flags) __THROW;
+#endif
+
/* Create a temporary file and open it read/write.
This function is a possible cancellation point and therefore not
diff --git a/manual/filesys.texi b/manual/filesys.texi
index cc70a6b..db2f104 100644
--- a/manual/filesys.texi
+++ b/manual/filesys.texi
@@ -3552,6 +3552,7 @@ The @code{mkdtemp} function comes from OpenBSD.
@c open_by_handle_at
@c readlinkat
@c renameat
+@c renameat2
@c scandirat
@c symlinkat
@c unlinkat
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 96bd7c3..a10f12a 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -35,7 +35,7 @@ routines := \
perror psignal \
tmpfile tmpfile64 tmpnam tmpnam_r tempnam tempname \
getline getw putw \
- remove rename renameat \
+ remove rename renameat renameat2 \
flockfile ftrylockfile funlockfile \
isoc99_scanf isoc99_vscanf isoc99_fscanf isoc99_vfscanf isoc99_sscanf \
isoc99_vsscanf \
@@ -62,6 +62,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
tst-vfprintf-user-type \
tst-vfprintf-mbs-prec \
tst-scanf-round \
+ tst-renameat2 \
test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble
diff --git a/stdio-common/Versions b/stdio-common/Versions
index 5016f69..b821757 100644
--- a/stdio-common/Versions
+++ b/stdio-common/Versions
@@ -57,6 +57,9 @@ libc {
psiginfo;
register_printf_modifier; register_printf_type; register_printf_specifier;
}
+ GLIBC_2.28 {
+ renameat2;
+ }
GLIBC_PRIVATE {
# global variables
_itoa_lower_digits;
diff --git a/stdio-common/renameat.c b/stdio-common/renameat.c
index 2180b87..98c8f1d 100644
--- a/stdio-common/renameat.c
+++ b/stdio-common/renameat.c
@@ -22,7 +22,7 @@
/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */
int
-renameat (int oldfd, const char *old, int newfd, const char *new)
+__renameat (int oldfd, const char *old, int newfd, const char *new)
{
if ((oldfd < 0 && oldfd != AT_FDCWD) || (newfd < 0 && newfd != AT_FDCWD))
{
@@ -40,5 +40,6 @@ renameat (int oldfd, const char *old, int newfd, const char *new)
return -1;
}
-
+libc_hidden_def (__renameat)
+weak_alias (__renameat, renameat)
stub_warning (renameat)
diff --git a/stdio-common/renameat2.c b/stdio-common/renameat2.c
new file mode 100644
index 0000000..c2cedcd
--- /dev/null
+++ b/stdio-common/renameat2.c
@@ -0,0 +1,30 @@
+/* Generic implementation of the renameat function.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+
+int
+renameat2 (int oldfd, const char *old, int newfd, const char *new,
+ unsigned int flags)
+{
+ if (flags == 0)
+ return __renameat (oldfd, old, newfd, new);
+ __set_errno (EINVAL);
+ return -1;
+}
diff --git a/stdio-common/tst-renameat2.c b/stdio-common/tst-renameat2.c
new file mode 100644
index 0000000..958b091
--- /dev/null
+++ b/stdio-common/tst-renameat2.c
@@ -0,0 +1,204 @@
+/* Linux implementation for renameat2 function.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+/* Directory with the temporary files. */
+static char *directory;
+static int directory_fd;
+
+/* Paths within that directory. */
+static char *old_path; /* File is called "old". */
+static char *new_path; /* File is called "new". */
+
+/* Subdirectory within the directory above. */
+static char *subdirectory;
+int subdirectory_fd;
+
+/* And a pathname in that directory (called "file"). */
+static char *subdir_path;
+
+static void
+prepare (int argc, char **argv)
+{
+ directory = support_create_temp_directory ("tst-renameat2-");
+ directory_fd = xopen (directory, O_RDONLY | O_DIRECTORY, 0);
+ old_path = xasprintf ("%s/old", directory);
+ add_temp_file (old_path);
+ new_path = xasprintf ("%s/new", directory);
+ add_temp_file (new_path);
+ subdirectory = xasprintf ("%s/subdir", directory);
+ xmkdir (subdirectory, 0777);
+ add_temp_file (subdirectory);
+ subdirectory_fd = xopen (subdirectory, O_RDONLY | O_DIRECTORY, 0);
+ subdir_path = xasprintf ("%s/file", subdirectory);
+ add_temp_file (subdir_path);
+}
+
+/* Delete all files, preparing a clean slate for the next test. */
+static void
+delete_all_files (void)
+{
+ char *files[] = { old_path, new_path, subdir_path };
+ for (size_t i = 0; i < array_length (files); ++i)
+ if (unlink (files[i]) != 0 && errno != ENOENT)
+ FAIL_EXIT1 ("unlink (\"%s\"): %m", files[i]);
+}
+
+/* Return true if PATH exists in the file system. */
+static bool
+file_exists (const char *path)
+{
+ return access (path, F_OK) == 0;
+}
+
+/* Check that PATH exists and has size EXPECTED_SIZE. */
+static void
+check_size (const char *path, off64_t expected_size)
+{
+ struct stat64 st;
+ xstat (path, &st);
+ if (st.st_size != expected_size)
+ FAIL_EXIT1 ("file \"%s\": expected size %lld, actual size %lld",
+ path, (unsigned long long int) expected_size,
+ (unsigned long long int) st.st_size);
+}
+
+/* Rename tests where the target does not exist. */
+static void
+rename_without_existing_target (unsigned int flags)
+{
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, flags), 0);
+ TEST_VERIFY (!file_exists (old_path));
+ TEST_VERIFY (file_exists (new_path));
+
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ TEST_COMPARE (renameat2 (directory_fd, "old", AT_FDCWD, new_path, flags), 0);
+ TEST_VERIFY (!file_exists (old_path));
+ TEST_VERIFY (file_exists (new_path));
+
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ TEST_COMPARE (renameat2 (directory_fd, "old", subdirectory_fd, "file", 0),
+ 0);
+ TEST_VERIFY (!file_exists (old_path));
+ TEST_VERIFY (file_exists (subdir_path));
+}
+
+static int
+do_test (void)
+{
+ /* Tests with zero flags argument. These are expected to succeed
+ because this renameat2 variant can be implemented with
+ renameat. */
+ rename_without_existing_target (0);
+
+ /* renameat2 without flags replaces an existing destination. */
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (new_path, "1234");
+ TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, 0), 0);
+ TEST_VERIFY (!file_exists (old_path));
+ check_size (new_path, 3);
+
+ /* Now we need to check for kernel support of renameat2 with
+ flags. */
+ delete_all_files ();
+ support_write_file_string (old_path, "");
+ if (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path, RENAME_NOREPLACE)
+ != 0)
+ {
+ if (errno == EINVAL)
+ puts ("warning: no support for renameat2 with flags");
+ else
+ FAIL_EXIT1 ("renameat2 probe failed: %m");
+ }
+ else
+ {
+ /* We have full renameat2 support. */
+ rename_without_existing_target (RENAME_NOREPLACE);
+
+ /* Now test RENAME_NOREPLACE with an existing target. */
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (new_path, "1234");
+ TEST_COMPARE (renameat2 (AT_FDCWD, old_path, AT_FDCWD, new_path,
+ RENAME_NOREPLACE), -1);
+ TEST_COMPARE (errno, EEXIST);
+ check_size (old_path, 3);
+ check_size (new_path, 4);
+
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (new_path, "1234");
+ TEST_COMPARE (renameat2 (directory_fd, "old", AT_FDCWD, new_path,
+ RENAME_NOREPLACE), -1);
+ TEST_COMPARE (errno, EEXIST);
+ check_size (old_path, 3);
+ check_size (new_path, 4);
+
+ delete_all_files ();
+ support_write_file_string (old_path, "123");
+ support_write_file_string (subdir_path, "1234");
+ TEST_COMPARE (renameat2 (directory_fd, "old", subdirectory_fd, "file",
+ RENAME_NOREPLACE), -1);
+ TEST_COMPARE (errno, EEXIST);
+ check_size (old_path, 3);
+ check_size (subdir_path, 4);
+
+ /* The flag combination of RENAME_NOREPLACE and RENAME_EXCHANGE
+ is invalid. */
+ TEST_COMPARE (renameat2 (directory_fd, "ignored",
+ subdirectory_fd, "ignored",
+ RENAME_NOREPLACE | RENAME_EXCHANGE), -1);
+ TEST_COMPARE (errno, EINVAL);
+ }
+
+ /* Create all the pathnames to avoid warnings from the test
+ harness. */
+ support_write_file_string (old_path, "");
+ support_write_file_string (new_path, "");
+ support_write_file_string (subdir_path, "");
+
+ free (directory);
+ free (subdirectory);
+ free (old_path);
+ free (new_path);
+ free (subdir_path);
+
+ xclose (directory_fd);
+ xclose (subdirectory_fd);
+
+ return 0;
+}
+
+#define PREPARE prepare
+#include <support/test-driver.c>
diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
index 57091fc..a9089d9 100644
--- a/sysdeps/mach/hurd/i386/libc.abilist
+++ b/sysdeps/mach/hurd/i386/libc.abilist
@@ -2034,6 +2034,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/mach/hurd/renameat.c b/sysdeps/mach/hurd/renameat.c
index 4360960..7985763 100644
--- a/sysdeps/mach/hurd/renameat.c
+++ b/sysdeps/mach/hurd/renameat.c
@@ -22,7 +22,7 @@
/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD. */
int
-renameat (int oldfd, const char *old, int newfd, const char *new)
+__renameat (int oldfd, const char *old, int newfd, const char *new)
{
error_t err;
file_t olddir, newdir;
@@ -45,3 +45,5 @@ renameat (int oldfd, const char *old, int newfd, const char *new)
return __hurd_fail (err);
return 0;
}
+libc_hidden_def (__renameat)
+weak_alias (__renameat, renameat)
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 884d0df..7a272a1 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2132,3 +2132,4 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
diff --git a/sysdeps/unix/sysv/linux/alpha/kernel-features.h b/sysdeps/unix/sysv/linux/alpha/kernel-features.h
index c2d4a9f..5781cff 100644
--- a/sysdeps/unix/sysv/linux/alpha/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/alpha/kernel-features.h
@@ -35,6 +35,11 @@
#define __ASSUME_RECV_SYSCALL 1
#define __ASSUME_SEND_SYSCALL 1
+/* Support for the renameat2 syscall was added in 3.17. */
+#if __LINUX_KERNEL_VERSION < 0x031100
+# undef __ASSUME_RENAMEAT2
+#endif
+
/* Support for the execveat syscall was added in 4.2. */
#if __LINUX_KERNEL_VERSION < 0x040200
# undef __ASSUME_EXECVEAT
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 28d54b9..23fec55 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2027,6 +2027,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index dfde3bd..b203160 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -117,6 +117,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 06b00f7..64809ca 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1874,6 +1874,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 1c1cc00..4a87f62 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2039,6 +2039,7 @@ GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index f6e17a0..6bdd0d0 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1908,6 +1908,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index b90ea30..86fc665 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -97,6 +97,11 @@
implementation based on p{read,write}v and returning an error for
non supported flags. */
+/* Support for the renameat2 system call was added in kernel 3.15. */
+#if __LINUX_KERNEL_VERSION >= 0x030F00
+# define __ASSUME_RENAMEAT2
+#endif
+
/* Support for the execveat syscall was added in 3.19. */
#if __LINUX_KERNEL_VERSION >= 0x031300
# define __ASSUME_EXECVEAT 1
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index ee054a6..3226f91 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -118,6 +118,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0x98
GLIBC_2.4 _IO_2_1_stdin_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 227a058..b1074ee 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1983,6 +1983,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/kernel-features.h b/sysdeps/unix/sysv/linux/microblaze/kernel-features.h
index b13b863..7db3d05 100644
--- a/sysdeps/unix/sysv/linux/microblaze/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/microblaze/kernel-features.h
@@ -48,6 +48,11 @@
# undef __ASSUME_SENDMMSG_SYSCALL
#endif
+/* Support for the renameat2 syscall was added in 3.17. */
+#if __LINUX_KERNEL_VERSION < 0x031100
+# undef __ASSUME_RENAMEAT2
+#endif
+
/* Support for the execveat syscall was added in 4.0. */
#if __LINUX_KERNEL_VERSION < 0x040000
# undef __ASSUME_EXECVEAT
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 18781b3..b52fc7d 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2124,3 +2124,4 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 2d86989..718c742 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1961,6 +1961,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index b8b113e..9b218a9 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1959,6 +1959,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 6a3cd13..5a90ab8 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1967,6 +1967,7 @@ GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 596ec05..3005fc9 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1962,6 +1962,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 8da18ee..a87fbbe 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2165,3 +2165,4 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 555751e..d56f776 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1987,6 +1987,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 80324e4..2b5337a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1991,6 +1991,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 97b1d35..d0dfde3 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2222,3 +2222,4 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 15be314..d505ae0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -117,6 +117,7 @@ GLIBC_2.27 wcstof32x_l F
GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 _Exit F
GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
GLIBC_2.3 _IO_2_1_stdin_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/renameat.c b/sysdeps/unix/sysv/linux/renameat.c
index 034432b..f85c5ae 100644
--- a/sysdeps/unix/sysv/linux/renameat.c
+++ b/sysdeps/unix/sysv/linux/renameat.c
@@ -22,7 +22,7 @@
#include <errno.h>
int
-renameat (int oldfd, const char *old, int newfd, const char *new)
+__renameat (int oldfd, const char *old, int newfd, const char *new)
{
#ifdef __NR_renameat
return INLINE_SYSCALL_CALL (renameat, oldfd, old, newfd, new);
@@ -30,3 +30,5 @@ renameat (int oldfd, const char *old, int newfd, const char *new)
return INLINE_SYSCALL_CALL (renameat2, oldfd, old, newfd, new, 0);
#endif
}
+libc_hidden_def (__renameat)
+weak_alias (__renameat, renameat)
diff --git a/sysdeps/unix/sysv/linux/renameat2.c b/sysdeps/unix/sysv/linux/renameat2.c
new file mode 100644
index 0000000..919bb2a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/renameat2.c
@@ -0,0 +1,44 @@
+/* Linux implementation for renameat2 function.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <sysdep.h>
+
+int
+renameat2 (int oldfd, const char *old, int newfd, const char *new,
+ unsigned int flags)
+{
+#if !defined (__NR_renameat) || defined (__ASSUME_RENAMEAT2)
+ return INLINE_SYSCALL_CALL (renameat2, oldfd, old, newfd, new, flags);
+#else
+ if (flags == 0)
+ return __renameat (oldfd, old, newfd, new);
+# ifdef __NR_renameat2
+ /* For non-zero flags, try the renameat2 system call. */
+ int ret = INLINE_SYSCALL_CALL (renameat2, oldfd, old, newfd, new, flags);
+ if (ret != -1 || errno != ENOSYS)
+ /* Preserve non-error/non-ENOSYS return values. */
+ return ret;
+# endif
+ /* No kernel (header) support for renameat2. All flags are
+ unknown. */
+ __set_errno (EINVAL);
+ return -1;
+#endif
+}
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 436b992..33f751a 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2094,3 +2094,4 @@ GLIBC_2.27 xencrypt F
GLIBC_2.27 xprt_register F
GLIBC_2.27 xprt_unregister F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index f66715f..c4ec93f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1996,6 +1996,7 @@ GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index bd62428..2a6a0ab 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1901,6 +1901,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/kernel-features.h b/sysdeps/unix/sysv/linux/sh/kernel-features.h
index b82d032..05b7dcd 100644
--- a/sysdeps/unix/sysv/linux/sh/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/sh/kernel-features.h
@@ -51,4 +51,9 @@
/* sh only supports ipc syscall. */
#undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
+/* Support for the renameat2 syscall was added in 4.8. */
+#if __LINUX_KERNEL_VERSION < 0x040800
+# undef __ASSUME_RENAMEAT2
+#endif
+
#endif
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index f2f070f..8de0d17 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1878,6 +1878,7 @@ GLIBC_2.27 wcstof64 F
GLIBC_2.27 wcstof64_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/kernel-features.h b/sysdeps/unix/sysv/linux/sparc/kernel-features.h
index 64d7140..91990a7 100644
--- a/sysdeps/unix/sysv/linux/sparc/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/sparc/kernel-features.h
@@ -41,6 +41,11 @@
/* sparc only supports ipc syscall. */
#undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS
+/* Support for the renameat2 syscall was added in 3.16. */
+#if __LINUX_KERNEL_VERSION < 0x031000
+# undef __ASSUME_RENAMEAT2
+#endif
+
/* SPARC kernel Kconfig does not define CONFIG_CLONE_BACKWARDS, however it
has the same ABI as if it did, implemented by sparc-specific code
(sparc_do_fork).
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 265087f..9858460 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1990,6 +1990,7 @@ GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 16a6981..a22b8fb 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1931,6 +1931,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index fa8c198..d5d71cc 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1889,6 +1889,7 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
GLIBC_2.3 __ctype_toupper_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 2536971..e6ad424 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2140,3 +2140,4 @@ GLIBC_2.27 wcstof64_l F
GLIBC_2.27 wcstof64x F
GLIBC_2.27 wcstof64x_l F
GLIBC_2.28 fcntl64 F
+GLIBC_2.28 renameat2 F