mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-01-24 23:08:24 -05:00
Make do_readlink() support fake-super w/o O_NOFOLLOW.
This commit is contained in:
49
syscall.c
49
syscall.c
@@ -87,7 +87,7 @@ ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
|
||||
{
|
||||
/* For --fake-super, we read the link from the file. */
|
||||
if (am_root < 0) {
|
||||
int fd = open(path, O_RDONLY|O_NOFOLLOW);
|
||||
int fd = do_open_nofollow(path, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
int len = read(fd, buf, bufsiz);
|
||||
close(fd);
|
||||
@@ -443,3 +443,50 @@ int do_fallocate(int fd, OFF_T offset, OFF_T length)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int do_open_nofollow(const char *pathname, int flags)
|
||||
{
|
||||
#ifndef O_NOFOLLOW
|
||||
struct stat f_st, l_st;
|
||||
#endif
|
||||
int fd;
|
||||
|
||||
if (flags != O_RDONLY) {
|
||||
RETURN_ERROR_IF(dry_run, 0);
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
#ifndef O_NOFOLLOW
|
||||
/* This function doesn't support write attempts w/o O_NOFOLLOW. */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef O_NOFOLLOW
|
||||
fd = open(pathname, flags|O_NOFOLLOW);
|
||||
#else
|
||||
if ((fd = open(pathname, flags)) < 0)
|
||||
return fd;
|
||||
|
||||
if (do_fstat(fd, &f_st) < 0) {
|
||||
close_and_return_error:
|
||||
{
|
||||
int save_errno = errno;
|
||||
close(fd);
|
||||
errno = save_errno;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (do_lstat(pathname, &l_st) < 0)
|
||||
goto close_and_return_error;
|
||||
if (S_ISLNK(l_st.st_mode)) {
|
||||
errno = ELOOP;
|
||||
goto close_and_return_error;
|
||||
}
|
||||
if (l_st.st_dev != f_st.st_dev || l_st.st_ino != f_st.st_ino) {
|
||||
errno = EINVAL;
|
||||
goto close_and_return_error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user