Use linkat() if available

Some OSes have a more capable linkat() function that can hard-link
syslinks, so use linkat() when it is available.
This commit is contained in:
Wayne Davison
2020-07-27 16:36:55 -07:00
parent 54693fa992
commit 5db7e4b1ee
2 changed files with 15 additions and 2 deletions

View File

@@ -822,7 +822,7 @@ AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd chown chmod lchmod mknod mkfifo \
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
chflags getattrlist mktime innetgr \
chflags getattrlist mktime innetgr linkat \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
@@ -946,6 +946,11 @@ fi
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#elif defined HAVE_SYS_FCNTL_H
# include <sys/fcntl.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -956,7 +961,11 @@ int main(void) {
unlink(FILENAME);
if (symlink("conftest.no-such", FILENAME) < 0) abort();
unlink(FILENAME "2");
#ifdef HAVE_LINKAT
if (linkat(AT_FDCWD, FILENAME, AT_FDCWD, FILENAME "2", 0) < 0) return 1;
#else
if (link(FILENAME, FILENAME "2") < 0) return 1;
#endif
return 0;
}]])],[rsync_cv_can_hardlink_symlink=yes],[rsync_cv_can_hardlink_symlink=no],[rsync_cv_can_hardlink_symlink=no])])
if test $rsync_cv_can_hardlink_symlink = yes; then

View File

@@ -129,12 +129,16 @@ ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
#endif
#endif
#ifdef HAVE_LINK
#if defined HAVE_LINK || defined HAVE_LINKAT
int do_link(const char *old_path, const char *new_path)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
#ifdef HAVE_LINKAT
return linkat(AT_FDCWD, old_path, AT_FDCWD, new_path, 0);
#else
return link(old_path, new_path);
#endif
}
#endif