bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PROPOSED] renameatu: rename from renameat2


From: Paul Eggert
Subject: [PROPOSED] renameatu: rename from renameat2
Date: Tue, 3 Jul 2018 19:45:32 -0700

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.
* 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.
---
 ChangeLog               |  20 +++++
 MODULES.html.sh         |   2 +-
 NEWS                    |   4 +
 lib/backupfile.c        |   4 +-
 lib/renameat.c          |   4 +-
 lib/renameat2.c         | 227 -----------------------------------------------
 lib/renameat2.h         |  30 -------
 lib/renameatu.c         | 230 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/renameatu.h         |  28 ++++++
 modules/backup-rename   |   2 +-
 modules/backupfile      |   2 +-
 modules/renameat        |   2 +-
 modules/renameat2       |  42 ---------
 modules/renameat2-tests |  20 -----
 modules/renameatu       |  42 +++++++++
 modules/renameatu-tests |  20 +++++
 tests/test-renameat2.c  | 211 --------------------------------------------
 tests/test-renameatu.c  | 211 ++++++++++++++++++++++++++++++++++++++++++++
 18 files changed, 563 insertions(+), 538 deletions(-)
 delete mode 100644 lib/renameat2.c
 delete mode 100644 lib/renameat2.h
 create mode 100644 lib/renameatu.c
 create mode 100644 lib/renameatu.h
 delete mode 100644 modules/renameat2
 delete mode 100644 modules/renameat2-tests
 create mode 100644 modules/renameatu
 create mode 100644 modules/renameatu-tests
 delete mode 100644 tests/test-renameat2.c
 create mode 100644 tests/test-renameatu.c

diff --git a/ChangeLog b/ChangeLog
index a220b9c..feddd30 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2018-07-03  Paul Eggert  <address@hidden>
+
+       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.
+       * 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-01  Paul Eggert  <address@hidden>
 
        wchar: fix bug when checking for ‘inline’
diff --git a/MODULES.html.sh b/MODULES.html.sh
index 2cb4cd3..a61a84e 100755
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -2689,7 +2689,7 @@ func_all_modules ()
   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
diff --git a/NEWS b/NEWS
index f4fc2e2..dd688b6 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,10 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2018-07-03  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.
 
diff --git a/lib/backupfile.c b/lib/backupfile.c
index d438455..637be6c 100644
--- a/lib/backupfile.c
+++ b/lib/backupfile.c
@@ -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 @@ backupfile_internal (char const *file, enum backup_type 
backup_type, bool rename
           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)
diff --git a/lib/renameat.c b/lib/renameat.c
index 0cb7d33..67be22b 100644
--- a/lib/renameat.c
+++ b/lib/renameat.c
@@ -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);
 }
diff --git a/lib/renameat2.c b/lib/renameat2.c
deleted file mode 100644
index a295ec3..0000000
--- a/lib/renameat2.c
+++ /dev/null
@@ -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 */
-}
diff --git a/lib/renameat2.h b/lib/renameat2.h
deleted file mode 100644
index aba7966..0000000
--- a/lib/renameat2.h
+++ /dev/null
@@ -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);
diff --git a/lib/renameatu.c b/lib/renameatu.c
new file mode 100644
index 0000000..b013ad6
--- /dev/null
+++ b/lib/renameatu.c
@@ -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 */
+}
diff --git a/lib/renameatu.h b/lib/renameatu.h
new file mode 100644
index 0000000..7d79775
--- /dev/null
+++ b/lib/renameatu.h
@@ -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);
diff --git a/modules/backup-rename b/modules/backup-rename
index 4d8932d..7e551af 100644
--- a/modules/backup-rename
+++ b/modules/backup-rename
@@ -18,7 +18,7 @@ dirname-lgpl
 fcntl
 memcmp
 opendir
-renameat2
+renameatu
 readdir
 stdbool
 
diff --git a/modules/backupfile b/modules/backupfile
index 9e4efd7..e9933fb 100644
--- a/modules/backupfile
+++ b/modules/backupfile
@@ -18,7 +18,7 @@ dirname-lgpl
 fcntl
 memcmp
 opendir
-renameat2
+renameatu
 readdir
 stdbool
 
diff --git a/modules/renameat b/modules/renameat
index 9af0225..48b32c3 100644
--- a/modules/renameat
+++ b/modules/renameat
@@ -6,7 +6,7 @@ lib/renameat.c
 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
diff --git a/modules/renameat2 b/modules/renameat2
deleted file mode 100644
index 54f72e1..0000000
--- a/modules/renameat2
+++ /dev/null
@@ -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
diff --git a/modules/renameat2-tests b/modules/renameat2-tests
deleted file mode 100644
index accf3c4..0000000
--- a/modules/renameat2-tests
+++ /dev/null
@@ -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@
diff --git a/modules/renameatu b/modules/renameatu
new file mode 100644
index 0000000..1c3fd99
--- /dev/null
+++ b/modules/renameatu
@@ -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
diff --git a/modules/renameatu-tests b/modules/renameatu-tests
new file mode 100644
index 0000000..135755e
--- /dev/null
+++ b/modules/renameatu-tests
@@ -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@
diff --git a/tests/test-renameat2.c b/tests/test-renameat2.c
deleted file mode 100644
index 0104890..0000000
--- a/tests/test-renameat2.c
+++ /dev/null
@@ -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 <address@hidden>, 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;
-}
diff --git a/tests/test-renameatu.c b/tests/test-renameatu.c
new file mode 100644
index 0000000..988428b
--- /dev/null
+++ b/tests/test-renameatu.c
@@ -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 <address@hidden>, 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;
+}
-- 
2.7.4






reply via email to

[Prev in Thread] Current Thread [Next in Thread]