affb11455586a8c834c72ce11db1bc4518bea828
[gnulib.git] / m4 / openat.m4
1 # serial 33
2 # See if we need to use our replacement for Solaris' openat et al functions.
3
4 dnl Copyright (C) 2004-2011 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 Jim Meyering.
10
11 AC_DEFUN([gl_FUNC_OPENAT],
12 [
13   AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
14   GNULIB_OPENAT=1
15
16   AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
17   GNULIB_FCHMODAT=1
18   GNULIB_FSTATAT=1
19   GNULIB_MKDIRAT=1
20
21   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
22   GNULIB_FCHOWNAT=1
23   GNULIB_UNLINKAT=1
24
25   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
26   AC_CHECK_FUNCS_ONCE([lchmod])
27   AC_CHECK_FUNCS([fchmodat fstatat mkdirat openat unlinkat])
28   AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK])
29   AC_REQUIRE([gl_FUNC_UNLINK])
30   case $ac_cv_func_openat+$gl_cv_func_lstat_dereferences_slashed_symlink in
31   yes+yes)
32     # GNU/Hurd has unlinkat, but it has the same bug as unlink.
33     if test $REPLACE_UNLINK = 1; then
34       REPLACE_UNLINKAT=1
35     fi ;;
36   yes+*)
37     # Solaris 9 has *at functions, but uniformly mishandles trailing
38     # slash in all of them.
39     REPLACE_OPENAT=1
40     REPLACE_FSTATAT=1
41     REPLACE_UNLINKAT=1
42     ;;
43   *)
44     HAVE_OPENAT=0
45     HAVE_UNLINKAT=0 # No known system with unlinkat but not openat
46     HAVE_FSTATAT=0 # No known system with fstatat but not openat
47     gl_PREREQ_OPENAT;;
48   esac
49   if test $ac_cv_func_fchmodat != yes; then
50     HAVE_FCHMODAT=0
51   fi
52   if test $ac_cv_func_mkdirat != yes; then
53     HAVE_MKDIRAT=0
54   fi
55   gl_FUNC_FCHOWNAT
56 ])
57
58 # gl_FUNC_FCHOWNAT_DEREF_BUG([ACTION-IF-BUGGY[, ACTION-IF-NOT_BUGGY]])
59 AC_DEFUN([gl_FUNC_FCHOWNAT_DEREF_BUG],
60 [
61   dnl Persuade glibc's <unistd.h> to declare fchownat().
62   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
63
64   AC_CACHE_CHECK([whether fchownat works with AT_SYMLINK_NOFOLLOW],
65     gl_cv_func_fchownat_nofollow_works,
66     [
67      gl_dangle=conftest.dangle
68      # Remove any remnants of a previous test.
69      rm -f $gl_dangle
70      # Arrange for deletion of the temporary file this test creates.
71      ac_clean_files="$ac_clean_files $gl_dangle"
72      ln -s conftest.no-such $gl_dangle
73      AC_RUN_IFELSE(
74        [AC_LANG_SOURCE(
75           [[
76 #include <fcntl.h>
77 #include <unistd.h>
78 #include <stdlib.h>
79 #include <errno.h>
80 #include <sys/types.h>
81 int
82 main ()
83 {
84   return (fchownat (AT_FDCWD, "$gl_dangle", -1, getgid (),
85                     AT_SYMLINK_NOFOLLOW) != 0
86           && errno == ENOENT);
87 }
88           ]])],
89     [gl_cv_func_fchownat_nofollow_works=yes],
90     [gl_cv_func_fchownat_nofollow_works=no],
91     [gl_cv_func_fchownat_nofollow_works=no],
92     )
93   ])
94   AS_IF([test $gl_cv_func_fchownat_nofollow_works = no], [$1], [$2])
95 ])
96
97 # gl_FUNC_FCHOWNAT_EMPTY_FILENAME_BUG([ACTION-IF-BUGGY[, ACTION-IF-NOT_BUGGY]])
98 AC_DEFUN([gl_FUNC_FCHOWNAT_EMPTY_FILENAME_BUG],
99 [
100   dnl Persuade glibc's <unistd.h> to declare fchownat().
101   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
102
103   AC_CACHE_CHECK([whether fchownat works with an empty file name],
104     [gl_cv_func_fchownat_empty_filename_works],
105     [AC_RUN_IFELSE(
106        [AC_LANG_PROGRAM(
107           [[#include <unistd.h>
108             #include <fcntl.h>
109           ]],
110           [[int fd;
111             int ret;
112             if (mkdir ("conftestdir", 0700) < 0)
113               return 2;
114             fd = open ("conftestdir", O_RDONLY);
115             if (fd < 0)
116               return 3;
117             ret = fchownat (fd, "", -1, -1, 0);
118             close (fd);
119             rmdir ("conftestdir");
120             return ret == 0;
121           ]])],
122        [gl_cv_func_fchownat_empty_filename_works=yes],
123        [gl_cv_func_fchownat_empty_filename_works=no],
124        [gl_cv_func_fchownat_empty_filename_works="guessing no"])
125     ])
126   AS_IF([test "$gl_cv_func_fchownat_empty_filename_works" != yes], [$1], [$2])
127 ])
128
129 # If we have the fchownat function, and it has the bug (in glibc-2.4)
130 # that it dereferences symlinks even with AT_SYMLINK_NOFOLLOW, then
131 # use the replacement function.
132 # Also if the fchownat function, like chown, has the trailing slash bug,
133 # use the replacement function.
134 # Also use the replacement function if fchownat is simply not available.
135 AC_DEFUN([gl_FUNC_FCHOWNAT],
136 [
137   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
138   AC_REQUIRE([gl_FUNC_CHOWN])
139   AC_CHECK_FUNC([fchownat],
140     [gl_FUNC_FCHOWNAT_DEREF_BUG(
141        [REPLACE_FCHOWNAT=1
142         AC_DEFINE([FCHOWNAT_NOFOLLOW_BUG], [1],
143                   [Define to 1 if your platform has fchownat, but it cannot
144                    perform lchown tasks.])
145        ])
146      gl_FUNC_FCHOWNAT_EMPTY_FILENAME_BUG(
147        [REPLACE_FCHOWNAT=1
148         AC_DEFINE([FCHOWNAT_EMPTY_FILENAME_BUG], [1],
149                   [Define to 1 if your platform has fchownat, but it does
150                    not reject an empty file name.])
151        ])
152      if test $REPLACE_CHOWN = 1; then
153        REPLACE_FCHOWNAT=1
154      fi],
155     [HAVE_FCHOWNAT=0])
156 ])
157
158 AC_DEFUN([gl_PREREQ_OPENAT],
159 [
160   AC_REQUIRE([AC_C_INLINE])
161   AC_REQUIRE([gl_PROMOTED_TYPE_MODE_T])
162   :
163 ])