+2008-06-07 Bruno Haible <bruno@clisp.org>
+
+ Add support for MacOS X ACLs.
+ * lib/file-has-acl.c (file_has_acl): Use ACL_TYPE_EXTENDED instead of
+ ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT.
+ * lib/set-mode-acl.c (qset_acl): Likewise.
+ * lib/copy-acl.c (qcopy_acl): Likewise.
+
2008-06-07 Bruno Haible <bruno@clisp.org>
Fix memory leak introduced on 2008-05-22.
#if USE_ACL && HAVE_ACL_GET_FILE
/* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
/* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
+# if MODE_INSIDE_ACL
+ /* Linux, FreeBSD, IRIX, Tru64 */
acl_t acl;
int ret;
else
acl_free (acl);
- if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX)))
+ if (mode & (S_ISUID | S_ISGID | S_ISVTX))
{
/* We did not call chmod so far, and either the mode and the ACL are
separate or special bits are to be set which don't fit into ACLs. */
}
return 0;
+# else /* !MODE_INSIDE_ACL */
+ /* MacOS X */
+
+# if !HAVE_ACL_TYPE_EXTENDED
+# error Must have ACL_TYPE_EXTENDED
+# endif
+
+ /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
+ and acl_get_file (name, ACL_TYPE_DEFAULT)
+ always return NULL / EINVAL. You have to use
+ acl_get_file (name, ACL_TYPE_EXTENDED)
+ or acl_get_fd (open (name, ...))
+ to retrieve an ACL.
+ On the other hand,
+ acl_set_file (name, ACL_TYPE_ACCESS, acl)
+ and acl_set_file (name, ACL_TYPE_DEFAULT, acl)
+ have the same effect as
+ acl_set_file (name, ACL_TYPE_EXTENDED, acl):
+ Each of these calls sets the file's ACL. */
+
+ acl_t acl;
+ int ret;
+
+ if (HAVE_ACL_GET_FD && source_desc != -1)
+ acl = acl_get_fd (source_desc);
+ else
+ acl = acl_get_file (src_name, ACL_TYPE_EXTENDED);
+ if (acl == NULL)
+ {
+ if (ACL_NOT_WELL_SUPPORTED (errno))
+ return qset_acl (dst_name, dest_desc, mode);
+ else
+ return -2;
+ }
+
+ if (HAVE_ACL_SET_FD && dest_desc != -1)
+ ret = acl_set_fd (dest_desc, acl);
+ else
+ ret = acl_set_file (dst_name, ACL_TYPE_EXTENDED, acl);
+ if (ret != 0)
+ {
+ int saved_errno = errno;
+
+ if (ACL_NOT_WELL_SUPPORTED (errno) && !(acl_entries (acl) > 0))
+ {
+ acl_free (acl);
+ return chmod_or_fchmod (dst_name, dest_desc, mode);
+ }
+ else
+ {
+ acl_free (acl);
+ chmod_or_fchmod (dst_name, dest_desc, mode);
+ errno = saved_errno;
+ return -1;
+ }
+ }
+ else
+ acl_free (acl);
+
+ /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */
+ return chmod_or_fchmod (dst_name, dest_desc, mode);
+
+# endif
+
#elif USE_ACL && defined ACL_NO_TRIVIAL
/* Solaris 10 NFSv4 ACLs. */
int ret;
if (HAVE_ACL_EXTENDED_FILE)
- ret = acl_extended_file (name);
+ {
+ /* On Linux, acl_extended_file is an optimized function: It only
+ makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
+ ACL_TYPE_DEFAULT. */
+ ret = acl_extended_file (name);
+ }
else
{
+# if HAVE_ACL_TYPE_EXTENDED /* MacOS X */
+ /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
+ and acl_get_file (name, ACL_TYPE_DEFAULT)
+ always return NULL / EINVAL. There is no point in making
+ these two useless calls. The real ACL is retrieved through
+ acl_get_file (name, ACL_TYPE_EXTENDED). */
+ acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
+ if (acl)
+ {
+ ret = (0 < acl_entries (acl));
+ acl_free (acl);
+ }
+ else
+ ret = -1;
+# else /* FreeBSD, IRIX, Tru64 */
acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
if (acl)
{
}
else
ret = -1;
+# endif
}
if (ret < 0)
return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
}
#endif
- /* FIXME: Add support for AIX, Irix, and Tru64. Please see Samba's
+ /* FIXME: Add support for AIX. Please see Samba's
source/lib/sysacls.c file for fix-related ideas. */
return 0;
# else /* !MODE_INSIDE_ACL */
/* MacOS X */
+# if !HAVE_ACL_TYPE_EXTENDED
+# error Must have ACL_TYPE_EXTENDED
+# endif
+
+ /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
+ and acl_get_file (name, ACL_TYPE_DEFAULT)
+ always return NULL / EINVAL. You have to use
+ acl_get_file (name, ACL_TYPE_EXTENDED)
+ or acl_get_fd (open (name, ...))
+ to retrieve an ACL.
+ On the other hand,
+ acl_set_file (name, ACL_TYPE_ACCESS, acl)
+ and acl_set_file (name, ACL_TYPE_DEFAULT, acl)
+ have the same effect as
+ acl_set_file (name, ACL_TYPE_EXTENDED, acl):
+ Each of these calls sets the file's ACL. */
+
acl_t acl;
int ret;
if (HAVE_ACL_GET_FD && desc != -1)
acl = acl_get_fd (desc);
else
- acl = acl_get_file (name, ACL_TYPE_ACCESS);
+ acl = acl_get_file (name, ACL_TYPE_EXTENDED);
if (acl)
{
acl_free (acl);
if (HAVE_ACL_SET_FD && desc != -1)
ret = acl_set_fd (desc, acl);
else
- ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
+ ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
if (ret != 0)
{
int saved_errno = errno;