changeset 39738:c05640d27ca2

renameatu: rename from renameat2 It's looking like Glibc will add a renameat2 function that is incompatible with Gnulib renameat2; see: https://sourceware.org/ml/libc-alpha/2018-07/msg00064.html To help avoid future confusion, rename renameat2 to something else. Use the name 'renameatu', as the Gnulib function is close to the Glibc function. Perhaps someday there will also be a renameat2 Gnulib module, which mimicks the future glibc renameat2, but that can wait as nobody seems to need such a module now. * NEWS: Mention this. * lib/renameatu.c: Rename from lib/renameat2.c. * lib/renameatu.h: Rename from lib/renameat2.h. * modules/renameat2: Rename from modules/renameatu. * modules/renameat2-tests: Rename from modules/renameat2-tests. All uses of "renameat2" in identifiers or file name changed to "renameatu", except for two instances in lib/renameatu.c that deal with the Linux kernel's renameat2 syscall.
author Paul Eggert <eggert@cs.ucla.edu>
date Thu, 05 Jul 2018 09:22:09 -0700
parents bf73bd094dbd
children 52530896babd
files ChangeLog MODULES.html.sh NEWS lib/backupfile.c lib/renameat.c lib/renameat2.c lib/renameat2.h lib/renameatu.c lib/renameatu.h modules/backup-rename modules/backupfile modules/renameat modules/renameat2 modules/renameat2-tests modules/renameatu modules/renameatu-tests tests/test-renameat2.c tests/test-renameatu.c
diffstat 18 files changed, 564 insertions(+), 538 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jul 04 20:42:07 2018 -0700
+++ b/ChangeLog	Thu Jul 05 09:22:09 2018 -0700
@@ -1,3 +1,24 @@
+2018-07-05  Paul Eggert  <eggert@cs.ucla.edu>
+
+	renameatu: rename from renameat2
+	It's looking like Glibc will add a renameat2 function
+	that is incompatible with Gnulib renameat2; see:
+	https://sourceware.org/ml/libc-alpha/2018-07/msg00064.html
+	To help avoid future confusion, rename renameat2 to something else.
+	Use the name 'renameatu', as the Gnulib function is close to the
+	Glibc function.  Perhaps someday there will also be a renameat2
+	Gnulib module, which mimicks the future glibc renameat2, but that
+	can wait as nobody seems to need such a module now.
+	* NEWS: Mention this.
+	* lib/renameatu.c: Rename from lib/renameat2.c.
+	* lib/renameatu.h: Rename from lib/renameat2.h.
+	* modules/renameat2: Rename from modules/renameatu.
+	* modules/renameat2-tests: Rename from modules/renameat2-tests.
+	All uses of "renameat2" in identifiers or file name
+	changed to "renameatu", except for two instances in
+	lib/renameatu.c that deal with the Linux kernel's
+	renameat2 syscall.
+
 2018-07-04  Paul Eggert  <eggert@cs.ucla.edu>
 
 	gnulib-tool: minor tweaks for --gnu-make
--- a/MODULES.html.sh	Wed Jul 04 20:42:07 2018 -0700
+++ b/MODULES.html.sh	Thu Jul 05 09:22:09 2018 -0700
@@ -2689,7 +2689,7 @@
   func_module qset-acl
   func_module read-file
   func_module readlinkat
-  func_module renameat2
+  func_module renameatu
   func_module same
   func_module save-cwd
   func_module savedir
--- a/NEWS	Wed Jul 04 20:42:07 2018 -0700
+++ b/NEWS	Thu Jul 05 09:22:09 2018 -0700
@@ -42,6 +42,10 @@
 
 Date        Modules         Changes
 
+2018-07-05  renameat2       This module is renamed to 'renameatu' and all
+                            its include files and functions are renamed
+                            accordingly.
+
 2017-12-30  chdir-safer     This module is removed.  It was deprecated
                             on 2006-07-17.
 
--- a/lib/backupfile.c	Wed Jul 04 20:42:07 2018 -0700
+++ b/lib/backupfile.c	Thu Jul 05 09:22:09 2018 -0700
@@ -23,7 +23,7 @@
 #include "backup-internal.h"
 
 #include "dirname.h"
-#include "renameat2.h"
+#include "renameatu.h"
 #include "xalloc-oversized.h"
 
 #include <fcntl.h>
@@ -353,7 +353,7 @@
           base_offset = 0;
         }
       unsigned flags = backup_type == simple_backups ? 0 : RENAME_NOREPLACE;
-      if (renameat2 (AT_FDCWD, file, sdir, s + base_offset, flags) == 0)
+      if (renameatu (AT_FDCWD, file, sdir, s + base_offset, flags) == 0)
         break;
       int e = errno;
       if (e != EEXIST)
