glob-h: Add tests.
[gnulib.git] / m4 / chown.m4
blob600ee934d188b6b1f26c2587211da424568a50b2
1 # serial 30
2 # Determine whether we need the chown wrapper.
4 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2018 Free Software
5 dnl Foundation, Inc.
7 dnl This file is free software; the Free Software Foundation
8 dnl gives unlimited permission to copy and/or distribute it,
9 dnl with or without modifications, as long as this notice is preserved.
11 # chown should accept arguments of -1 for uid and gid, and it should
12 # dereference symlinks.  If it doesn't, arrange to use the replacement
13 # function.
15 # From Jim Meyering.
17 # This is taken from the following Autoconf patch:
18 # https://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=7fbb553727ed7e0e689a17594b58559ecf3ea6e9
19 AC_DEFUN([AC_FUNC_CHOWN],
21   AC_REQUIRE([AC_TYPE_UID_T])dnl
22   AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
23   AC_CHECK_HEADERS([unistd.h])
24   AC_CACHE_CHECK([for working chown],
25     [ac_cv_func_chown_works],
26     [AC_RUN_IFELSE(
27        [AC_LANG_PROGRAM(
28           [AC_INCLUDES_DEFAULT
29            [#include <fcntl.h>
30           ]],
31           [[
32             char *f = "conftest.chown";
33             struct stat before, after;
35             if (creat (f, 0600) < 0)
36               return 1;
37             if (stat (f, &before) < 0)
38               return 1;
39             if (chown (f, (uid_t) -1, (gid_t) -1) == -1)
40               return 1;
41             if (stat (f, &after) < 0)
42               return 1;
43             return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid);
44           ]])
45        ],
46        [ac_cv_func_chown_works=yes],
47        [ac_cv_func_chown_works=no],
48        [case "$host_os" in # ((
49                            # Guess yes on Linux systems.
50           linux-* | linux) ac_cv_func_chown_works="guessing yes" ;;
51                            # Guess yes on glibc systems.
52           *-gnu* | gnu*)   ac_cv_func_chown_works="guessing yes" ;;
53                            # Guess no on native Windows.
54           mingw*)          ac_cv_func_chown_works="guessing no" ;;
55                            # If we don't know, assume the worst.
56           *)               ac_cv_func_chown_works="guessing no" ;;
57         esac
58        ])
59      rm -f conftest.chown
60     ])
61   case "$ac_cv_func_chown_works" in
62     *yes)
63       AC_DEFINE([HAVE_CHOWN], [1],
64         [Define to 1 if your system has a working `chown' function.])
65       ;;
66   esac
67 ])# AC_FUNC_CHOWN
69 AC_DEFUN_ONCE([gl_FUNC_CHOWN],
71   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
72   AC_REQUIRE([AC_TYPE_UID_T])
73   AC_REQUIRE([AC_FUNC_CHOWN])
74   AC_REQUIRE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK])
75   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
76   AC_CHECK_FUNCS_ONCE([chown fchown])
78   dnl mingw lacks chown altogether.
79   if test $ac_cv_func_chown = no; then
80     HAVE_CHOWN=0
81   else
82     dnl Some old systems treated chown like lchown.
83     if test $gl_cv_func_chown_follows_symlink = no; then
84       REPLACE_CHOWN=1
85     fi
87     dnl Some old systems tried to use uid/gid -1 literally.
88     case "$ac_cv_func_chown_works" in
89       *no)
90         AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1],
91           [Define if chown is not POSIX compliant regarding IDs of -1.])
92         REPLACE_CHOWN=1
93         ;;
94     esac
96     dnl Solaris 9 ignores trailing slash.
97     dnl FreeBSD 7.2 mishandles trailing slash on symlinks.
98     dnl Likewise for AIX 7.1.
99     AC_CACHE_CHECK([whether chown honors trailing slash],
100       [gl_cv_func_chown_slash_works],
101       [touch conftest.file && rm -f conftest.link
102        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
103 #include <unistd.h>
104 #include <stdlib.h>
105 #include <errno.h>
106 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
107           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
108         ]])],
109         [gl_cv_func_chown_slash_works=yes],
110         [gl_cv_func_chown_slash_works=no],
111         [case "$host_os" in
112                    # Guess yes on glibc systems.
113            *-gnu*) gl_cv_func_chown_slash_works="guessing yes" ;;
114                    # If we don't know, assume the worst.
115            *)      gl_cv_func_chown_slash_works="guessing no" ;;
116          esac
117         ])
118       rm -f conftest.link conftest.file])
119     case "$gl_cv_func_chown_slash_works" in
120       *yes) ;;
121       *)
122         AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
123           [Define to 1 if chown mishandles trailing slash.])
124         REPLACE_CHOWN=1
125         ;;
126     esac
128     dnl OpenBSD fails to update ctime if ownership does not change.
129     AC_CACHE_CHECK([whether chown always updates ctime],
130       [gl_cv_func_chown_ctime_works],
131       [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
132 #include <unistd.h>
133 #include <stdlib.h>
134 #include <errno.h>
135 #include <fcntl.h>
136 #include <sys/stat.h>
137 ]], [[    struct stat st1, st2;
138           if (close (creat ("conftest.file", 0600))) return 1;
139           if (stat ("conftest.file", &st1)) return 2;
140           sleep (1);
141           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
142           if (stat ("conftest.file", &st2)) return 4;
143           if (st2.st_ctime <= st1.st_ctime) return 5;
144         ]])],
145         [gl_cv_func_chown_ctime_works=yes],
146         [gl_cv_func_chown_ctime_works=no],
147         [case "$host_os" in
148                    # Guess yes on glibc systems.
149            *-gnu*) gl_cv_func_chown_ctime_works="guessing yes" ;;
150                    # If we don't know, assume the worst.
151            *)      gl_cv_func_chown_ctime_works="guessing no" ;;
152          esac
153         ])
154       rm -f conftest.file])
155     case "$gl_cv_func_chown_ctime_works" in
156       *yes) ;;
157       *)
158         AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
159           to change ctime when at least one argument was not -1.])
160         REPLACE_CHOWN=1
161         ;;
162     esac
163   fi
166 # Determine whether chown follows symlinks (it should).
167 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
169   AC_CACHE_CHECK(
170     [whether chown dereferences symlinks],
171     [gl_cv_func_chown_follows_symlink],
172     [
173       AC_RUN_IFELSE([AC_LANG_SOURCE([[
174 #include <unistd.h>
175 #include <stdlib.h>
176 #include <errno.h>
178         int
179         main ()
180         {
181           int result = 0;
182           char const *dangling_symlink = "conftest.dangle";
184           unlink (dangling_symlink);
185           if (symlink ("conftest.no-such", dangling_symlink))
186             abort ();
188           /* Exit successfully on a conforming system,
189              i.e., where chown must fail with ENOENT.  */
190           if (chown (dangling_symlink, getuid (), getgid ()) == 0)
191             result |= 1;
192           if (errno != ENOENT)
193             result |= 2;
194           return result;
195         }
196         ]])],
197         [gl_cv_func_chown_follows_symlink=yes],
198         [gl_cv_func_chown_follows_symlink=no],
199         [gl_cv_func_chown_follows_symlink=yes]
200       )
201     ]
202   )
204   if test $gl_cv_func_chown_follows_symlink = no; then
205     AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
206       [Define if chown modifies symlinks.])
207   fi