maint: update copyright
[gnulib.git] / m4 / linkat.m4
1 # serial 6
2 # See if we need to provide linkat replacement.
3
4 dnl Copyright (C) 2009-2014 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.
8
9 # Written by Eric Blake.
10
11 AC_DEFUN([gl_FUNC_LINKAT],
12 [
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     AC_CACHE_CHECK([whether linkat(,AT_SYMLINK_FOLLOW) works],
24       [gl_cv_func_linkat_follow],
25       [rm -rf conftest.f1 conftest.f2
26        touch conftest.f1
27        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
28 #include <fcntl.h>
29 #include <unistd.h>
30 #ifdef __linux__
31 /* Linux added linkat in 2.6.16, but did not add AT_SYMLINK_FOLLOW
32    until 2.6.18.  Always replace linkat to support older kernels.  */
33 choke me
34 #endif
35 ]], [return linkat (AT_FDCWD, "conftest.f1", AT_FDCWD, "conftest.f2",
36                     AT_SYMLINK_FOLLOW);])],
37          [gl_cv_func_linkat_follow=yes],
38          [gl_cv_func_linkat_follow="need runtime check"])
39        rm -rf conftest.f1 conftest.f2])
40     AC_CACHE_CHECK([whether linkat handles trailing slash correctly],
41       [gl_cv_func_linkat_slash],
42       [rm -rf conftest.a conftest.b conftest.c conftest.d
43        AC_RUN_IFELSE(
44          [AC_LANG_PROGRAM(
45             [[#include <unistd.h>
46               #include <fcntl.h>
47               #include <errno.h>
48               #include <stdio.h>
49             ]],
50             [[int result;
51               int fd;
52               /* Create a regular file.  */
53               fd = open ("conftest.a", O_CREAT | O_EXCL | O_WRONLY, 0600);
54               if (fd < 0)
55                 return 1;
56               if (write (fd, "hello", 5) < 5)
57                 return 2;
58               if (close (fd) < 0)
59                 return 3;
60               /* Test whether hard links are supported on the current
61                  device.  */
62               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.b",
63                           AT_SYMLINK_FOLLOW) < 0)
64                 return 0;
65               result = 0;
66               /* Test whether a trailing "/" is treated like "/.".  */
67               if (linkat (AT_FDCWD, "conftest.a/", AT_FDCWD, "conftest.c",
68                           AT_SYMLINK_FOLLOW) == 0)
69                 result |= 4;
70               if (linkat (AT_FDCWD, "conftest.a", AT_FDCWD, "conftest.d/",
71                           AT_SYMLINK_FOLLOW) == 0)
72                 result |= 8;
73               return result;
74             ]])],
75          [gl_cv_func_linkat_slash=yes],
76          [gl_cv_func_linkat_slash=no],
77          [# Guess yes on glibc systems, no otherwise.
78           case "$host_os" in
79             *-gnu*) gl_cv_func_linkat_slash="guessing yes";;
80             *)      gl_cv_func_linkat_slash="guessing no";;
81           esac
82          ])
83        rm -rf conftest.a conftest.b conftest.c conftest.d])
84     case "$gl_cv_func_linkat_slash" in
85       *yes) gl_linkat_slash_bug=0 ;;
86       *)    gl_linkat_slash_bug=1 ;;
87     esac
88     if test "$gl_cv_func_linkat_follow" != yes \
89        || test $gl_linkat_slash_bug = 1; then
90       REPLACE_LINKAT=1
91       AC_DEFINE_UNQUOTED([LINKAT_TRAILING_SLASH_BUG], [$gl_linkat_slash_bug],
92         [Define to 1 if linkat fails to recognize a trailing slash.])
93     fi
94   fi
95 ])