--- a/lib/renameat.c	Wed Jul 04 20:42:07 2018 -0700
+++ b/lib/renameat.c	Thu Jul 05 09:22:09 2018 -0700
@@ -16,10 +16,10 @@
 
 #include <config.h>
 #include <stdio.h>
-#include "renameat2.h"
+#include "renameatu.h"
 
 int
 renameat (int fd1, char const *src, int fd2, char const *dst)
 {
-  return renameat2 (fd1, src, fd2, dst, 0);
+  return renameatu (fd1, src, fd2, dst, 0);
 }
--- a/lib/renameat2.c	Wed Jul 04 20:42:07 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,227 +0,0 @@
-/* Rename a file relative to open directories.
-   Copyright (C) 2009-2018 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* written by Eric Blake and Paul Eggert */
-
-#include <config.h>
-
-#include "renameat2.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#ifdef __linux__
-# include <sys/syscall.h>
-#endif
-
-static int
-errno_fail (int e)
-{
-  errno = e;
-  return -1;
-}
-
-#if HAVE_RENAMEAT
-
-# include <stdbool.h>
-# include <stdlib.h>
-# include <string.h>
-
-# include "dirname.h"
-# include "openat.h"
-
-#else
-# include "openat-priv.h"
-
-static int
-rename_noreplace (char const *src, char const *dst)
-{
-  /* This has a race between the call to lstat and the call to rename.  */
-  struct stat st;
-  return (lstat (dst, &st) == 0 || errno == EOVERFLOW ? errno_fail (EEXIST)
-          : errno == ENOENT ? rename (src, dst)
-          : -1);
-}
-#endif
-
-#undef renameat
-
-/* Rename FILE1, in the directory open on descriptor FD1, to FILE2, in
-   the directory open on descriptor FD2.  If possible, do it without
-   changing the working directory.  Otherwise, resort to using
-   save_cwd/fchdir, then rename/restore_cwd.  If either the save_cwd or
-   the restore_cwd fails, then give a diagnostic and exit nonzero.
-
-   Obey FLAGS when doing the renaming.  If FLAGS is zero, this
-   function is equivalent to renameat (FD1, SRC, FD2, DST).  */
-
-int
-renameat2 (int fd1, char const *src, int fd2, char const *dst,
-           unsigned int flags)
-{
-  int ret_val = -1;
-  int err = EINVAL;
-
-#ifdef 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)))
-    return ret_val;
-
-#if HAVE_RENAMEAT
-  {
-  size_t src_len;
-  size_t dst_len;
-  char *src_temp = (char *) src;
-  char *dst_temp = (char *) dst;
-  bool src_slash;
-  bool dst_slash;
-  int rename_errno = ENOTDIR;
-  struct stat src_st;
-  struct stat dst_st;
-  bool dst_found_nonexistent = false;
-
-  if (flags != 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;
-        }
-    }
-
-  /* Let strace see any ENOENT failure.  */
-  src_len = strlen (src);
-  dst_len = strlen (dst);
-  if (!src_len || !dst_len)
-    return renameat (fd1, src, fd2, dst);
-
-  src_slash = src[src_len - 1] == '/';
-  dst_slash = dst[dst_len - 1] == '/';
-  if (!src_slash && !dst_slash)
-    return renameat (fd1, src, fd2, dst);
-
-  /* Presence of a trailing slash requires directory semantics.  If
-     the source does not exist, or if the destination cannot be turned
-     into a directory, give up now.  Otherwise, strip trailing slashes
-     before calling rename.  */
-  if (lstatat (fd1, src, &src_st))
-    return -1;
-  if (dst_found_nonexistent)
-    {
-      if (!S_ISDIR (src_st.st_mode))
-        return errno_fail (ENOENT);
-    }
-  else if (lstatat (fd2, dst, &dst_st))
-    {
-      if (errno != ENOENT || !S_ISDIR (src_st.st_mode))
-        return -1;
-    }
-  else if (!S_ISDIR (dst_st.st_mode))
-    return errno_fail (ENOTDIR);
-  else if (!S_ISDIR (src_st.st_mode))
-    return errno_fail (EISDIR);
-
-# if RENAME_TRAILING_SLASH_SOURCE_BUG
-  /* See the lengthy comment in rename.c why Solaris 9 is forced to
-     GNU behavior, while Solaris 10 is left with POSIX behavior,
-     regarding symlinks with trailing slash.  */
-  ret_val = -1;
-  if (src_slash)
-    {
-      src_temp = strdup (src);
-      if (!src_temp)
-        {
-          /* Rather than rely on strdup-posix, we set errno ourselves.  */
-          rename_errno = ENOMEM;
-          goto out;
-        }
-      strip_trailing_slashes (src_temp);
-      if (lstatat (fd1, src_temp, &src_st))
-        {
-          rename_errno = errno;
-          goto out;
-        }
-      if (S_ISLNK (src_st.st_mode))
-        goto out;
-    }
-  if (dst_slash)
-    {
-      dst_temp = strdup (dst);
-      if (!dst_temp)
-        {
-          rename_errno = ENOMEM;
-          goto out;
-        }
-      strip_trailing_slashes (dst_temp);
-      if (lstatat (fd2, dst_temp, &dst_st))
-        {
-          if (errno != ENOENT)
-            {
-              rename_errno = errno;
-              goto out;
-            }
-        }
-      else if (S_ISLNK (dst_st.st_mode))
-        goto out;
-    }
-# endif /* RENAME_TRAILING_SLASH_SOURCE_BUG */
-
-  /* renameat does not honor trailing / on Solaris 10.  Solve it in a
-     similar manner to rename.  No need to worry about bugs not present
-     on Solaris, since all other systems either lack renameat or honor
-     trailing slash correctly.  */
-
-  ret_val = renameat (fd1, src_temp, fd2, dst_temp);
-  rename_errno = errno;
-  goto out;
- out:
-  if (src_temp != src)
-    free (src_temp);
-  if (dst_temp != dst)
-    free (dst_temp);
-  errno = rename_errno;
-  return ret_val;
-  }
-#else /* !HAVE_RENAMEAT */
-
-  /* RENAME_NOREPLACE is the only flag currently supported.  */
-  if (flags & ~RENAME_NOREPLACE)
-    return errno_fail (ENOTSUP);
-  return at_func2 (fd1, src, fd2, dst, flags ? rename_noreplace : rename);
-
-#endif /* !HAVE_RENAMEAT */
-}
--- a/lib/renameat2.h	Wed Jul 04 20:42:07 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/* Rename a file relative to open directories.
-   Copyright 2017-2018 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* written by Paul Eggert */
-
-/* Get RENAME_* macros from linux/fs.h if present, otherwise supply
-   the traditional Linux values.  */
-#if HAVE_LINUX_FS_H
-# include <linux/fs.h>
-#endif
-#ifndef RENAME_NOREPLACE
-# define RENAME_NOREPLACE  (1 << 0)
-# define RENAME_EXCHANGE   (1 << 1)
-# define RENAME_WHITEOUT   (1 << 2)
-#endif
-
-extern int renameat2 (int, char const *, int, char const *, unsigned int);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/renameatu.c	Thu Jul 05 09:22:09 2018 -0700
@@ -0,0 +1,230 @@
+/* Rename a file relative to open directories.
+   Copyright (C) 2009-2018 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* written by Eric Blake and Paul Eggert */
+
+#include <config.h>
+
+#include "renameatu.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef __linux__
+# include <sys/syscall.h>
+#endif
+
+static int
+errno_fail (int e)
+{
+  errno = e;
+  return -1;
+}
+
+#if HAVE_RENAMEAT
+
+# include <stdbool.h>
+# include <stdlib.h>
+# include <string.h>
+
+# include "dirname.h"
+# include "openat.h"
+
+#else
+# include "openat-priv.h"
+
+static int
+rename_noreplace (char const *src, char const *dst)
+{
+  /* This has a race between the call to lstat and the call to rename.  */
+  struct stat st;
+  return (lstat (dst, &st) == 0 || errno == EOVERFLOW ? errno_fail (EEXIST)
+          : errno == ENOENT ? rename (src, dst)
+          : -1);
+}
+#endif
+
+#undef renameat
+
+/* Rename FILE1, in the directory open on descriptor FD1, to FILE2, in
+   the directory open on descriptor FD2.  If possible, do it without
+   changing the working directory.  Otherwise, resort to using
+   save_cwd/fchdir, then rename/restore_cwd.  If either the save_cwd or
+   the restore_cwd fails, then give a diagnostic and exit nonzero.
+
+   Obey FLAGS when doing the renaming.  If FLAGS is zero, this
+   function is equivalent to renameat (FD1, SRC, FD2, DST).
+   Otherwise, attempt to implement FLAGS even if the implementation is
+   not atomic; this differs from the GNU/Linux native renameat2,
+   which fails if it cannot guarantee atomicity.  */
+
+int
+renameatu (int fd1, char const *src, int fd2, char const *dst,
+           unsigned int flags)
+{
+  int ret_val = -1;
+  int err = EINVAL;
+
+#ifdef 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)))
+    return ret_val;
+
+#if HAVE_RENAMEAT
+  {
+  size_t src_len;
+  size_t dst_len;
+  char *src_temp = (char *) src;
+  char *dst_temp = (char *) dst;
+  bool src_slash;
+  bool dst_slash;
+  int rename_errno = ENOTDIR;
+  struct stat src_st;
+  struct stat dst_st;
+  bool dst_found_nonexistent = false;
+
+  if (flags != 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;
+        }
+    }
+
+  /* Let strace see any ENOENT failure.  */
+  src_len = strlen (src);
+  dst_len = strlen (dst);
+  if (!src_len || !dst_len)
+    return renameat (fd1, src, fd2, dst);
+
+  src_slash = src[src_len - 1] == '/';
+  dst_slash = dst[dst_len - 1] == '/';
+  if (!src_slash && !dst_slash)
+    return renameat (fd1, src, fd2, dst);
+
+  /* Presence of a trailing slash requires directory semantics.  If
+     the source does not exist, or if the destination cannot be turned
+     into a directory, give up now.  Otherwise, strip trailing slashes
+     before calling rename.  */
+  if (lstatat (fd1, src, &src_st))
+    return -1;
+  if (dst_found_nonexistent)
+    {
+      if (!S_ISDIR (src_st.st_mode))
+        return errno_fail (ENOENT);
+    }
+  else if (lstatat (fd2, dst, &dst_st))
+    {
+      if (errno != ENOENT || !S_ISDIR (src_st.st_mode))
+        return -1;
+    }
+  else if (!S_ISDIR (dst_st.st_mode))
+    return errno_fail (ENOTDIR);
+  else if (!S_ISDIR (src_st.st_mode))
+    return errno_fail (EISDIR);
+
+# if RENAME_TRAILING_SLASH_SOURCE_BUG
+  /* See the lengthy comment in rename.c why Solaris 9 is forced to
+     GNU behavior, while Solaris 10 is left with POSIX behavior,
+     regarding symlinks with trailing slash.  */
+  ret_val = -1;
+  if (src_slash)
+    {
+      src_temp = strdup (src);
+      if (!src_temp)
+        {
+          /* Rather than rely on strdup-posix, we set errno ourselves.  */
+          rename_errno = ENOMEM;
+          goto out;
+        }
+      strip_trailing_slashes (src_temp);
+      if (lstatat (fd1, src_temp, &src_st))
+        {
+          rename_errno = errno;
+          goto out;
+        }
+      if (S_ISLNK (src_st.st_mode))
+        goto out;
+    }
+  if (dst_slash)
+    {
+      dst_temp = strdup (dst);
+      if (!dst_temp)
+        {
+          rename_errno = ENOMEM;
+          goto out;
+        }
+      strip_trailing_slashes (dst_temp);
+      if (lstatat (fd2, dst_temp, &dst_st))
+        {
+          if (errno != ENOENT)
+            {
+              rename_errno = errno;
+              goto out;
+            }
+        }
+      else if (S_ISLNK (dst_st.st_mode))
+        goto out;
+    }
+# endif /* RENAME_TRAILING_SLASH_SOURCE_BUG */
+
+  /* renameat does not honor trailing / on Solaris 10.  Solve it in a
+     similar manner to rename.  No need to worry about bugs not present
+     on Solaris, since all other systems either lack renameat or honor
+     trailing slash correctly.  */
+
+  ret_val = renameat (fd1, src_temp, fd2, dst_temp);
+  rename_errno = errno;
+  goto out;
+ out:
+  if (src_temp != src)
+    free (src_temp);
+  if (dst_temp != dst)
+    free (dst_temp);
+  errno = rename_errno;
+  return ret_val;
+  }
+#else /* !HAVE_RENAMEAT */
+
+  /* RENAME_NOREPLACE is the only flag currently supported.  */
+  if (flags & ~RENAME_NOREPLACE)
+    return errno_fail (ENOTSUP);
+  return at_func2 (fd1, src, fd2, dst, flags ? rename_noreplace : rename);
+
+#endif /* !HAVE_RENAMEAT */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/renameatu.h	Thu Jul 05 09:22:09 2018 -0700
@@ -0,0 +1,28 @@
+/* Rename a file relative to open directories.
+   Copyright 2017-2018 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* written by Paul Eggert */
+
+/* Get RENAME_* macros from <stdio.h> if present, otherwise supply
+   the traditional Linux values.  */
+#include <stdio.h>
+#ifndef RENAME_NOREPLACE
+# define RENAME_NOREPLACE  (1 << 0)
+# define RENAME_EXCHANGE   (1 << 1)
+# define RENAME_WHITEOUT   (1 << 2)
+#endif
+
+extern int renameatu (int, char const *, int, char const *, unsigned int);
--- a/modules/backup-rename	Wed Jul 04 20:42:07 2018 -0700
+++ b/modules/backup-rename	Thu Jul 05 09:22:09 2018 -0700
@@ -18,7 +18,7 @@
 fcntl
 memcmp
 opendir
