Simplify #ifs. Put Solaris code after POSIX-like code.
[pspp] / lib / file-has-acl.c
1 /* Test whether a file has a nontrivial access control list.
2
3    Copyright (C) 2002-2003, 2005-2008 Free Software Foundation, Inc.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18    Written by Paul Eggert and Andreas Gruenbacher.  */
19
20 #include <config.h>
21
22 #include "acl.h"
23
24 #include "acl-internal.h"
25
26 /* Return 1 if NAME has a nontrivial access control list, 0 if NAME
27    only has no or a base access control list, and -1 (setting errno)
28    on error.  SB must be set to the stat buffer of FILE.  */
29
30 int
31 file_has_acl (char const *name, struct stat const *sb)
32 {
33 #if USE_ACL
34   if (! S_ISLNK (sb->st_mode))
35     {
36 # if HAVE_ACL_GET_FILE
37
38       /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
39       /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
40       int ret;
41
42       if (HAVE_ACL_EXTENDED_FILE)
43         ret = acl_extended_file (name);
44       else
45         {
46           acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
47           if (acl)
48             {
49               ret = (3 * MODE_INSIDE_ACL < acl_entries (acl));
50               acl_free (acl);
51               if (ret == 0 && S_ISDIR (sb->st_mode))
52                 {
53                   acl = acl_get_file (name, ACL_TYPE_DEFAULT);
54                   if (acl)
55                     {
56                       ret = (0 < acl_entries (acl));
57                       acl_free (acl);
58                     }
59                   else
60                     ret = -1;
61                 }
62             }
63           else
64             ret = -1;
65         }
66       if (ret < 0)
67         return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
68       return ret;
69
70 # elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
71
72 #  if HAVE_ACL_TRIVIAL
73
74       /* Solaris 10, which also has NFSv4 and ZFS style ACLs.  */
75       return acl_trivial (name);
76
77 #  else /* Solaris, Cygwin, general case */
78
79       /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
80          of Unixware.  The acl() call returns the access and default ACL both
81          at once.  */
82       int n = acl (name, GETACLCNT, 0, NULL);
83       return n < 0 ? (errno == ENOSYS ? 0 : -1) : (MIN_ACL_ENTRIES < n);
84
85 #  endif
86
87 # endif
88     }
89 #endif
90
91   /* FIXME: Add support for AIX, Irix, and Tru64.  Please see Samba's
92      source/lib/sysacls.c file for fix-related ideas.  */
93
94   return 0;
95 }