Do the Windows oldnames workaround through the C++ GNULIB_NAMESPACE.
[gnulib.git] / m4 / linkat.m4
blobe9b3d8266c66e30f091f21c11122b33a2892968e
1 # serial 13
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   AC_CHECK_HEADERS_ONCE([sys/param.h])
20   if test $ac_cv_func_linkat = no; then
21     HAVE_LINKAT=0
22   else
23     dnl OS X Yosemite has linkat() but it's not sufficient
24     dnl to our needs since it doesn't support creating
25     dnl hardlinks to symlinks.  Therefore check for that
26     dnl capability before considering using the system version.
27     AC_CACHE_CHECK([whether linkat() can link symlinks],
28       [gl_cv_func_linkat_nofollow],
29       [rm -rf conftest.l1 conftest.l2
30        ln -s target conftest.l1
31        AC_RUN_IFELSE([AC_LANG_PROGRAM(
32                         [[#include <fcntl.h>
33                           #include <unistd.h>
34                         ]],
35                         [[return linkat (AT_FDCWD, "conftest.l1", AT_FDCWD,
36                                          "conftest.l2", 0);
37                         ]])],
38          [gl_cv_func_linkat_nofollow=yes],
39          [gl_cv_func_linkat_nofollow=no],
40          [case "$host_os" in
41            darwin*) gl_cv_func_linkat_nofollow="guessing no" ;;
42            *)       gl_cv_func_linkat_nofollow="guessing yes" ;;
43           esac])
45        rm -rf conftest.l1 conftest.l2])
47     case $gl_cv_func_linkat_nofollow in
48       *no) LINKAT_SYMLINK_NOTSUP=1 ;;
49       *yes) LINKAT_SYMLINK_NOTSUP=0 ;;
50     esac
52     AC_CACHE_CHECK([whether linkat handles trailing slash correctly],
53       [gl_cv_func_linkat_slash],
54       [rm -rf conftest.a conftest.b conftest.c conftest.d conftest.e conftest.s
55        AC_RUN_IFELSE(
56          [AC_LANG_PROGRAM(
57             [[#include <unistd.h>
58               #include <fcntl.h>
59               #include <errno.h>
60               #include <stdio.h>
61             ]GL_MDA_DEFINES],
62             [[int result;
63               int fd;
64               /* Create a regular file.  */
65               fd = open ("conftest.a", O_CREAT | O_EXCL | O_WRONLY, 0600);
66               if (fd < 0)
67                 return 1;
68               if (write (fd, "hello", 5) < 5)
69                 return 2;
70               if (close (fd) < 0)
71                 return 3;
72               /* Test whether hard links are supported on the current
73                  device.  */
74               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.b",
75                           AT_SYMLINK_FOLLOW) < 0)
76                 return 0;
77               result = 0;
78               /* Test whether a trailing "/" is treated like "/.".  */
79               if (linkat (AT_FDCWD, "conftest.a/", AT_FDCWD, "conftest.c",
80                           AT_SYMLINK_FOLLOW) == 0)
81                 result |= 4;
82               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.d/",
83                           AT_SYMLINK_FOLLOW) == 0)
84                 result |= 8;
86               /* On Mac OS X 10.13 a trailing "/" will cause the second path to be
87                  dereferenced, and thus will succeed on a dangling symlink.  */
88               if (symlink ("conftest.e", "conftest.s") == 0)
89                 {
90                   if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.s/",
91                       AT_SYMLINK_FOLLOW) == 0)
92                     result |= 16;
93                 }
95               return result;
96             ]])],
97          [gl_cv_func_linkat_slash=yes],
98          [gl_cv_func_linkat_slash=no],
99          [
100           case "$host_os" in
101                              # Guess yes on Linux systems.
102             linux-* | linux) gl_cv_func_linkat_slash="guessing yes";;
103                              # Guess yes on glibc systems.
104             *-gnu* | gnu*)   gl_cv_func_linkat_slash="guessing yes";;
105                              # If we don't know, obey --enable-cross-guesses.
106             *)               gl_cv_func_linkat_slash="$gl_cross_guess_normal";;
107           esac
108          ])
109        rm -rf conftest.a conftest.b conftest.c conftest.d conftest.e conftest.s])
110     case "$gl_cv_func_linkat_slash" in
111       *yes) gl_linkat_slash_bug=0 ;;
112       *)    gl_linkat_slash_bug=1 ;;
113     esac
115     case "$gl_cv_func_linkat_nofollow" in
116       *yes) linkat_nofollow=yes ;;
117       *) linkat_nofollow=no ;;
118     esac
120     if test "$linkat_nofollow" != yes \
121        || test $gl_linkat_slash_bug = 1; then
122       REPLACE_LINKAT=1
123       AC_DEFINE_UNQUOTED([LINKAT_TRAILING_SLASH_BUG], [$gl_linkat_slash_bug],
124         [Define to 1 if linkat fails to recognize a trailing slash.])
125       AC_DEFINE_UNQUOTED([LINKAT_SYMLINK_NOTSUP], [$LINKAT_SYMLINK_NOTSUP],
126         [Define to 1 if linkat can create hardlinks to symlinks])
127     fi
128   fi