]> git.cworth.org Git - tar/blob - m4/chown.m4
Imported Upstream version 1.24
[tar] / m4 / chown.m4
1 # serial 23
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     dnl Likewise for AIX 7.1.
47     AC_CACHE_CHECK([whether chown honors trailing slash],
48       [gl_cv_func_chown_slash_works],
49       [touch conftest.file && rm -f conftest.link
50        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <errno.h>
54 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
55           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
56         ]])],
57         [gl_cv_func_chown_slash_works=yes],
58         [gl_cv_func_chown_slash_works=no],
59         [gl_cv_func_chown_slash_works="guessing no"])
60       rm -f conftest.link conftest.file])
61     if test "$gl_cv_func_chown_slash_works" != yes; then
62       AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
63         [Define to 1 if chown mishandles trailing slash.])
64       REPLACE_CHOWN=1
65       AC_LIBOBJ([chown])
66     fi
67
68     dnl OpenBSD fails to update ctime if ownership does not change.
69     AC_CACHE_CHECK([whether chown always updates ctime],
70       [gl_cv_func_chown_ctime_works],
71       [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
72 #include <unistd.h>
73 #include <stdlib.h>
74 #include <errno.h>
75 #include <fcntl.h>
76 #include <sys/stat.h>
77 ]], [[    struct stat st1, st2;
78           if (close (creat ("conftest.file", 0600))) return 1;
79           if (stat ("conftest.file", &st1)) return 2;
80           sleep (1);
81           if (chown ("conftest.file", st1.st_uid, st1.st_gid)) return 3;
82           if (stat ("conftest.file", &st2)) return 4;
83           if (st2.st_ctime <= st1.st_ctime) return 5;
84         ]])],
85         [gl_cv_func_chown_ctime_works=yes],
86         [gl_cv_func_chown_ctime_works=no],
87         [gl_cv_func_chown_ctime_works="guessing no"])
88       rm -f conftest.file])
89     if test "$gl_cv_func_chown_ctime_works" != yes; then
90       AC_DEFINE([CHOWN_CHANGE_TIME_BUG], [1], [Define to 1 if chown fails
91         to change ctime when at least one argument was not -1.])
92       REPLACE_CHOWN=1
93       AC_LIBOBJ([chown])
94     fi
95
96     if test $REPLACE_CHOWN = 1 && test $ac_cv_func_fchown = no; then
97       AC_LIBOBJ([fchown-stub])
98     fi
99   fi
100 ])
101
102 # Determine whether chown follows symlinks (it should).
103 AC_DEFUN_ONCE([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
104 [
105   AC_CACHE_CHECK(
106     [whether chown dereferences symlinks],
107     [gl_cv_func_chown_follows_symlink],
108     [
109       AC_RUN_IFELSE([AC_LANG_SOURCE([[
110 #include <unistd.h>
111 #include <stdlib.h>
112 #include <errno.h>
113
114         int
115         main ()
116         {
117           char const *dangling_symlink = "conftest.dangle";
118
119           unlink (dangling_symlink);
120           if (symlink ("conftest.no-such", dangling_symlink))
121             abort ();
122
123           /* Exit successfully on a conforming system,
124              i.e., where chown must fail with ENOENT.  */
125           exit ( ! (chown (dangling_symlink, getuid (), getgid ()) != 0
126                     && errno == ENOENT));
127         }
128         ]])],
129         [gl_cv_func_chown_follows_symlink=yes],
130         [gl_cv_func_chown_follows_symlink=no],
131         [gl_cv_func_chown_follows_symlink=yes]
132       )
133     ]
134   )
135
136   if test $gl_cv_func_chown_follows_symlink = no; then
137     AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
138       [Define if chown modifies symlinks.])
139   fi
140 ])