libc-config: Fix __GNUC_PREREQ macro.
[gnulib.git] / m4 / chown.m4
blob588b6bae4e7b9824a9063da7ce3a6becd4c03fa0
1 # serial 28
2 # Determine whether we need the chown wrapper.
4 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2017 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 # http://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 glibc systems.
50           *-gnu*) ac_cv_func_chown_works="guessing yes" ;;
51                   # Guess no on native Windows.
52           mingw*) ac_cv_func_chown_works="guessing no" ;;
53                   # If we don't know, assume the worst.
54           *)      ac_cv_func_chown_works="guessing no" ;;
55         esac
56        ])
57      rm -f conftest.chown
58     ])
59   case "$ac_cv_func_chown_works" in
60     *yes)
61       AC_DEFINE([HAVE_CHOWN], [1],
62         [Define to 1 if your system has a working `chown' function.])
63       ;;
64   esac
65 ])# AC_FUNC_CHOWN
67 AC_DEFUN_ONCE([gl_FUNC_CHOWN],
69   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
70   AC_REQUIRE([AC_TYPE_UID_T])
71   AC_REQUIRE([AC_FUNC_CHOWN])
72   AC_REQUIRE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK])
73   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
74   AC_CHECK_FUNCS_ONCE([chown fchown])
76   dnl mingw lacks chown altogether.
77   if test $ac_cv_func_chown = no; then
78     HAVE_CHOWN=0
79   else
80     dnl Some old systems treated chown like lchown.
81     if test $gl_cv_func_chown_follows_symlink = no; then
82       REPLACE_CHOWN=1
83     fi
85     dnl Some old systems tried to use uid/gid -1 literally.
86     case "$ac_cv_func_chown_works" in
87       *no)
88         AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1],
89           [Define if chown is not POSIX compliant regarding IDs of -1.])
90         REPLACE_CHOWN=1
91         ;;
92     esac
94     dnl Solaris 9 ignores trailing slash.
95     dnl FreeBSD 7.2 mishandles trailing slash on symlinks.
96     dnl Likewise for AIX 7.1.
97     AC_CACHE_CHECK([whether chown honors trailing slash],
98       [gl_cv_func_chown_slash_works],
99       [touch conftest.file && rm -f conftest.link
100        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
101 #include <unistd.h>
102 #include <stdlib.h>
103 #include <errno.h>
104 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
105           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
106         ]])],
107         [gl_cv_func_chown_slash_works=yes],
108         [gl_cv_func_chown_slash_works=no],
109         [case "$host_os" in
110                    # Guess yes on glibc systems.
111            *-gnu*) gl_cv_func_chown_slash_works="guessing yes" ;;
112                    # If we don't know, assume the worst.
113            *)      gl_cv_func_chown_slash_works="guessing no" ;;
114          esac
115         ])
116       rm -f conftest.link conftest.file])
117     case "$gl_cv_func_chown_slash_works" in
118       *yes) ;;
119       *)
120         AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
121           [Define to 1 if chown mishandles trailing slash.])
122         REPLACE_CHOWN=1
123         ;;
124     esac
126     dnl OpenBSD fails to update ctime if ownership does not change.
127     AC_CACHE_CHECK([whether chown always updates ctime],
128       [gl_cv_func_chown_ctime_works],
129       [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
130 #include <unistd.h>
131 #include <stdlib.h>
132 #include <errno.h>
133 #include <fcntl.h>
134 #include <sys/stat.h>
135 ]], [[    struct stat st1, st2;
136           if (close (creat ("conftest.file", 0600))) return 1;
137           if (stat ("conftest.file", &st1)) return 2;
138           sleep (1);
139           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
140           if (stat ("conftest.file", &st2)) return 4;
141           if (st2.st_ctime <= st1.st_ctime) return 5;
142         ]])],
143         [gl_cv_func_chown_ctime_works=yes],
144         [gl_cv_func_chown_ctime_works=no],
145         [case "$host_os" in
146                    # Guess yes on glibc systems.
147            *-gnu*) gl_cv_func_chown_ctime_works="guessing yes" ;;
148                    # If we don't know, assume the worst.
149            *)      gl_cv_func_chown_ctime_works="guessing no" ;;
150          esac
151         ])
152       rm -f conftest.file])
153     case "$gl_cv_func_chown_ctime_works" in
154       *yes) ;;
155       *)
156         AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
157           to change ctime when at least one argument was not -1.])
158         REPLACE_CHOWN=1
159         ;;
160     esac
161   fi
164 # Determine whether chown follows symlinks (it should).
165 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
167   AC_CACHE_CHECK(
168     [whether chown dereferences symlinks],
169     [gl_cv_func_chown_follows_symlink],
170     [
171       AC_RUN_IFELSE([AC_LANG_SOURCE([[
172 #include <unistd.h>
173 #include <stdlib.h>
174 #include <errno.h>
176         int
177         main ()
178         {
179           int result = 0;
180           char const *dangling_symlink = "conftest.dangle";
182           unlink (dangling_symlink);
183           if (symlink ("conftest.no-such", dangling_symlink))
184             abort ();
186           /* Exit successfully on a conforming system,
187              i.e., where chown must fail with ENOENT.  */
188           if (chown (dangling_symlink, getuid (), getgid ()) == 0)
189             result |= 1;
190           if (errno != ENOENT)
191             result |= 2;
192           return result;
193         }
194         ]])],
195         [gl_cv_func_chown_follows_symlink=yes],
196         [gl_cv_func_chown_follows_symlink=no],
197         [gl_cv_func_chown_follows_symlink=yes]
198       )
199     ]
200   )
202   if test $gl_cv_func_chown_follows_symlink = no; then
203     AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
204       [Define if chown modifies symlinks.])
205   fi