havelib: Fix for Solaris 11 OpenIndiana and Solaris 11 OmniOS.
[gnulib.git] / m4 / linkat.m4
bloba4e61c332ae7f1e45d6a03a9c9366ade56438da0
1 # serial 14
2 # See if we need to provide linkat replacement.
4 dnl Copyright (C) 2009-2020 Free Software Foundation, Inc.
5 dnl This file is free software; the Free Software Foundation
6 dnl gives unlimited permission to copy and/or distribute it,
7 dnl with or without modifications, as long as this notice is preserved.
9 # Written by Eric Blake.
11 AC_DEFUN([gl_FUNC_LINKAT],
13   AC_REQUIRE([gl_FUNC_OPENAT])
14   AC_REQUIRE([gl_FUNC_LINK_FOLLOWS_SYMLINK])
15   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
16   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
17   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
18   AC_CHECK_FUNCS_ONCE([linkat symlink])
19   if test $ac_cv_func_linkat = no; then
20     HAVE_LINKAT=0
21   else
22     dnl OS X Yosemite has linkat() but it's not sufficient
23     dnl to our needs since it doesn't support creating
24     dnl hardlinks to symlinks.  Therefore check for that
25     dnl capability before considering using the system version.
26     AC_CACHE_CHECK([whether linkat() can link symlinks],
27       [gl_cv_func_linkat_nofollow],
28       [rm -rf conftest.l1 conftest.l2
29        ln -s target conftest.l1
30        AC_RUN_IFELSE([AC_LANG_PROGRAM(
31                         [[#include <fcntl.h>
32                           #include <unistd.h>
33                         ]],
34                         [[return linkat (AT_FDCWD, "conftest.l1", AT_FDCWD,
35                                          "conftest.l2", 0);
36                         ]])],
37          [gl_cv_func_linkat_nofollow=yes],
38          [gl_cv_func_linkat_nofollow=no],
39          [case "$host_os" in
40            darwin*) gl_cv_func_linkat_nofollow="guessing no" ;;
41            *)       gl_cv_func_linkat_nofollow="guessing yes" ;;
42           esac])
44        rm -rf conftest.l1 conftest.l2])
46     case $gl_cv_func_linkat_nofollow in
47       *no) LINKAT_SYMLINK_NOTSUP=1 ;;
48       *yes) LINKAT_SYMLINK_NOTSUP=0 ;;
49     esac
51     AC_CACHE_CHECK([whether linkat handles trailing slash correctly],
52       [gl_cv_func_linkat_slash],
53       [rm -rf conftest.a conftest.b conftest.c conftest.d conftest.e conftest.s
54        AC_RUN_IFELSE(
55          [AC_LANG_PROGRAM(
56             [[#include <unistd.h>
57               #include <fcntl.h>
58               #include <errno.h>
59               #include <stdio.h>
60             ]GL_MDA_DEFINES],
61             [[int result;
62               int fd;
63               /* Create a regular file.  */
64               fd = open ("conftest.a", O_CREAT | O_EXCL | O_WRONLY, 0600);
65               if (fd < 0)
66                 return 1;
67               if (write (fd, "hello", 5) < 5)
68                 return 2;
69               if (close (fd) < 0)
70                 return 3;
71               /* Test whether hard links are supported on the current
72                  device.  */
73               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.b",
74                           AT_SYMLINK_FOLLOW) < 0)
75                 return 0;
76               result = 0;
77               /* Test whether a trailing "/" is treated like "/.".  */
78               if (linkat (AT_FDCWD, "conftest.a/", AT_FDCWD, "conftest.c",
79                           AT_SYMLINK_FOLLOW) == 0)
80                 result |= 4;
81               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.d/",
82                           AT_SYMLINK_FOLLOW) == 0)
83                 result |= 8;
85               /* On Mac OS X 10.13 a trailing "/" will cause the second path to be
86                  dereferenced, and thus will succeed on a dangling symlink.  */
87               if (symlink ("conftest.e", "conftest.s") == 0)
88                 {
89                   if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.s/",
90                       AT_SYMLINK_FOLLOW) == 0)
91                     result |= 16;
92                 }
94               return result;
95             ]])],
96          [gl_cv_func_linkat_slash=yes],
97          [gl_cv_func_linkat_slash=no],
98          [
99           case "$host_os" in
100                              # Guess yes on Linux systems.
101             linux-* | linux) gl_cv_func_linkat_slash="guessing yes";;
102                              # Guess yes on glibc systems.
103             *-gnu* | gnu*)   gl_cv_func_linkat_slash="guessing yes";;
104                              # If we don't know, obey --enable-cross-guesses.
105             *)               gl_cv_func_linkat_slash="$gl_cross_guess_normal";;
106           esac
107          ])
108        rm -rf conftest.a conftest.b conftest.c conftest.d conftest.e conftest.s])
109     case "$gl_cv_func_linkat_slash" in
110       *yes) gl_linkat_slash_bug=0 ;;
111       *)    gl_linkat_slash_bug=1 ;;
112     esac
114     case "$gl_cv_func_linkat_nofollow" in
115       *yes) linkat_nofollow=yes ;;
116       *) linkat_nofollow=no ;;
117     esac
119     if test "$linkat_nofollow" != yes \
120        || test $gl_linkat_slash_bug = 1; then
121       REPLACE_LINKAT=1
122       AC_DEFINE_UNQUOTED([LINKAT_TRAILING_SLASH_BUG], [$gl_linkat_slash_bug],
123         [Define to 1 if linkat fails to recognize a trailing slash.])
124       AC_DEFINE_UNQUOTED([LINKAT_SYMLINK_NOTSUP], [$LINKAT_SYMLINK_NOTSUP],
125         [Define to 1 if linkat can create hardlinks to symlinks])
126     fi
127   fi