Commit c8e57ce5 authored by Pádraig Brady's avatar Pádraig Brady

linkat: wrap to handle symlinks on OS X 10.10

* m4/linkat.m4 (gl_FUNC_LINKAT): linkat() is available on Yosemite
but not usable because it doesn't support creating hardlinks
to symlinks.  Therefore add a generic test for this capability
and fallback to our emulation if linkat() fails with ENOTSUP.
parent 08a713e0
2014-11-03 Pádraig Brady <P@draigBrady.com>
linkat: wrap to handle symlinks on OS X 10.10
* m4/linkat.m4 (gl_FUNC_LINKAT): linkat() is available on Yosemite
but not usable because it doesn't support creating hardlinks
to symlinks. Therefore add a generic test for this capability
and fallback to our emulation if linkat() fails with ENOTSUP.
2014-11-02 Paul Eggert <eggert@cs.ucla.edu>
open, openat: document nonstandard FreeBSD, NetBSD O_NOFOLLOW errno
......@@ -10,10 +10,13 @@ Portability problems fixed by Gnulib:
@itemize
@item
This function is missing on some platforms:
glibc 2.3.6, Mac OS X 10.5, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8,
glibc 2.3.6, Mac OS X < 10.10, FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8,
AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x, mingw, MSVC 9, Interix 3.5, BeOS.
But the replacement function is not safe to be used in libraries and is not multithread-safe.
@item
This function fails to directly hardlink symlinks on some platforms:
Mac OS X 10.10.
@item
This function fails to reject trailing slashes on non-directories on
some platforms:
AIX 7.1, Solaris 11 2011-11.
......
......@@ -43,7 +43,7 @@
# endif
#endif
#if !HAVE_LINKAT
#if !HAVE_LINKAT || LINKAT_SYMLINK_NOTSUP
/* Create a link. If FILE1 is a symlink, either create a hardlink to
that symlink, or fake it by creating an identical symlink. */
......@@ -195,6 +195,10 @@ solaris_optimized_link_follow (char const *file1, char const *file2)
# endif
#endif /* !HAVE_LINKAT || LINKAT_SYMLINK_NOTSUP */
#if !HAVE_LINKAT
/* Create a link to FILE1, in the directory open on descriptor FD1, to FILE2,
in the directory open on descriptor FD2. If FILE1 is a symlink, FLAG
controls whether to dereference FILE1 first. If possible, do it without
......@@ -321,7 +325,17 @@ rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
# endif
if (!flag)
return linkat (fd1, file1, fd2, file2, flag);
{
int result = linkat (fd1, file1, fd2, file2, flag);
# if LINKAT_SYMLINK_NOTSUP
/* OS X 10.10 has linkat() but it doesn't support
hardlinks to symlinks. Fallback to our emulation
in that case. */
if (result == -1 && (errno == ENOTSUP || errno == EOPNOTSUPP))
return at_func2 (fd1, file1, fd2, file2, link_immediate);
# endif
return result;
}
/* Cache the information on whether the system call really works. */
{
......
......@@ -20,6 +20,27 @@ AC_DEFUN([gl_FUNC_LINKAT],
if test $ac_cv_func_linkat = no; then
HAVE_LINKAT=0
else
dnl OS X Yosemite has linkat() but it's not sufficient
dnl to our needs since it doesn't support creating
dnl hardlinks to symlinks. Therefore check for that
dnl capability before considering using the system version.
AC_CACHE_CHECK([whether linkat() can link symlinks],
[gl_cv_func_linkat_nofollow],
[rm -rf conftest.l1 conftest.l2
ln -s target conftest.l1
AC_RUN_IFELSE([AC_LANG_PROGRAM(
[[#include <fcntl.h>
#include <unistd.h>
]],
[return linkat (AT_FDCWD, "conftest.l1", AT_FDCWD,
"conftest.l2", 0);
])],
[gl_cv_func_linkat_nofollow=yes
LINKAT_SYMLINK_NOTSUP=0],
[gl_cv_func_linkat_nofollow=no
LINKAT_SYMLINK_NOTSUP=1])
rm -rf conftest.l1 conftest.l2])
AC_CACHE_CHECK([whether linkat(,AT_SYMLINK_FOLLOW) works],
[gl_cv_func_linkat_follow],
[rm -rf conftest.f1 conftest.f2
......@@ -37,6 +58,7 @@ choke me
[gl_cv_func_linkat_follow=yes],
[gl_cv_func_linkat_follow="need runtime check"])
rm -rf conftest.f1 conftest.f2])
AC_CACHE_CHECK([whether linkat handles trailing slash correctly],
[gl_cv_func_linkat_slash],
[rm -rf conftest.a conftest.b conftest.c conftest.d
......@@ -85,11 +107,15 @@ choke me
*yes) gl_linkat_slash_bug=0 ;;
*) gl_linkat_slash_bug=1 ;;
esac
if test "$gl_cv_func_linkat_follow" != yes \
|| test "$gl_cv_func_linkat_nofollow" != yes \
|| test $gl_linkat_slash_bug = 1; then
REPLACE_LINKAT=1
AC_DEFINE_UNQUOTED([LINKAT_TRAILING_SLASH_BUG], [$gl_linkat_slash_bug],
[Define to 1 if linkat fails to recognize a trailing slash.])
AC_DEFINE_UNQUOTED([LINKAT_SYMLINK_NOTSUP], [$LINKAT_SYMLINK_NOTSUP],
[Define to 1 if linkat can create hardlinks to symlinks])
fi
fi
])
......@@ -14,18 +14,18 @@ errno [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
fcntl-h [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
filenamecat-lgpl [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
link-follow [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
areadlink [test $HAVE_LINKAT = 0]
at-internal [test $HAVE_LINKAT = 0]
dosname [test $HAVE_LINKAT = 0]
fstat [test $HAVE_LINKAT = 0]
getcwd-lgpl [test $HAVE_LINKAT = 0]
openat-h [test $HAVE_LINKAT = 0]
openat-die [test $HAVE_LINKAT = 0]
link [test $HAVE_LINKAT = 0]
lstat [test $HAVE_LINKAT = 0]
same-inode [test $HAVE_LINKAT = 0]
save-cwd [test $HAVE_LINKAT = 0]
symlink [test $HAVE_LINKAT = 0]
areadlink [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
at-internal [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
dosname [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
fstat [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
getcwd-lgpl [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
openat-h [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
openat-die [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
link [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
lstat [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
same-inode [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
save-cwd [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
symlink [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1]
areadlinkat [test $REPLACE_LINKAT = 1]
fstatat [test $REPLACE_LINKAT = 1]
......@@ -33,8 +33,6 @@ configure.ac:
gl_FUNC_LINKAT
if test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1; then
AC_LIBOBJ([linkat])
fi
if test $HAVE_LINKAT = 0; then
AC_LIBOBJ([at-func2])
fi
gl_UNISTD_MODULE_INDICATOR([linkat])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment