Subject: Re: bug#32796: please consider using renameat2 from glibc if available

From: Andreas Henriksson <[email-masked]>
Date: Sat, 6 Oct 2018 20:40:56 +0200

Hi,

On Fri, Sep 21, 2018 at 04:42:37PM -0700, Paul Eggert wrote:
> Johannes Schauer wrote:
> > This problem could be solved by coreutils using the glibc renameat2 function in
> > glibc version 2.28 and newer.
> 
> Yes, that's on my list of things to do. It's not high priority, though, so
> if you want it done faster you can write up and test the code and submit a
> patch (hint, hint).
> 

Probably going to embarras myself here with no prior coreutils (or
gnulib) experience and including an untested patch, but oh well.

I tried to look at this issue and AIUI this is basically a gnulib
issue rather than coreutils. There's even been some relevant changes
done since (the gnulib version included in) coreutils 8.30:
http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commit;h=2522322e5304e7d86c63e607e2bc83c8d8b0a889

Since I have no idea how to bundle a new gnulib version with coreutils
to build a test version (and I don't even have glibc 2.28 yet either),
I haven't been able to test but wouldn't a simple patch like the
attached one do the trick?
(Note: stdio.h is already included so no addition for it needed. The
fallback discussed in [1] should be the same for HAVE_RENAMEAT2 and 
SYS_renameat2 codepaths.)

[1] https://sourceware.org/ml/libc-alpha/2018-07/msg00064.html

I assume if it was this simple you'd have already delt with it, so
I'm probably way too naive here.

Regards,
Andreas Henriksson
>From 32e683687be271ba3589021722b14e54e8b41d08 Mon Sep 17 00:00:00 2001
From: Andreas Henriksson <[email-masked]>
Date: Sat, 6 Oct 2018 20:25:24 +0200
Subject: [PATCH] renameatu: Use renameat2 when available

Use the function call rather than direct syscall when possible.
The renameat2 function is provided since glibc 2.28.
See:
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32796
---
 lib/renameatu.c | 5 ++++-
 m4/renameat.m4  | 1 +
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/renameatu.c b/lib/renameatu.c
index b013ad697..8a32417bf 100644
--- a/lib/renameatu.c
+++ b/lib/renameatu.c
@@ -80,7 +80,10 @@ renameatu (int fd1, char const *src, int fd2, char const *dst,
   int ret_val = -1;
   int err = EINVAL;
 
-#ifdef SYS_renameat2
+#ifdef HAVE_RENAMEAT2
+  ret_val = renameat2(fd1, src, fd2, dst, flags);
+  err = errno;
+#elif defined SYS_renameat2
   ret_val = syscall (SYS_renameat2, fd1, src, fd2, dst, flags);
   err = errno;
 #elif defined RENAME_EXCL
diff --git a/m4/renameat.m4 b/m4/renameat.m4
index 116750785..df6f1fd5a 100644
--- a/m4/renameat.m4
+++ b/m4/renameat.m4
@@ -16,6 +16,7 @@ AC_DEFUN([gl_FUNC_RENAMEAT],
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_CHECK_HEADERS([linux/fs.h])
   AC_CHECK_FUNCS_ONCE([renameat])
+  AC_CHECK_FUNCS_ONCE([renameat2])
   if test $ac_cv_func_renameat = no; then
     HAVE_RENAMEAT=0
   elif test $REPLACE_RENAME = 1; then
-- 
2.19.0