Import upstream version 1.29
[debian/tar] / m4 / linkat.m4
index 2da0e30cb1d4154244a3dd748a7023ee862c23fb..9ed082db971fdfe61030fb9bca3ce2cdbaef2b55 100644 (file)
@@ -1,7 +1,7 @@
-# serial 6
+# serial 7
 # See if we need to provide linkat replacement.
 
-dnl Copyright (C) 2009-2014 Free Software Foundation, Inc.
+dnl Copyright (C) 2009-2015 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -20,26 +20,38 @@ AC_DEFUN([gl_FUNC_LINKAT],
   if test $ac_cv_func_linkat = no; then
     HAVE_LINKAT=0
   else
-    AC_CACHE_CHECK([whether linkat(,AT_SYMLINK_FOLLOW) works],
-      [gl_cv_func_linkat_follow],
-      [rm -rf conftest.f1 conftest.f2
-       touch conftest.f1
-       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <fcntl.h>
-#include <unistd.h>
-#ifdef __linux__
-/* Linux added linkat in 2.6.16, but did not add AT_SYMLINK_FOLLOW
-   until 2.6.18.  Always replace linkat to support older kernels.  */
-choke me
-#endif
-]], [return linkat (AT_FDCWD, "conftest.f1", AT_FDCWD, "conftest.f2",
-                    AT_SYMLINK_FOLLOW);])],
-         [gl_cv_func_linkat_follow=yes],
-         [gl_cv_func_linkat_follow="need runtime check"])
-       rm -rf conftest.f1 conftest.f2])
+    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],
+         [gl_cv_func_linkat_nofollow=no],
+         [case "$host_os" in
+           darwin*) gl_cv_func_linkat_nofollow="guessing no" ;;
+           *)       gl_cv_func_linkat_nofollow="guessing yes" ;;
+          esac])
+
+       rm -rf conftest.l1 conftest.l2])
+
+    case $gl_cv_func_linkat_nofollow in
+      *no) LINKAT_SYMLINK_NOTSUP=1 ;;
+      *yes) LINKAT_SYMLINK_NOTSUP=0 ;;
+    esac
+
     AC_CACHE_CHECK([whether linkat handles trailing slash correctly],
       [gl_cv_func_linkat_slash],
-      [rm -rf conftest.a conftest.b conftest.c conftest.d
+      [rm -rf conftest.a conftest.b conftest.c conftest.d conftest.e conftest.s
        AC_RUN_IFELSE(
          [AC_LANG_PROGRAM(
             [[#include <unistd.h>
@@ -70,6 +82,16 @@ choke me
               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.d/",
                           AT_SYMLINK_FOLLOW) == 0)
                 result |= 8;
+
+              /* On OS X 10.10 a trailing "/" will cause the second path to be
+                 dereferenced, and thus will succeed on a dangling symlink.  */
+              if (symlink ("conftest.e", "conftest.s") == 0)
+                {
+                  if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.s/",
+                      AT_SYMLINK_FOLLOW) == 0)
+                    result |= 16;
+                }
+
               return result;
             ]])],
          [gl_cv_func_linkat_slash=yes],
@@ -80,16 +102,24 @@ choke me
             *)      gl_cv_func_linkat_slash="guessing no";;
           esac
          ])
-       rm -rf conftest.a conftest.b conftest.c conftest.d])
+       rm -rf conftest.a conftest.b conftest.c conftest.d conftest.e conftest.s])
     case "$gl_cv_func_linkat_slash" in
       *yes) gl_linkat_slash_bug=0 ;;
       *)    gl_linkat_slash_bug=1 ;;
     esac
-    if test "$gl_cv_func_linkat_follow" != yes \
+
+    case "$gl_cv_func_linkat_nofollow" in
+      *yes) linkat_nofollow=yes ;;
+      *) linkat_nofollow=no ;;
+    esac
+
+    if test "$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
 ])