\f
static bool
-is_directory_link (const char *file_name)
+is_directory_link (char const *file_name, struct stat *st)
{
- struct stat st;
- int e = errno;
- int res;
-
- res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 &&
- S_ISLNK (st.st_mode) &&
- fstatat (chdir_fd, file_name, &st, 0) == 0 &&
- S_ISDIR (st.st_mode));
- errno = e;
- return res;
+ char buf[1];
+ return (0 <= readlinkat (chdir_fd, file_name, buf, sizeof buf)
+ && fstatat (chdir_fd, file_name, st, 0) == 0
+ && S_ISDIR (st->st_mode));
}
\f
/* Given struct stat of a directory (or directory member) whose ownership
|| old_files_option == OVERWRITE_OLD_FILES))
{
struct stat st;
+ st.st_mode = 0;
- if (keep_directory_symlink_option && is_directory_link (file_name))
+ if (keep_directory_symlink_option
+ && is_directory_link (file_name, &st))
return 0;
- if (deref_stat (file_name, &st) == 0)
+ if ((st.st_mode != 0 && fstatat_flags == 0)
+ || deref_stat (file_name, &st) == 0)
{
current_mode = st.st_mode;
current_mode_mask = ALL_MODE_BITS;
if (! HAVE_WORKING_O_NOFOLLOW
&& overwriting_old_files && ! dereference_option)
{
- struct stat st;
- if (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0
- && S_ISLNK (st.st_mode))
+ char buf[1];
+ if (0 <= readlinkat (chdir_fd, file_name, buf, sizeof buf))
{
errno = ELOOP;
return -1;