diff options
Diffstat (limited to 'lib/renameat.c')
-rw-r--r-- | lib/renameat.c | 140 |
1 files changed, 4 insertions, 136 deletions
diff --git a/lib/renameat.c b/lib/renameat.c index 22151c2d88..af25a54fab 100644 --- a/lib/renameat.c +++ b/lib/renameat.c @@ -1,5 +1,5 @@ /* Rename a file relative to open directories. - Copyright (C) 2009-2017 Free Software Foundation, Inc. + Copyright 2017 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 @@ -14,144 +14,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* written by Eric Blake */ - #include <config.h> - #include <stdio.h> - -#if HAVE_RENAMEAT - -# include <errno.h> -# include <stdbool.h> -# include <stdlib.h> -# include <string.h> -# include <sys/stat.h> - -# include "dirname.h" -# include "openat.h" - -# undef renameat - -/* 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. */ - -int -rpl_renameat (int fd1, char const *src, int fd2, char const *dst) -{ - size_t src_len = strlen (src); - size_t dst_len = strlen (dst); - char *src_temp = (char *) src; - char *dst_temp = (char *) dst; - bool src_slash; - bool dst_slash; - int ret_val = -1; - int rename_errno = ENOTDIR; - struct stat src_st; - struct stat dst_st; - - /* Let strace see any ENOENT failure. */ - 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 (lstatat (fd2, dst, &dst_st)) - { - if (errno != ENOENT || !S_ISDIR (src_st.st_mode)) - return -1; - } - else if (!S_ISDIR (dst_st.st_mode)) - { - errno = ENOTDIR; - return -1; - } - else if (!S_ISDIR (src_st.st_mode)) - { - errno = EISDIR; - return -1; - } - -# 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. */ - 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 */ - - ret_val = renameat (fd1, src_temp, fd2, dst_temp); - rename_errno = errno; - out: - if (src_temp != src) - free (src_temp); - if (dst_temp != dst) - free (dst_temp); - errno = rename_errno; - return ret_val; -} - -#else /* !HAVE_RENAMEAT */ - -# include "openat-priv.h" - -/* 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. */ +#include "renameat2.h" int -renameat (int fd1, char const *file1, int fd2, char const *file2) +renameat (int fd1, char const *src, int fd2, char const *dst) { - return at_func2 (fd1, file1, fd2, file2, rename); + return renameat2 (fd1, src, fd2, dst, 0); } - -#endif /* !HAVE_RENAMEAT */ |