[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
acl: finish support for MacOS X
From: |
Bruno Haible |
Subject: |
acl: finish support for MacOS X |
Date: |
Sun, 8 Jun 2008 05:06:39 +0200 |
User-agent: |
KMail/1.5.4 |
On MacOS X the testsuite still fails:
file_has_acl("tmpfile0") returned no, expected yes
FAIL: test-file-has-acl.sh
PASS: test-set-mode-acl.sh
PASS: test-copy-acl.sh
The reason is that on MacOS X, the ACL types ACL_TYPE_ACCESS and
ACL_TYPE_DEFAULT
are not supported; only ACL_TYPE_EXTENDED works. More precisely, I found out
through some testing that:
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.
In my first attempt, I had code that uses all both ACL_TYPE_ACCESS and
ACL_TYPE_EXTENDED. But this is overkill: It only makes useless system calls.
Better use ACL_TYPE_EXTENDED _only_.
Please review (although I commit it immediately, because more patches are
coming.)
2008-06-07 Bruno Haible <address@hidden>
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.
*** lib/file-has-acl.c.orig 2008-06-08 04:56:25.000000000 +0200
--- lib/file-has-acl.c 2008-06-08 04:56:11.000000000 +0200
***************
*** 127,135 ****
int ret;
if (HAVE_ACL_EXTENDED_FILE)
! ret = acl_extended_file (name);
else
{
acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
if (acl)
{
--- 127,155 ----
int ret;
if (HAVE_ACL_EXTENDED_FILE)
! {
! /* 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)
{
***************
*** 153,158 ****
--- 173,179 ----
}
else
ret = -1;
+ # endif
}
if (ret < 0)
return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
***************
*** 179,185 ****
}
#endif
! /* FIXME: Add support for AIX, Irix, and Tru64. Please see Samba's
source/lib/sysacls.c file for fix-related ideas. */
return 0;
--- 200,206 ----
}
#endif
! /* FIXME: Add support for AIX. Please see Samba's
source/lib/sysacls.c file for fix-related ideas. */
return 0;
*** lib/set-mode-acl.c.orig 2008-06-08 04:56:25.000000000 +0200
--- lib/set-mode-acl.c 2008-06-08 04:56:11.000000000 +0200
***************
*** 143,148 ****
--- 143,165 ----
# 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;
***************
*** 150,156 ****
if (HAVE_ACL_GET_FD && desc != -1)
acl = acl_get_fd (desc);
else
! acl = acl_get_file (name, ACL_TYPE_ACCESS);
if (acl)
{
acl_free (acl);
--- 167,173 ----
if (HAVE_ACL_GET_FD && desc != -1)
acl = acl_get_fd (desc);
else
! acl = acl_get_file (name, ACL_TYPE_EXTENDED);
if (acl)
{
acl_free (acl);
***************
*** 161,167 ****
if (HAVE_ACL_SET_FD && desc != -1)
ret = acl_set_fd (desc, acl);
else
! ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
if (ret != 0)
{
int saved_errno = errno;
--- 178,184 ----
if (HAVE_ACL_SET_FD && desc != -1)
ret = acl_set_fd (desc, acl);
else
! ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl);
if (ret != 0)
{
int saved_errno = errno;
*** lib/copy-acl.c.orig 2008-06-08 04:56:25.000000000 +0200
--- lib/copy-acl.c 2008-06-08 04:56:11.000000000 +0200
***************
*** 42,47 ****
--- 42,49 ----
#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;
***************
*** 82,88 ****
else
acl_free (acl);
! if (!MODE_INSIDE_ACL || (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. */
--- 84,90 ----
else
acl_free (acl);
! 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. */
***************
*** 110,115 ****
--- 112,181 ----
}
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. */
- acl: finish support for MacOS X,
Bruno Haible <=