]> git.cworth.org Git - tar/blob - m4/chown.m4
0c32fa39ff623c068bd5ecb3d5d1927c0acbf12d
[tar] / m4 / chown.m4
1 # serial 22
2 # Determine whether we need the chown wrapper.
3
4 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009-2010 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_CHECK_FUNCS_ONCE([chown fchown])
24
25   dnl mingw lacks chown altogether.
26   if test $ac_cv_func_chown = no; then
27     HAVE_CHOWN=0
28     AC_LIBOBJ([chown])
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       AC_LIBOBJ([chown])
34     fi
35
36     dnl Some old systems tried to use uid/gid -1 literally.
37     if test $ac_cv_func_chown_works = no; then
38       AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1],
39         [Define if chown is not POSIX compliant regarding IDs of -1.])
40       REPLACE_CHOWN=1
41       AC_LIBOBJ([chown])
42     fi
43
44     dnl Solaris 9 ignores trailing slash.
45     dnl FreeBSD 7.2 mishandles trailing slash on symlinks.
46     AC_CACHE_CHECK([whether chown honors trailing slash],
47       [gl_cv_func_chown_slash_works],
48       [touch conftest.file && rm -f conftest.link
49        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <errno.h>
53 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
54           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
55         ]])],
56         [gl_cv_func_chown_slash_works=yes],
57         [gl_cv_func_chown_slash_works=no],
58         [gl_cv_func_chown_slash_works="guessing no"])
59       rm -f conftest.link conftest.file])
60     if test "$gl_cv_func_chown_slash_works" != yes; then
61       AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
62         [Define to 1 if chown mishandles trailing slash.])
63       REPLACE_CHOWN=1
64       AC_LIBOBJ([chown])
65     fi
66
67     dnl OpenBSD fails to update ctime if ownership does not change.
68     AC_CACHE_CHECK([whether chown always updates ctime],
69       [gl_cv_func_chown_ctime_works],
70       [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
71 #include <unistd.h>
72 #include <stdlib.h>
73 #include <errno.h>
74 #include <fcntl.h>
75 #include <sys/stat.h>
76 ]], [[    struct stat st1, st2;
77           if (close (creat ("conftest.file", 0600))) return 1;
78           if (stat ("conftest.file", &st1)) return 2;
79           sleep (1);
80           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
81           if (stat ("conftest.file", &st2)) return 4;
82           if (st2.st_ctime <= st1.st_ctime) return 5;
83         ]])],
84         [gl_cv_func_chown_ctime_works=yes],
85         [gl_cv_func_chown_ctime_works=no],
86         [gl_cv_func_chown_ctime_works="guessing no"])
87       rm -f conftest.file])
88     if test "$gl_cv_func_chown_ctime_works" != yes; then
89       AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
90         to change ctime when at least one argument was not -1.])
91       REPLACE_CHOWN=1
92       AC_LIBOBJ([chown])
93     fi
94
95     if test $REPLACE_CHOWN = 1 && test $ac_cv_func_fchown = no; then
96       AC_LIBOBJ([fchown-stub])
97     fi
98   fi
99 ])
100
101 # Determine whether chown follows symlinks (it should).
102 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
103 [
104   AC_CACHE_CHECK(
105     [whether chown dereferences symlinks],
106     [gl_cv_func_chown_follows_symlink],
107     [
108       AC_RUN_IFELSE([AC_LANG_SOURCE([[
109 #include <unistd.h>
110 #include <stdlib.h>
111 #include <errno.h>
112
113         int
114         main ()
115         {
116           char const *dangling_symlink = "conftest.dangle";
117
118           unlink (dangling_symlink);
119           if (symlink ("conftest.no-such", dangling_symlink))
120             abort ();
121
122           /* Exit successfully on a conforming system,
123              i.e., where chown must fail with ENOENT.  */
124           exit ( ! (chown (dangling_symlink, getuid (), getgid ()) != 0
125                     && errno == ENOENT));
126         }
127         ]])],
128         [gl_cv_func_chown_follows_symlink=yes],
129         [gl_cv_func_chown_follows_symlink=no],
130         [gl_cv_func_chown_follows_symlink=yes]
131       )
132     ]
133   )
134
135   if test $gl_cv_func_chown_follows_symlink = no; then
136     AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
137       [Define if chown modifies symlinks.])
138   fi
139 ])