test-framework-sh: Fix typo in function invocation (regression 2024-06-11).
[gnulib.git] / m4 / chown.m4
blob293d3f93fcc49354a2e0c110f8ac158b52c99d8c
1 # chown.m4
2 # serial 36
3 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2024 Free Software Foundation, Inc.
4 dnl This file is free software; the Free Software Foundation
5 dnl gives unlimited permission to copy and/or distribute it,
6 dnl with or without modifications, as long as this notice is preserved.
8 # Determine whether we need the chown wrapper.
10 # chown should accept arguments of -1 for uid and gid, and it should
11 # dereference symlinks.  If it doesn't, arrange to use the replacement
12 # function.
14 # From Jim Meyering.
16 # This is taken from the following Autoconf patch:
17 # https://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=7fbb553727ed7e0e689a17594b58559ecf3ea6e9
18 AC_DEFUN([AC_FUNC_CHOWN],
20   AC_REQUIRE([AC_TYPE_UID_T])dnl
21   AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
22   AC_CHECK_HEADERS([unistd.h])
23   AC_CACHE_CHECK([for working chown],
24     [ac_cv_func_chown_works],
25     [AC_RUN_IFELSE(
26        [AC_LANG_PROGRAM(
27           [AC_INCLUDES_DEFAULT
28            [#include <fcntl.h>
29           ]GL_MDA_DEFINES],
30           [[
31             char *f = "conftest.chown";
32             struct stat before, after;
34             if (creat (f, 0600) < 0)
35               return 1;
36             if (stat (f, &before) < 0)
37               return 1;
38             if (chown (f, (uid_t) -1, (gid_t) -1) == -1)
39               return 1;
40             if (stat (f, &after) < 0)
41               return 1;
42             return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid);
43           ]])
44        ],
45        [ac_cv_func_chown_works=yes],
46        [ac_cv_func_chown_works=no],
47        [case "$host_os" in # ((
48                              # Guess yes on Linux systems.
49           linux-* | linux)   ac_cv_func_chown_works="guessing yes" ;;
50                              # Guess yes on glibc systems.
51           *-gnu* | gnu*)     ac_cv_func_chown_works="guessing yes" ;;
52                              # Guess no on native Windows.
53           mingw* | windows*) ac_cv_func_chown_works="guessing no" ;;
54                              # If we don't know, obey --enable-cross-guesses.
55           *)                 ac_cv_func_chown_works="$gl_cross_guess_normal" ;;
56         esac
57        ])
58      rm -f conftest.chown
59     ])
60   case "$ac_cv_func_chown_works" in
61     *yes)
62       AC_DEFINE([HAVE_CHOWN], [1],
63         [Define to 1 if your system has a working `chown' function.])
64       ;;
65   esac
66 ])# AC_FUNC_CHOWN
68 AC_DEFUN_ONCE([gl_FUNC_CHOWN],
70   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
71   AC_REQUIRE([AC_TYPE_UID_T])
72   AC_REQUIRE([AC_FUNC_CHOWN])
73   AC_REQUIRE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK])
74   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
75   AC_CHECK_FUNCS_ONCE([chown fchown])
77   dnl mingw lacks chown altogether.
78   if test $ac_cv_func_chown = no; then
79     HAVE_CHOWN=0
80   else
81     dnl Some old systems treated chown like lchown.
82     case "$gl_cv_func_chown_follows_symlink" in
83       *yes) ;;
84       *) REPLACE_CHOWN=1 ;;
85     esac
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 ]GL_MDA_DEFINES],
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 ]GL_MDA_DEFINES],
141         [[struct stat st1, st2;
142           if (close (creat ("conftest.file", 0600))) return 1;
143           if (stat ("conftest.file", &st1)) return 2;
144           sleep (1);
145           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
146           if (stat ("conftest.file", &st2)) return 4;
147           if (st2.st_ctime <= st1.st_ctime) return 5;
148         ]])],
149         [gl_cv_func_chown_ctime_works=yes],
150         [gl_cv_func_chown_ctime_works=no],
151         [case "$host_os" in
152                     # Guess yes on glibc systems.
153            *-gnu*)  gl_cv_func_chown_ctime_works="guessing yes" ;;
154                     # Guess yes on musl systems.
155            *-musl*) gl_cv_func_chown_ctime_works="guessing yes" ;;
156                     # If we don't know, obey --enable-cross-guesses.
157            *)       gl_cv_func_chown_ctime_works="$gl_cross_guess_normal" ;;
158          esac
159         ])
160       rm -f conftest.file])
161     case "$gl_cv_func_chown_ctime_works" in
162       *yes) ;;
163       *)
164         AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
165           to change ctime when at least one argument was not -1.])
166         REPLACE_CHOWN=1
167         ;;
168     esac
169   fi
172 # Determine whether chown follows symlinks (it should).
173 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
175   AC_CACHE_CHECK(
176     [whether chown dereferences symlinks],
177     [gl_cv_func_chown_follows_symlink],
178     [
179       AC_RUN_IFELSE([AC_LANG_SOURCE([[
180 #include <unistd.h>
181 #include <stdlib.h>
182 #include <errno.h>
183 ]GL_MDA_DEFINES[
184         int
185         main ()
186         {
187           int result = 0;
188           char const *dangling_symlink = "conftest.dangle";
190           unlink (dangling_symlink);
191           if (symlink ("conftest.no-such", dangling_symlink))
192             abort ();
194           /* Exit successfully on a conforming system,
195              i.e., where chown must fail with ENOENT.  */
196           if (chown (dangling_symlink, getuid (), getgid ()) == 0)
197             result |= 1;
198           if (errno != ENOENT)
199             result |= 2;
200           return result;
201         }
202         ]])],
203         [gl_cv_func_chown_follows_symlink=yes],
204         [gl_cv_func_chown_follows_symlink=no],
205         [gl_cv_func_chown_follows_symlink="guessing yes"]
206       )
207     ]
208   )
210   case "$gl_cv_func_chown_follows_symlink" in
211     *yes) ;;
212     *)
213       AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
214         [Define if chown modifies symlinks.])
215       ;;
216   esac