]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/unix/sysv/linux/renameat.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / renameat.c
index 31662ea05313594999ae7e3a1244544557dcfe6f..e0ced79e8584622bc29a4c34563134172af34f4c 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005 Free Software Foundation, Inc.
+/* Linux implementation for renameat function.
+   Copyright (C) 2016-2019 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
    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, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <fcntl.h>
 #include <stdio.h>
+#include <fcntl.h>
 #include <sysdep.h>
+#include <errno.h>
 
-
-/* Rename the file OLD relative to OLDFD to NEW relative to NEWFD.  */
 int
-renameat (oldfd, old, newfd, new)
-     int oldfd;
-     const char *old;
-     int newfd;
-     const char *new;
+__renameat (int oldfd, const char *old, int newfd, const char *new)
 {
-  static const char procfd[] = "/proc/self/fd/%d/%s";
-  char *bufold = NULL;
-
-  if (oldfd != AT_FDCWD && old[0] != '/')
-    {
-      size_t filelen = strlen (old);
-      /* Buffer for the path name we are going to use.  It consists of
-        - the string /proc/self/fd/
-        - the file descriptor number
-        - the file name provided.
-        The final NUL is included in the sizeof.   A bit of overhead
-        due to the format elements compensates for possible negative
-        numbers.  */
-      size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
-      bufold = alloca (buflen);
-
-      __snprintf (bufold, buflen, procfd, oldfd, old);
-      old = bufold;
-    }
-
-  char *bufnew = NULL;
-
-  if (newfd != AT_FDCWD && new[0] != '/')
-    {
-      size_t filelen = strlen (new);
-      /* Buffer for the path name we are going to use.  It consists of
-        - the string /proc/self/fd/
-        - the file descriptor number
-        - the file name provided.
-        The final NUL is included in the sizeof.   A bit of overhead
-        due to the format elements compensates for possible negative
-        numbers.  */
-      size_t buflen = sizeof (procfd) + sizeof (int) * 3 + filelen;
-      bufnew = alloca (buflen);
-
-      __snprintf (bufnew, buflen, procfd, newfd, new);
-      new = bufnew;
-    }
-
-  INTERNAL_SYSCALL_DECL (err);
-
-  int result = INTERNAL_SYSCALL (rename, err, 2, old,  new);
-
-  if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 0))
-    {
-      int errval = INTERNAL_SYSCALL_ERRNO (result, err);
-      if (errval == ENOTDIR && (bufnew != NULL || bufold != NULL))
-       {
-         /* This can mean either the file descriptor is invalid or
-            /proc is not mounted.  */
-         struct stat64 st;
-
-         if (bufnew != NULL)
-           {
-             if (__fxstat64 (_STAT_VER, newfd, &st) != 0)
-               /* errno is already set correctly.  */
-               return -1;
-
-             /* If /proc is not mounted there is nothing we can do.  */
-             if (S_ISDIR (st.st_mode)
-                 && (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
-                     || !S_ISDIR (st.st_mode)))
-               {
-                 errval = ENOSYS;
-                 goto out;
-               }
-           }
-
-         if (bufold != NULL)
-           {
-             if (__fxstat64 (_STAT_VER, oldfd, &st) != 0)
-               /* errno is already set correctly.  */
-               return -1;
-
-             /* If /proc is not mounted there is nothing we can do.  */
-             if (S_ISDIR (st.st_mode)
-                 && (__xstat64 (_STAT_VER, "/proc/self/fd", &st) != 0
-                     || !S_ISDIR (st.st_mode)))
-               errval = ENOSYS;
-           }
-       }
-
-    out:
-      __set_errno (errval);
-      result = -1;
-    }
-
-  return result;
+#ifdef __NR_renameat
+  return INLINE_SYSCALL_CALL (renameat, oldfd, old, newfd, new);
+#else
+  return INLINE_SYSCALL_CALL (renameat2, oldfd, old, newfd, new, 0);
+#endif
 }
+libc_hidden_def (__renameat)
+weak_alias (__renameat, renameat)