chown: detect Solaris and FreeBSD bug
[pspp] / m4 / chown.m4
1 # serial 20
2 # Determine whether we need the chown wrapper.
3
4 dnl Copyright (C) 1997-2001, 2003-2005, 2007, 2009
5 dnl Free Software 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([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   if test $ac_cv_func_chown = no; then
26     HAVE_CHOWN=0
27     AC_LIBOBJ([chown])
28   else
29     if test $gl_cv_func_chown_follows_symlink = no; then
30       REPLACE_CHOWN=1
31       AC_LIBOBJ([chown])
32     fi
33     if test $ac_cv_func_chown_works = no; then
34       AC_DEFINE([CHOWN_FAILS_TO_HONOR_ID_OF_NEGATIVE_ONE], [1],
35         [Define if chown is not POSIX compliant regarding IDs of -1.])
36       REPLACE_CHOWN=1
37       AC_LIBOBJ([chown])
38     fi
39     AC_CACHE_CHECK([whether chown honors trailing slash],
40       [gl_cv_func_chown_slash_works],
41       [touch conftest.file && rm -f conftest.link
42        AC_RUN_IFELSE([AC_LANG_PROGRAM([[
43 #include <unistd.h>
44 #include <stdlib.h>
45 #include <errno.h>
46 ]], [[    if (symlink ("conftest.file", "conftest.link")) return 1;
47           if (chown ("conftest.link/", getuid (), getgid ()) == 0) return 2;
48         ]])],
49         [gl_cv_func_chown_slash_works=yes],
50         [gl_cv_func_chown_slash_works=no],
51         [gl_cv_func_chown_slash_works="guessing no"])
52       rm -f conftest.link conftest.file])
53     if test "$gl_cv_func_chown_slash_works" != yes; then
54       AC_DEFINE([CHOWN_TRAILING_SLASH_BUG], [1],
55         [Define if chown mishandles trailing slash.])
56       REPLACE_CHOWN=1
57       AC_LIBOBJ([chown])
58     fi
59     if test $REPLACE_CHOWN = 1 && test $ac_cv_func_fchown = no; then
60       AC_LIBOBJ([fchown-stub])
61     fi
62   fi
63 ])
64
65 # Determine whether chown follows symlinks (it should).
66 AC_DEFUN([gl_FUNC_CHOWN_FOLLOWS_SYMLINK],
67 [
68   AC_CACHE_CHECK(
69     [whether chown dereferences symlinks],
70     [gl_cv_func_chown_follows_symlink],
71     [
72       AC_RUN_IFELSE([AC_LANG_SOURCE([[
73 #include <unistd.h>
74 #include <stdlib.h>
75 #include <errno.h>
76
77         int
78         main ()
79         {
80           char const *dangling_symlink = "conftest.dangle";
81
82           unlink (dangling_symlink);
83           if (symlink ("conftest.no-such", dangling_symlink))
84             abort ();
85
86           /* Exit successfully on a conforming system,
87              i.e., where chown must fail with ENOENT.  */
88           exit ( ! (chown (dangling_symlink, getuid (), getgid ()) != 0
89                     && errno == ENOENT));
90         }
91         ]])],
92         [gl_cv_func_chown_follows_symlink=yes],
93         [gl_cv_func_chown_follows_symlink=no],
94         [gl_cv_func_chown_follows_symlink=yes]
95       )
96     ]
97   )
98
99   if test $gl_cv_func_chown_follows_symlink = no; then
100     AC_DEFINE([CHOWN_MODIFIES_SYMLINK], [1],
101       [Define if chown modifies symlinks.])
102   fi
103 ])