findprog, relocatable-prog: Ignore directories during PATH search.
[gnulib.git] / m4 / chown.m4
blob3638187aac20e743bd8c6202b5764a7d3350180e
1 # serial 34
2 # Determine whether we need the chown wrapper.
4 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2020 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, obey --enable-cross-guesses.
56           *)               ac_cv_func_chown_works="$gl_cross_guess_normal" ;;
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     case "$gl_cv_func_chown_follows_symlink" in
84       *yes) ;;
85       *) REPLACE_CHOWN=1 ;;
86     esac
88     dnl Some old systems tried to use uid/gid -1 literally.
89     case "$ac_cv_func_chown_works" in
90       *no)
91         AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1],
92           [Define if chown is not POSIX compliant regarding IDs of -1.])
93         REPLACE_CHOWN=1
94         ;;
95     esac
97     dnl Solaris 9 ignores trailing slash.
98     dnl FreeBSD 7.2 mishandles trailing slash on symlinks.
99     dnl Likewise for AIX 7.1.
100     AC_CACHE_CHECK([whether chown honors trailing slash],
101       [gl_cv_func_chown_slash_works],
102       [touch conftest.file && rm -f conftest.link
103        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
104 #include <unistd.h>
105 #include <stdlib.h>
106 #include <errno.h>
107 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
108           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
109         ]])],
110         [gl_cv_func_chown_slash_works=yes],
111         [gl_cv_func_chown_slash_works=no],
112         [case "$host_os" in
113                     # Guess yes on glibc systems.
114            *-gnu*)  gl_cv_func_chown_slash_works="guessing yes" ;;
115                     # Guess yes on musl systems.
116            *-musl*) gl_cv_func_chown_slash_works="guessing yes" ;;
117                     # If we don't know, obey --enable-cross-guesses.
118            *)       gl_cv_func_chown_slash_works="$gl_cross_guess_normal" ;;
119          esac
120         ])
121       rm -f conftest.link conftest.file])
122     case "$gl_cv_func_chown_slash_works" in
123       *yes) ;;
124       *)
125         AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
126           [Define to 1 if chown mishandles trailing slash.])
127         REPLACE_CHOWN=1
128         ;;
129     esac
131     dnl OpenBSD fails to update ctime if ownership does not change.
132     AC_CACHE_CHECK([whether chown always updates ctime],
133       [gl_cv_func_chown_ctime_works],
134       [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
135 #include <unistd.h>
136 #include <stdlib.h>
137 #include <errno.h>
138 #include <fcntl.h>
139 #include <sys/stat.h>
140 ]], [[    struct stat st1, st2;
141           if (close (creat ("conftest.file", 0600))) return 1;
142           if (stat ("conftest.file", &st1)) return 2;
143           sleep (1);
144           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
145           if (stat ("conftest.file", &st2)) return 4;
146           if (st2.st_ctime <= st1.st_ctime) return 5;
147         ]])],
148         [gl_cv_func_chown_ctime_works=yes],
149         [gl_cv_func_chown_ctime_works=no],
150         [case "$host_os" in
151                     # Guess yes on glibc systems.
152            *-gnu*)  gl_cv_func_chown_ctime_works="guessing yes" ;;
153                     # Guess yes on musl systems.
154            *-musl*) gl_cv_func_chown_ctime_works="guessing yes" ;;
155                     # If we don't know, obey --enable-cross-guesses.
156            *)       gl_cv_func_chown_ctime_works="$gl_cross_guess_normal" ;;
157          esac
158         ])
159       rm -f conftest.file])
160     case "$gl_cv_func_chown_ctime_works" in
161       *yes) ;;
162       *)
163         AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
164           to change ctime when at least one argument was not -1.])
165         REPLACE_CHOWN=1
166         ;;
167     esac
168   fi
171 # Determine whether chown follows symlinks (it should).
172 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
174   AC_CACHE_CHECK(
175     [whether chown dereferences symlinks],
176     [gl_cv_func_chown_follows_symlink],
177     [
178       AC_RUN_IFELSE([AC_LANG_SOURCE([[
179 #include <unistd.h>
180 #include <stdlib.h>
181 #include <errno.h>
183         int
184         main ()
185         {
186           int result = 0;
187           char const *dangling_symlink = "conftest.dangle";
189           unlink (dangling_symlink);
190           if (symlink ("conftest.no-such", dangling_symlink))
191             abort ();
193           /* Exit successfully on a conforming system,
194              i.e., where chown must fail with ENOENT.  */
195           if (chown (dangling_symlink, getuid (), getgid ()) == 0)
196             result |= 1;
197           if (errno != ENOENT)
198             result |= 2;
199           return result;
200         }
201         ]])],
202         [gl_cv_func_chown_follows_symlink=yes],
203         [gl_cv_func_chown_follows_symlink=no],
204         [gl_cv_func_chown_follows_symlink="guessing yes"]
205       )
206     ]
207   )
209   case "$gl_cv_func_chown_follows_symlink" in
210     *yes) ;;
211     *)
212       AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
213         [Define if chown modifies symlinks.])
214       ;;
215   esac