bb7b29598ece7ecdaa6192c11b406c551a1e545a
[gnulib.git] / m4 / chown.m4
1 # serial 26
2 # Determine whether we need the chown wrapper.
3
4 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2012 Free Software
5 dnl Foundation, Inc.
6
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.
10
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.
14
15 # From Jim Meyering.
16
17 AC_DEFUN_ONCE([gl_FUNC_CHOWN],
18 [
19   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
20   AC_REQUIRE([AC_TYPE_UID_T])
21   AC_REQUIRE([AC_FUNC_CHOWN])
22   AC_REQUIRE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK])
23   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
24   AC_CHECK_FUNCS_ONCE([chown fchown])
25
26   dnl mingw lacks chown altogether.
27   if test $ac_cv_func_chown = no; then
28     HAVE_CHOWN=0
29   else
30     dnl Some old systems treated chown like lchown.
31     if test $gl_cv_func_chown_follows_symlink = no; then
32       REPLACE_CHOWN=1
33     fi
34
35     dnl Some old systems tried to use uid/gid -1 literally.
36     if test $ac_cv_func_chown_works = no; then
37       AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1],
38         [Define if chown is not POSIX compliant regarding IDs of -1.])
39       REPLACE_CHOWN=1
40     fi
41
42     dnl Solaris 9 ignores trailing slash.
43     dnl FreeBSD 7.2 mishandles trailing slash on symlinks.
44     dnl Likewise for AIX 7.1.
45     AC_CACHE_CHECK([whether chown honors trailing slash],
46       [gl_cv_func_chown_slash_works],
47       [touch conftest.file && rm -f conftest.link
48        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
49 #include <unistd.h>
50 #include <stdlib.h>
51 #include <errno.h>
52 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
53           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
54         ]])],
55         [gl_cv_func_chown_slash_works=yes],
56         [gl_cv_func_chown_slash_works=no],
57         [case "$host_os" in
58                    # Guess yes on glibc systems.
59            *-gnu*) gl_cv_func_chown_slash_works="guessing yes" ;;
60                    # If we don't know, assume the worst.
61            *)      gl_cv_func_chown_slash_works="guessing no" ;;
62          esac
63         ])
64       rm -f conftest.link conftest.file])
65     case "$gl_cv_func_chown_slash_works" in
66       *yes) ;;
67       *)
68         AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
69           [Define to 1 if chown mishandles trailing slash.])
70         REPLACE_CHOWN=1
71         ;;
72     esac
73
74     dnl OpenBSD fails to update ctime if ownership does not change.
75     AC_CACHE_CHECK([whether chown always updates ctime],
76       [gl_cv_func_chown_ctime_works],
77       [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
78 #include <unistd.h>
79 #include <stdlib.h>
80 #include <errno.h>
81 #include <fcntl.h>
82 #include <sys/stat.h>
83 ]], [[    struct stat st1, st2;
84           if (close (creat ("conftest.file", 0600))) return 1;
85           if (stat ("conftest.file", &st1)) return 2;
86           sleep (1);
87           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
88           if (stat ("conftest.file", &st2)) return 4;
89           if (st2.st_ctime <= st1.st_ctime) return 5;
90         ]])],
91         [gl_cv_func_chown_ctime_works=yes],
92         [gl_cv_func_chown_ctime_works=no],
93         [case "$host_os" in
94                    # Guess yes on glibc systems.
95            *-gnu*) gl_cv_func_chown_ctime_works="guessing yes" ;;
96                    # If we don't know, assume the worst.
97            *)      gl_cv_func_chown_ctime_works="guessing no" ;;
98          esac
99         ])
100       rm -f conftest.file])
101     case "$gl_cv_func_chown_ctime_works" in
102       *yes) ;;
103       *)
104         AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
105           to change ctime when at least one argument was not -1.])
106         REPLACE_CHOWN=1
107         ;;
108     esac
109   fi
110 ])
111
112 # Determine whether chown follows symlinks (it should).
113 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
114 [
115   AC_CACHE_CHECK(
116     [whether chown dereferences symlinks],
117     [gl_cv_func_chown_follows_symlink],
118     [
119       AC_RUN_IFELSE([AC_LANG_SOURCE([[
120 #include <unistd.h>
121 #include <stdlib.h>
122 #include <errno.h>
123
124         int
125         main ()
126         {
127           int result = 0;
128           char const *dangling_symlink = "conftest.dangle";
129
130           unlink (dangling_symlink);
131           if (symlink ("conftest.no-such", dangling_symlink))
132             abort ();
133
134           /* Exit successfully on a conforming system,
135              i.e., where chown must fail with ENOENT.  */
136           if (chown (dangling_symlink, getuid (), getgid ()) == 0)
137             result |= 1;
138           if (errno != ENOENT)
139             result |= 2;
140           return result;
141         }
142         ]])],
143         [gl_cv_func_chown_follows_symlink=yes],
144         [gl_cv_func_chown_follows_symlink=no],
145         [gl_cv_func_chown_follows_symlink=yes]
146       )
147     ]
148   )
149
150   if test $gl_cv_func_chown_follows_symlink = no; then
151     AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
152       [Define if chown modifies symlinks.])
153   fi
154 ])