1 /* Test whether a file has a nontrivial access control list.
3 Copyright (C) 2002-2003, 2005-2015 Free Software Foundation, Inc.
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.
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.
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/>.
18 Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
20 /* Without this pragma, gcc 4.7.0 20120126 may suggest that the
21 file_has_acl function might be candidate for attribute 'const' */
22 #if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
23 # pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
30 #include "acl-internal.h"
32 #if GETXATTR_WITH_POSIX_ACLS
33 # include <sys/xattr.h>
34 # include <linux/xattr.h>
37 /* Return 1 if NAME has a nontrivial access control list,
38 0 if ACLs are not supported, or if NAME has no or only a base ACL,
39 and -1 (setting errno) on error. Note callers can determine
40 if ACLs are not supported as errno is set in that case also.
41 SB must be set to the stat buffer of NAME,
42 obtained through stat() or lstat(). */
45 file_has_acl (char const *name, struct stat const *sb)
48 if (! S_ISLNK (sb->st_mode))
51 # if GETXATTR_WITH_POSIX_ACLS
55 ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0);
56 if (ret < 0 && errno == ENODATA)
61 if (ret == 0 && S_ISDIR (sb->st_mode))
63 ret = getxattr (name, XATTR_NAME_POSIX_ACL_DEFAULT, NULL, 0);
64 if (ret < 0 && errno == ENODATA)
71 return - acl_errno_valid (errno);
74 # elif HAVE_ACL_GET_FILE
76 /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
77 /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
80 if (HAVE_ACL_EXTENDED_FILE) /* Linux */
82 /* On Linux, acl_extended_file is an optimized function: It only
83 makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
85 ret = acl_extended_file (name);
87 else /* FreeBSD, Mac OS X, IRIX, Tru64 */
89 # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
90 /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
91 and acl_get_file (name, ACL_TYPE_DEFAULT)
92 always return NULL / EINVAL. There is no point in making
93 these two useless calls. The real ACL is retrieved through
94 acl_get_file (name, ACL_TYPE_EXTENDED). */
95 acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
98 ret = acl_extended_nontrivial (acl);
103 # else /* FreeBSD, IRIX, Tru64 */
104 acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
109 ret = acl_access_nontrivial (acl);
113 # if HAVE_ACL_FREE_TEXT /* Tru64 */
114 /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
115 returns NULL with errno not set. There is no point in
117 # else /* FreeBSD, IRIX */
118 /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
119 and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
120 either both succeed or both fail; it depends on the
121 file system. Therefore there is no point in making the second
122 call if the first one already failed. */
123 if (ret == 0 && S_ISDIR (sb->st_mode))
125 acl = acl_get_file (name, ACL_TYPE_DEFAULT);
128 ret = (0 < acl_entries (acl));
141 return - acl_errno_valid (errno);
144 # elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
146 # if defined ACL_NO_TRIVIAL
148 /* Solaris 10 (newer version), which has additional API declared in
149 <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
150 acl_fromtext, ...). */
151 return acl_trivial (name);
153 # else /* Solaris, Cygwin, general case */
155 /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
156 of Unixware. The acl() call returns the access and default ACL both
159 /* Initially, try to read the entries into a stack-allocated buffer.
160 Use malloc if it does not fit. */
163 alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */
164 alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t))
166 aclent_t buf[alloc_init];
167 size_t alloc = alloc_init;
168 aclent_t *entries = buf;
169 aclent_t *malloced = NULL;
174 count = acl (name, GETACL, alloc, entries);
175 if (count < 0 && errno == ENOSPC)
177 /* Increase the size of the buffer. */
179 if (alloc > alloc_max / 2)
184 alloc = 2 * alloc; /* <= alloc_max */
186 (aclent_t *) malloc (alloc * sizeof (aclent_t));
198 if (errno == ENOSYS || errno == ENOTSUP)
202 int saved_errno = errno;
212 /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin
213 returns only 3 entries for files with no ACL. But this is safe:
214 If there are more than 4 entries, there cannot be only the
215 "user::", "group::", "other:", and "mask:" entries. */
222 if (acl_nontrivial (count, entries))
232 /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
233 file systems (whereas the other ones are used in UFS file systems). */
235 /* Initially, try to read the entries into a stack-allocated buffer.
236 Use malloc if it does not fit. */
239 alloc_init = 4000 / sizeof (ace_t), /* >= 3 */
240 alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
242 ace_t buf[alloc_init];
243 size_t alloc = alloc_init;
244 ace_t *entries = buf;
245 ace_t *malloced = NULL;
250 count = acl (name, ACE_GETACL, alloc, entries);
251 if (count < 0 && errno == ENOSPC)
253 /* Increase the size of the buffer. */
255 if (alloc > alloc_max / 2)
260 alloc = 2 * alloc; /* <= alloc_max */
261 entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
273 if (errno == ENOSYS || errno == EINVAL)
277 int saved_errno = errno;
287 /* In the old (original Solaris 10) convention:
288 If there are more than 3 entries, there cannot be only the
289 ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
290 In the newer Solaris 10 and Solaris 11 convention:
291 If there are more than 6 entries, there cannot be only the
292 ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
293 NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
294 NEW_ACE_ACCESS_DENIED_ACE_TYPE. */
301 if (acl_ace_nontrivial (count, entries))
314 # elif HAVE_GETACL /* HP-UX */
317 struct acl_entry entries[NACLENTRIES];
320 count = getacl (name, NACLENTRIES, entries);
324 /* ENOSYS is seen on newer HP-UX versions.
325 EOPNOTSUPP is typically seen on NFS mounts.
326 ENOTSUP was seen on Quantum StorNext file systems (cvfs). */
327 if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
336 if (count > NACLENTRIES)
337 /* If NACLENTRIES cannot be trusted, use dynamic memory
341 /* If there are more than 3 entries, there cannot be only the
342 (uid,%), (%,gid), (%,%) entries. */
349 if (stat (name, &statbuf) < 0)
352 return acl_nontrivial (count, entries);
357 # if HAVE_ACLV_H /* HP-UX >= 11.11 */
360 struct acl entries[NACLVENTRIES];
363 count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries);
367 /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
368 EINVAL is seen on NFS in HP-UX 11.31. */
369 if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
378 if (count > NACLVENTRIES)
379 /* If NACLVENTRIES cannot be trusted, use dynamic memory
383 /* If there are more than 4 entries, there cannot be only the
384 four base ACL entries. */
388 return aclv_nontrivial (count, entries);
394 # elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
399 size_t aclsize = sizeof (aclbuf);
404 /* The docs say that type being 0 is equivalent to ACL_ANY, but it
405 is not true, in AIX 5.3. */
407 if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
415 int saved_errno = errno;
421 aclsize = 2 * aclsize;
424 acl = malloc (aclsize);
432 if (type.u64 == ACL_AIXC)
434 int result = acl_nontrivial ((struct acl *) acl);
439 else if (type.u64 == ACL_NFS4)
441 int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
448 /* A newer type of ACL has been introduced in the system.
449 We should better support it. */
456 # elif HAVE_STATACL /* older AIX */
458 union { struct acl a; char room[4096]; } u;
460 if (statacl ((char *) name, STX_NORMAL, &u.a, sizeof (u)) < 0)
463 return acl_nontrivial (&u.a);
465 # elif HAVE_ACLSORT /* NonStop Kernel */
468 struct acl entries[NACLENTRIES];
471 count = acl ((char *) name, ACL_GET, NACLENTRIES, entries);
475 if (errno == ENOSYS || errno == ENOTSUP)
484 if (count > NACLENTRIES)
485 /* If NACLENTRIES cannot be trusted, use dynamic memory
489 /* If there are more than 4 entries, there cannot be only the
490 four base ACL entries. */
494 return acl_nontrivial (count, entries);