1 /* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
3 Copyright (C) 2002-2003, 2005-2020 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 <https://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, Cygwin >= 2.5 */
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, Cygwin >= 2.5 */
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, Cygwin >= 2.5 */
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, Cygwin >= 2.5 */
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 # ifdef __CYGWIN__ /* Cygwin >= 2.5 */
129 ret
= acl_access_nontrivial (acl
);
134 ret
= (0 < acl_entries (acl
));
148 return - acl_errno_valid (errno
);
151 # elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
153 # if defined ACL_NO_TRIVIAL
155 /* Solaris 10 (newer version), which has additional API declared in
156 <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
157 acl_fromtext, ...). */
158 return acl_trivial (name
);
160 # else /* Solaris, Cygwin, general case */
162 /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
163 of Unixware. The acl() call returns the access and default ACL both
166 /* Initially, try to read the entries into a stack-allocated buffer.
167 Use malloc if it does not fit. */
170 alloc_init
= 4000 / sizeof (aclent_t
), /* >= 3 */
171 alloc_max
= MIN (INT_MAX
, SIZE_MAX
/ sizeof (aclent_t
))
173 aclent_t buf
[alloc_init
];
174 size_t alloc
= alloc_init
;
175 aclent_t
*entries
= buf
;
176 aclent_t
*malloced
= NULL
;
181 count
= acl (name
, GETACL
, alloc
, entries
);
182 if (count
< 0 && errno
== ENOSPC
)
184 /* Increase the size of the buffer. */
186 if (alloc
> alloc_max
/ 2)
191 alloc
= 2 * alloc
; /* <= alloc_max */
193 (aclent_t
*) malloc (alloc
* sizeof (aclent_t
));
205 if (errno
== ENOSYS
|| errno
== ENOTSUP
)
209 int saved_errno
= errno
;
219 /* Don't use MIN_ACL_ENTRIES: It's set to 4 on Cygwin, but Cygwin
220 returns only 3 entries for files with no ACL. But this is safe:
221 If there are more than 4 entries, there cannot be only the
222 "user::", "group::", "other:", and "mask:" entries. */
229 if (acl_nontrivial (count
, entries
))
239 /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
240 file systems (whereas the other ones are used in UFS file systems). */
242 /* Initially, try to read the entries into a stack-allocated buffer.
243 Use malloc if it does not fit. */
246 alloc_init
= 4000 / sizeof (ace_t
), /* >= 3 */
247 alloc_max
= MIN (INT_MAX
, SIZE_MAX
/ sizeof (ace_t
))
249 ace_t buf
[alloc_init
];
250 size_t alloc
= alloc_init
;
251 ace_t
*entries
= buf
;
252 ace_t
*malloced
= NULL
;
257 count
= acl (name
, ACE_GETACL
, alloc
, entries
);
258 if (count
< 0 && errno
== ENOSPC
)
260 /* Increase the size of the buffer. */
262 if (alloc
> alloc_max
/ 2)
267 alloc
= 2 * alloc
; /* <= alloc_max */
268 entries
= malloced
= (ace_t
*) malloc (alloc
* sizeof (ace_t
));
280 if (errno
== ENOSYS
|| errno
== EINVAL
)
284 int saved_errno
= errno
;
294 /* In the old (original Solaris 10) convention:
295 If there are more than 3 entries, there cannot be only the
296 ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
297 In the newer Solaris 10 and Solaris 11 convention:
298 If there are more than 6 entries, there cannot be only the
299 ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
300 NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
301 NEW_ACE_ACCESS_DENIED_ACE_TYPE. */
308 if (acl_ace_nontrivial (count
, entries
))
321 # elif HAVE_GETACL /* HP-UX */
324 struct acl_entry entries
[NACLENTRIES
];
327 count
= getacl (name
, NACLENTRIES
, entries
);
331 /* ENOSYS is seen on newer HP-UX versions.
332 EOPNOTSUPP is typically seen on NFS mounts.
333 ENOTSUP was seen on Quantum StorNext file systems (cvfs). */
334 if (errno
== ENOSYS
|| errno
== EOPNOTSUPP
|| errno
== ENOTSUP
)
343 if (count
> NACLENTRIES
)
344 /* If NACLENTRIES cannot be trusted, use dynamic memory
348 /* If there are more than 3 entries, there cannot be only the
349 (uid,%), (%,gid), (%,%) entries. */
356 if (stat (name
, &statbuf
) < 0)
359 return acl_nontrivial (count
, entries
);
364 # if HAVE_ACLV_H /* HP-UX >= 11.11 */
367 struct acl entries
[NACLVENTRIES
];
370 count
= acl ((char *) name
, ACL_GET
, NACLVENTRIES
, entries
);
374 /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
375 EINVAL is seen on NFS in HP-UX 11.31. */
376 if (errno
== ENOSYS
|| errno
== EOPNOTSUPP
|| errno
== EINVAL
)
385 if (count
> NACLVENTRIES
)
386 /* If NACLVENTRIES cannot be trusted, use dynamic memory
390 /* If there are more than 4 entries, there cannot be only the
391 four base ACL entries. */
395 return aclv_nontrivial (count
, entries
);
401 # elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
406 size_t aclsize
= sizeof (aclbuf
);
411 /* The docs say that type being 0 is equivalent to ACL_ANY, but it
412 is not true, in AIX 5.3. */
414 if (aclx_get (name
, 0, &type
, aclbuf
, &aclsize
, &mode
) >= 0)
422 int saved_errno
= errno
;
428 aclsize
= 2 * aclsize
;
431 acl
= malloc (aclsize
);
439 if (type
.u64
== ACL_AIXC
)
441 int result
= acl_nontrivial ((struct acl
*) acl
);
446 else if (type
.u64
== ACL_NFS4
)
448 int result
= acl_nfs4_nontrivial ((nfs4_acl_int_t
*) acl
);
455 /* A newer type of ACL has been introduced in the system.
456 We should better support it. */
463 # elif HAVE_STATACL /* older AIX */
465 union { struct acl a
; char room
[4096]; } u
;
467 if (statacl ((char *) name
, STX_NORMAL
, &u
.a
, sizeof (u
)) < 0)
470 return acl_nontrivial (&u
.a
);
472 # elif HAVE_ACLSORT /* NonStop Kernel */
475 struct acl entries
[NACLENTRIES
];
478 count
= acl ((char *) name
, ACL_GET
, NACLENTRIES
, entries
);
482 if (errno
== ENOSYS
|| errno
== ENOTSUP
)
491 if (count
> NACLENTRIES
)
492 /* If NACLENTRIES cannot be trusted, use dynamic memory
496 /* If there are more than 4 entries, there cannot be only the
497 four base ACL entries. */
501 return acl_nontrivial (count
, entries
);