-renameat2
+renameatu
 readdir
 stdbool
 
--- a/modules/backupfile	Wed Jul 04 20:42:07 2018 -0700
+++ b/modules/backupfile	Thu Jul 05 09:22:09 2018 -0700
@@ -18,7 +18,7 @@
 fcntl
 memcmp
 opendir
-renameat2
+renameatu
 readdir
 stdbool
 
--- a/modules/renameat	Wed Jul 04 20:42:07 2018 -0700
+++ b/modules/renameat	Thu Jul 05 09:22:09 2018 -0700
@@ -6,7 +6,7 @@
 m4/renameat.m4
 
 Depends-on:
-renameat2        [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
+renameatu        [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
 
 configure.ac:
 gl_FUNC_RENAMEAT
--- a/modules/renameat2	Wed Jul 04 20:42:07 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-Description:
-renameat2() function: rename a file, relative to two directories
-
-Files:
-lib/at-func2.c
-lib/renameat2.c
-lib/renameat2.h
-m4/renameat.m4
-
-Depends-on:
-stdio
-extensions
-fcntl-h
-filenamecat-lgpl [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
-openat-h         [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
-statat           [test $REPLACE_RENAMEAT = 1]
-stdbool          [test $REPLACE_RENAMEAT = 1]
-at-internal      [test $HAVE_RENAMEAT = 0]
-dosname          [test $HAVE_RENAMEAT = 0]
-getcwd-lgpl      [test $HAVE_RENAMEAT = 0]
-openat-die       [test $HAVE_RENAMEAT = 0]
-rename           [test $HAVE_RENAMEAT = 0]
-same-inode       [test $HAVE_RENAMEAT = 0]
-save-cwd         [test $HAVE_RENAMEAT = 0]
-
-configure.ac:
-gl_FUNC_RENAMEAT
-if test $HAVE_RENAMEAT = 0; then
-  AC_LIBOBJ([at-func2])
-fi
-
-Makefile.am:
-lib_SOURCES += renameat2.c
-
-Include:
-"renameat2.h"
-
-License:
-GPL
-
-Maintainer:
-Jim Meyering, Eric Blake
--- a/modules/renameat2-tests	Wed Jul 04 20:42:07 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-Files:
-tests/test-rename.h
-tests/test-renameat2.c
-tests/signature.h
-tests/macros.h
-
-Depends-on:
-ignore-value
-filenamecat
-getcwd-lgpl
-opendir
-readdir
-closedir
-
-configure.ac:
-
-Makefile.am:
-TESTS += test-renameat2
-check_PROGRAMS += test-renameat2
-test_renameat2_LDADD = $(LDADD) @LIBINTL@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/renameatu	Thu Jul 05 09:22:09 2018 -0700
@@ -0,0 +1,42 @@
+Description:
+renameatu() function: rename a file, relative to two dirs, with unsigned flag
+
+Files:
+lib/at-func2.c
+lib/renameatu.c
+lib/renameatu.h
+m4/renameat.m4
+
+Depends-on:
+stdio
+extensions
+fcntl-h
+filenamecat-lgpl [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
+openat-h         [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1]
+statat           [test $REPLACE_RENAMEAT = 1]
+stdbool          [test $REPLACE_RENAMEAT = 1]
+at-internal      [test $HAVE_RENAMEAT = 0]
+dosname          [test $HAVE_RENAMEAT = 0]
+getcwd-lgpl      [test $HAVE_RENAMEAT = 0]
+openat-die       [test $HAVE_RENAMEAT = 0]
+rename           [test $HAVE_RENAMEAT = 0]
+same-inode       [test $HAVE_RENAMEAT = 0]
+save-cwd         [test $HAVE_RENAMEAT = 0]
+
+configure.ac:
+gl_FUNC_RENAMEAT
+if test $HAVE_RENAMEAT = 0; then
+  AC_LIBOBJ([at-func2])
+fi
+
+Makefile.am:
+lib_SOURCES += renameatu.c
+
+Include:
+"renameatu.h"
+
+License:
+GPL
+
+Maintainer:
+Jim Meyering, Eric Blake
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/renameatu-tests	Thu Jul 05 09:22:09 2018 -0700
@@ -0,0 +1,20 @@
+Files:
+tests/test-rename.h
+tests/test-renameatu.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+ignore-value
+filenamecat
+getcwd-lgpl
+opendir
+readdir
+closedir
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-renameatu
+check_PROGRAMS += test-renameatu
+test_renameatu_LDADD = $(LDADD) @LIBINTL@
--- a/tests/test-renameat2.c	Wed Jul 04 20:42:07 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/* Test renameat2.
-   Copyright (C) 2009-2018 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* Written by Eric Blake <ebb9@byu.net>, 2009.  */
-
-#include <config.h>
-
-#include <renameat2.h>
-
-#include <stdio.h>
-
-#include "signature.h"
-SIGNATURE_CHECK (renameat2, int,
-                 (int, char const *, int, char const *, unsigned int));
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include "filenamecat.h"
-#include "ignore-value.h"
-#include "macros.h"
-
-#define BASE "test-renameat2.t"
-
-#include "test-rename.h"
-
-static int dfd1 = AT_FDCWD;
-static int dfd2 = AT_FDCWD;
-
-/* Wrapper to test renameat2 like rename.  */
-static int
-do_rename (char const *name1, char const *name2)
-{
-  return renameat2 (dfd1, name1, dfd2, name2, 0);
-}
-
-int
-main (void)
-{
-  int i;
-  int dfd;
-  char *cwd;
-  int result;
-
-  /* Clean up any trash from prior testsuite runs.  */
-  ignore_value (system ("rm -rf " BASE "*"));
-
-  /* Test behaviour for invalid file descriptors.  */
-  {
-    errno = 0;
-    ASSERT (renameat2 (-1, "foo", AT_FDCWD, "bar", 0) == -1);
-    ASSERT (errno == EBADF);
-  }
-  {
-    close (99);
-    errno = 0;
-    ASSERT (renameat2 (99, "foo", AT_FDCWD, "bar", 0) == -1);
-    ASSERT (errno == EBADF);
-  }
-  ASSERT (close (creat (BASE "oo", 0600)) == 0);
-  {
-    errno = 0;
-    ASSERT (renameat2 (AT_FDCWD, BASE "oo", -1, "bar", 0) == -1);
-    ASSERT (errno == EBADF);
-  }
-  {
-    errno = 0;
-    ASSERT (renameat2 (AT_FDCWD, BASE "oo", 99, "bar", 0) == -1);
-    ASSERT (errno == EBADF);
-  }
-  ASSERT (unlink (BASE "oo") == 0);
-
-  /* Test basic rename functionality, using current directory.  */
-  result = test_rename (do_rename, false);
-  dfd1 = open (".", O_RDONLY);
-  ASSERT (0 <= dfd1);
-  ASSERT (test_rename (do_rename, false) == result);
-  dfd2 = dfd1;
-  ASSERT (test_rename (do_rename, false) == result);
-  dfd1 = AT_FDCWD;
-  ASSERT (test_rename (do_rename, false) == result);
-  ASSERT (close (dfd2) == 0);
-
-  /* Create locations to manipulate.  */
-  ASSERT (mkdir (BASE "sub1", 0700) == 0);
-  ASSERT (mkdir (BASE "sub2", 0700) == 0);
-  dfd = creat (BASE "00", 0600);
-  ASSERT (0 <= dfd);
-  ASSERT (close (dfd) == 0);
-  cwd = getcwd (NULL, 0);
-  ASSERT (cwd);
-
-  dfd = open (BASE "sub1", O_RDONLY);
-  ASSERT (0 <= dfd);
-  ASSERT (chdir (BASE "sub2") == 0);
-
-  /* There are 16 possible scenarios, based on whether an fd is
-     AT_FDCWD or real, and whether a file is absolute or relative.
-
-     To ensure that we test all of the code paths (rather than
-     triggering early normalization optimizations), we use a loop to
-     repeatedly rename a file in the parent directory, use an fd open
-     on subdirectory 1, all while executing in subdirectory 2; all
-     relative names are thus given with a leading "../".  Finally, the
-     last scenario (two relative paths given, neither one AT_FDCWD)
-     has two paths, based on whether the two fds are equivalent, so we
-     do the other variant after the loop.  */
-  for (i = 0; i < 16; i++)
-    {
-      int fd1 = (i & 8) ? dfd : AT_FDCWD;
-      char *file1 = file_name_concat ((i & 4) ? ".." : cwd, BASE "xx", NULL);
-      int fd2 = (i & 2) ? dfd : AT_FDCWD;
-      char *file2 = file_name_concat ((i & 1) ? ".." : cwd, BASE "xx", NULL);
-
-      ASSERT (sprintf (strchr (file1, '\0') - 2, "%02d", i) == 2);
-      ASSERT (sprintf (strchr (file2, '\0') - 2, "%02d", i + 1) == 2);
-      ASSERT (renameat2 (fd1, file1, fd2, file2, 0) == 0);
-      free (file1);
-      free (file2);
-    }
-  dfd2 = open ("..", O_RDONLY);
-  ASSERT (0 <= dfd2);
-  ASSERT (renameat2 (dfd, "../" BASE "16", dfd2, BASE "17", 0) == 0);
-  ASSERT (close (dfd2) == 0);
-
-  /* Now we change back to the parent directory, and set dfd to ".";
-     using dfd in remaining tests will expose any bugs if emulation
-     via /proc/self/fd doesn't check for empty names.  */
-  ASSERT (chdir ("..") == 0);
-  ASSERT (close (dfd) == 0);
-  dfd = open (".", O_RDONLY);
-  ASSERT (0 <= dfd);
-
-  ASSERT (close (creat (BASE "sub2/file", 0600)) == 0);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "sub1", dfd, BASE "sub2", 0) == -1);
-  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
-  ASSERT (unlink (BASE "sub2/file") == 0);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "sub2", dfd, BASE "sub1/.", 0) == -1);
-  ASSERT (errno == EINVAL || errno == EISDIR || errno == EBUSY
-          || errno == ENOTEMPTY || errno == EEXIST
-          || errno == ENOENT /* WSL */);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "sub2/.", dfd, BASE "sub1", 0) == -1);
-  ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST
-          || errno == ENOENT /* WSL */);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "17", dfd, BASE "sub1", 0) == -1);
-  ASSERT (errno == EISDIR);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "nosuch", dfd, BASE "18", 0) == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (renameat2 (dfd, "", dfd, BASE "17", 0) == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "17", dfd, "", 0) == -1);
-  ASSERT (errno == ENOENT);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "sub2", dfd, BASE "17", 0) == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "17/", dfd, BASE "18", 0) == -1);
-  ASSERT (errno == ENOTDIR);
-  errno = 0;
-  ASSERT (renameat2 (dfd, BASE "17", dfd, BASE "18/", 0) == -1);
-  ASSERT (errno == ENOTDIR || errno == ENOENT);
-
-  /* Finally, make sure we cannot overwrite existing files.  */
-  ASSERT (close (creat (BASE "sub2/file", 0600)) == 0);
-  errno = 0;
-  ASSERT ((renameat2 (dfd, BASE "sub2", dfd, BASE "sub1", RENAME_NOREPLACE)
-           == -1)
-          && errno == EEXIST);
-  ASSERT ((renameat2 (dfd, BASE "sub2/file", dfd, BASE "17", RENAME_NOREPLACE)
-           == -1)
-          && errno == EEXIST);
-
-  /* Cleanup.  */
-  ASSERT (close (dfd) == 0);
-  ASSERT (unlink (BASE "sub2/file") == 0);
-  ASSERT (unlink (BASE "17") == 0);
-  ASSERT (rmdir (BASE "sub1") == 0);
-  ASSERT (rmdir (BASE "sub2") == 0);
-  free (cwd);
-
-  if (result)
-    fputs ("skipping test: symlinks not supported on this file system\n",
-           stderr);
-  return result;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-renameatu.c	Thu Jul 05 09:22:09 2018 -0700
@@ -0,0 +1,211 @@
+/* Test renameatu.
+   Copyright (C) 2009-2018 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake <ebb9@byu.net>, 2009.  */
+
+#include <config.h>
+
+#include <renameatu.h>
+
+#include <stdio.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (renameatu, int,
+                 (int, char const *, int, char const *, unsigned int));
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "filenamecat.h"
+#include "ignore-value.h"
+#include "macros.h"
+
+#define BASE "test-renameatu.t"
+
+#include "test-rename.h"
+
+static int dfd1 = AT_FDCWD;
+static int dfd2 = AT_FDCWD;
+
+/* Wrapper to test renameatu like rename.  */
+static int
+do_rename (char const *name1, char const *name2)
+{
+  return renameatu (dfd1, name1, dfd2, name2, 0);
+}
+
+int
+main (void)
+{
+  int i;
+  int dfd;
+  char *cwd;
+  int result;
+
+  /* Clean up any trash from prior testsuite runs.  */
+  ignore_value (system ("rm -rf " BASE "*"));
+
+  /* Test behaviour for invalid file descriptors.  */
+  {
+    errno = 0;
+    ASSERT (renameatu (-1, "foo", AT_FDCWD, "bar", 0) == -1);
+    ASSERT (errno == EBADF);
+  }
+  {
+    close (99);
+    errno = 0;
+    ASSERT (renameatu (99, "foo", AT_FDCWD, "bar", 0) == -1);
+    ASSERT (errno == EBADF);
+  }
+  ASSERT (close (creat (BASE "oo", 0600)) == 0);
+  {
+    errno = 0;
+    ASSERT (renameatu (AT_FDCWD, BASE "oo", -1, "bar", 0) == -1);
+    ASSERT (errno == EBADF);
+  }
+  {
+    errno = 0;
+    ASSERT (renameatu (AT_FDCWD, BASE "oo", 99, "bar", 0) == -1);
+    ASSERT (errno == EBADF);
+  }
+  ASSERT (unlink (BASE "oo") == 0);
+
+  /* Test basic rename functionality, using current directory.  */
+  result = test_rename (do_rename, false);
+  dfd1 = open (".", O_RDONLY);
+  ASSERT (0 <= dfd1);
+  ASSERT (test_rename (do_rename, false) == result);
+  dfd2 = dfd1;
+  ASSERT (test_rename (do_rename, false) == result);
+  dfd1 = AT_FDCWD;
+  ASSERT (test_rename (do_rename, false) == result);
+  ASSERT (close (dfd2) == 0);
+
+  /* Create locations to manipulate.  */
+  ASSERT (mkdir (BASE "sub1", 0700) == 0);
+  ASSERT (mkdir (BASE "sub2", 0700) == 0);
+  dfd = creat (BASE "00", 0600);
+  ASSERT (0 <= dfd);
+  ASSERT (close (dfd) == 0);
+  cwd = getcwd (NULL, 0);
+  ASSERT (cwd);
+
+  dfd = open (BASE "sub1", O_RDONLY);
+  ASSERT (0 <= dfd);
+  ASSERT (chdir (BASE "sub2") == 0);
+
+  /* There are 16 possible scenarios, based on whether an fd is
+     AT_FDCWD or real, and whether a file is absolute or relative.
+
+     To ensure that we test all of the code paths (rather than
+     triggering early normalization optimizations), we use a loop to
+     repeatedly rename a file in the parent directory, use an fd open
+     on subdirectory 1, all while executing in subdirectory 2; all
+     relative names are thus given with a leading "../".  Finally, the
+     last scenario (two relative paths given, neither one AT_FDCWD)
+     has two paths, based on whether the two fds are equivalent, so we
+     do the other variant after the loop.  */
+  for (i = 0; i < 16; i++)
+    {
+      int fd1 = (i & 8) ? dfd : AT_FDCWD;
+      char *file1 = file_name_concat ((i & 4) ? ".." : cwd, BASE "xx", NULL);
+      int fd2 = (i & 2) ? dfd : AT_FDCWD;
+      char *file2 = file_name_concat ((i & 1) ? ".." : cwd, BASE "xx", NULL);
+
+      ASSERT (sprintf (strchr (file1, '\0') - 2, "%02d", i) == 2);
+      ASSERT (sprintf (strchr (file2, '\0') - 2, "%02d", i + 1) == 2);
+      ASSERT (renameatu (fd1, file1, fd2, file2, 0) == 0);
+      free (file1);
+      free (file2);
+    }
+  dfd2 = open ("..", O_RDONLY);
+  ASSERT (0 <= dfd2);
+  ASSERT (renameatu (dfd, "../" BASE "16", dfd2, BASE "17", 0) == 0);
+  ASSERT (close (dfd2) == 0);
+
+  /* Now we change back to the parent directory, and set dfd to ".";
+     using dfd in remaining tests will expose any bugs if emulation
+     via /proc/self/fd doesn't check for empty names.  */
+  ASSERT (chdir ("..") == 0);
+  ASSERT (close (dfd) == 0);
+  dfd = open (".", O_RDONLY);
+  ASSERT (0 <= dfd);
+
+  ASSERT (close (creat (BASE "sub2/file", 0600)) == 0);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "sub1", dfd, BASE "sub2", 0) == -1);
+  ASSERT (errno == EEXIST || errno == ENOTEMPTY);
+  ASSERT (unlink (BASE "sub2/file") == 0);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "sub2", dfd, BASE "sub1/.", 0) == -1);
+  ASSERT (errno == EINVAL || errno == EISDIR || errno == EBUSY
+          || errno == ENOTEMPTY || errno == EEXIST
+          || errno == ENOENT /* WSL */);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "sub2/.", dfd, BASE "sub1", 0) == -1);
+  ASSERT (errno == EINVAL || errno == EBUSY || errno == EEXIST
+          || errno == ENOENT /* WSL */);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "17", dfd, BASE "sub1", 0) == -1);
+  ASSERT (errno == EISDIR);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "nosuch", dfd, BASE "18", 0) == -1);
+  ASSERT (errno == ENOENT);
+  errno = 0;
+  ASSERT (renameatu (dfd, "", dfd, BASE "17", 0) == -1);
+  ASSERT (errno == ENOENT);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "17", dfd, "", 0) == -1);
+  ASSERT (errno == ENOENT);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "sub2", dfd, BASE "17", 0) == -1);
+  ASSERT (errno == ENOTDIR);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "17/", dfd, BASE "18", 0) == -1);
+  ASSERT (errno == ENOTDIR);
+  errno = 0;
+  ASSERT (renameatu (dfd, BASE "17", dfd, BASE "18/", 0) == -1);
+  ASSERT (errno == ENOTDIR || errno == ENOENT);
+
+  /* Finally, make sure we cannot overwrite existing files.  */
+  ASSERT (close (creat (BASE "sub2/file", 0600)) == 0);
+  errno = 0;
+  ASSERT ((renameatu (dfd, BASE "sub2", dfd, BASE "sub1", RENAME_NOREPLACE)
+           == -1)
+          && errno == EEXIST);
+  ASSERT ((renameatu (dfd, BASE "sub2/file", dfd, BASE "17", RENAME_NOREPLACE)
+           == -1)
+          && errno == EEXIST);
+
+  /* Cleanup.  */
+  ASSERT (close (dfd) == 0);
+  ASSERT (unlink (BASE "sub2/file") == 0);
+  ASSERT (unlink (BASE "17") == 0);
+  ASSERT (rmdir (BASE "sub1") == 0);
+  ASSERT (rmdir (BASE "sub2") == 0);
+  free (cwd);
+
+  if (result)
+    fputs ("skipping test: symlinks not supported on this file system\n",
+           stderr);
+  return result;
+}