From 37da693c0a2d4d84369d1910d258370ce65552ce Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 28 Dec 2010 12:18:54 +0100 Subject: linkat: Make implementation robust against system behaviour variations. * m4/link-follow.m4 (gl_FUNC_LINK_FOLLOWS_SYMLINK): Define LINK_FOLLOWS_SYMLINKS to -1 if it needs a runtime test in the Solaris way, and to -2 if it needs a generic runtime test. * lib/linkat.c (solaris_optimized_link_immediate, solaris_optimized_link_follow): New functions. * tests/test-linkat.c (EXPECT_LINK_HARDLINKS_SYMLINKS): New macro. (check_same_link): Use it. --- m4/link-follow.m4 | 60 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 21 deletions(-) (limited to 'm4/link-follow.m4') diff --git a/m4/link-follow.m4 b/m4/link-follow.m4 index 256b2a99d8..95264db261 100644 --- a/m4/link-follow.m4 +++ b/m4/link-follow.m4 @@ -1,4 +1,4 @@ -# serial 15 +# serial 16 dnl Run a program to determine whether link(2) follows symlinks. dnl Set LINK_FOLLOWS_SYMLINKS accordingly. @@ -12,7 +12,8 @@ dnl LINK_FOLLOWS_SYMLINKS is 0, link matches linkat(,0), and dnl linkat(,AT_SYMLINK_FOLLOW) requires a readlink. If it is 1, dnl link matches linkat(,AT_SYMLINK_FOLLOW), and there is no way dnl to do linkat(,0) on symlinks (on all other file types, -dnl link() is sufficient). If it is -1, use a runtime test. +dnl link() is sufficient). If it is -1, use a Solaris specific +dnl runtime test. If it is -2, use a generic runtime test. AC_DEFUN([gl_FUNC_LINK_FOLLOWS_SYMLINK], [dnl AC_CHECK_FUNCS_ONCE([readlink]) @@ -22,12 +23,27 @@ AC_DEFUN([gl_FUNC_LINK_FOLLOWS_SYMLINK], dnl linkat variants. So, we set LINK_FOLLOWS_SYMLINKS to 0. gl_link_follows_symlinks=0 # assume GNU behavior if test $ac_cv_func_readlink = yes; then - AC_CACHE_CHECK([whether link(2) dereferences a symlink], - gl_cv_func_link_follows_symlink, - [ - # Create a regular file. - echo > conftest.file - AC_RUN_IFELSE([AC_LANG_SOURCE([[ + dnl Solaris has an __xpg4 variable in libc, and it determines the + dnl behaviour of link(): It dereferences a symlink if and only if + dnl __xpg4 != 0. + AC_CACHE_CHECK([for __xpg4], [gl_cv_have___xpg4], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[extern int __xpg4;]], + [[return __xpg4;]])], + [gl_cv_have___xpg4=yes], + [gl_cv_have___xpg4=no]) + ]) + if test $gl_cv_have___xpg4 = yes; then + gl_link_follows_symlinks=-1 + else + AC_CACHE_CHECK([whether link(2) dereferences a symlink], + [gl_cv_func_link_follows_symlink], + [ + # Create a regular file. + echo > conftest.file + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ # include # include # include @@ -62,20 +78,22 @@ AC_DEFUN([gl_FUNC_LINK_FOLLOWS_SYMLINK], the link call followed the symlink. */ return SAME_INODE (sb_hard, sb_file) ? 1 : 0; } - ]])], - [gl_cv_func_link_follows_symlink=no], dnl GNU behavior - [gl_cv_func_link_follows_symlink=yes], dnl Followed link/compile failed - [gl_cv_func_link_follows_symlink=unknown] dnl We're cross compiling. - ) - rm -f conftest.file conftest.sym conftest.hard - ]) - case $gl_cv_func_link_follows_symlink in - yes) gl_link_follows_symlinks=1 ;; - no) ;; # already defaulted to 0 - *) gl_link_follows_symlinks=-1 ;; - esac + ]])], + [gl_cv_func_link_follows_symlink=no], dnl GNU behavior + [gl_cv_func_link_follows_symlink=yes], dnl Followed link/compile failed + [gl_cv_func_link_follows_symlink=unknown] dnl We're cross compiling. + ) + rm -f conftest.file conftest.sym conftest.hard + ]) + case $gl_cv_func_link_follows_symlink in + yes) gl_link_follows_symlinks=1 ;; + no) ;; # already defaulted to 0 + *) gl_link_follows_symlinks=-2 ;; + esac + fi fi AC_DEFINE_UNQUOTED([LINK_FOLLOWS_SYMLINKS], [$gl_link_follows_symlinks], [Define to 1 if `link(2)' dereferences symbolic links, 0 if it - creates hard links to symlinks, and -1 if unknown.]) + creates hard links to symlinks, -1 if it depends on the variable __xpg4, + and -2 if unknown.]) ]) -- cgit v1.2.1