# HG changeset patch # User Bruno Haible # Date 1212894379 -7200 # Node ID 50e666f281eff805e5d71b75c2abba606747a808 # Parent f988df7e273dae65f46d42d09231c8f7c1af761b Add support for MacOS X ACLs. diff -r f988df7e273d -r 50e666f281ef ChangeLog --- a/ChangeLog Sun Jun 08 04:51:21 2008 +0200 +++ b/ChangeLog Sun Jun 08 05:06:19 2008 +0200 @@ -1,3 +1,11 @@ +2008-06-07 Bruno Haible + + 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 Fix memory leak introduced on 2008-05-22. diff -r f988df7e273d -r 50e666f281ef lib/copy-acl.c --- a/lib/copy-acl.c Sun Jun 08 04:51:21 2008 +0200 +++ b/lib/copy-acl.c Sun Jun 08 05:06:19 2008 +0200 @@ -42,6 +42,8 @@ #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,7 +84,7 @@ 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. */ @@ -110,6 +112,70 @@ } 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. */ diff -r f988df7e273d -r 50e666f281ef lib/file-has-acl.c --- a/lib/file-has-acl.c Sun Jun 08 04:51:21 2008 +0200 +++ b/lib/file-has-acl.c Sun Jun 08 05:06:19 2008 +0200 @@ -127,9 +127,29 @@ 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) { @@ -153,6 +173,7 @@ } else ret = -1; +# endif } if (ret < 0) return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1; @@ -179,7 +200,7 @@ } #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; diff -r f988df7e273d -r 50e666f281ef lib/set-mode-acl.c --- a/lib/set-mode-acl.c Sun Jun 08 04:51:21 2008 +0200 +++ b/lib/set-mode-acl.c Sun Jun 08 05:06:19 2008 +0200 @@ -143,6 +143,23 @@ # 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,7 +167,7 @@ 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); @@ -161,7 +178,7 @@ 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;