From: Wayne Davison Date: Mon, 27 Jul 2020 23:36:55 +0000 (-0700) Subject: Use linkat() if available X-Git-Tag: v3.2.3pre1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5db7e4b1eefb3fab6a5e5808d718bfe74ee79bc0;p=thirdparty%2Frsync.git Use linkat() if available Some OSes have a more capable linkat() function that can hard-link syslinks, so use linkat() when it is available. --- diff --git a/configure.ac b/configure.ac index 8030eebc..b271e363 100644 --- a/configure.ac +++ b/configure.ac @@ -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 +#elif defined HAVE_SYS_FCNTL_H +# include +#endif #if HAVE_UNISTD_H # include #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 diff --git a/syscall.c b/syscall.c index 80cac204..b9c3b4ef 100644 --- a/syscall.c +++ b/syscall.c @@ -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