Hi Jim, Here comes the reworked patch for MacOS X 10.5 support in copy_acl, used by the 'copy-file' module. With it, now the test passes on MacOS X 10.5, and of course still passes on Linux and FreeBSD.
The main difficulty here was to realize that in MacOS X, unlike many other flavors of ACLs, an ACL does *not* contain the file mode (rwxrwxrwx). They are separate. In the code I created a macro MODE_INSIDE_ACL to denote the "normal" situation. The consequences are that - The qset_acl function requires a different logic when !MODE_INSIDE_ACL. When MODE_INSIDE_ACL, one optimizes system calls by calling chmod only when setting the ACL failed or was not enough. When !MODE_INSIDE_ACL, one has to call chmod always. - Similarly in copy_acl, but here the code changes are smaller. - When !MODE_INSIDE_ACL, a trivial ACL has 0 entries, not 3 entries. Another realization is that this piece of code in acl.c: char acl_text[] = "u::---,g::---,o::---"; if (mode & S_IRUSR) acl_text[ 3] = 'r'; if (mode & S_IWUSR) acl_text[ 4] = 'w'; if (mode & S_IXUSR) acl_text[ 5] = 'x'; works only on FreeBSD (and possibly IRIX). Basically, every ACL flavor comes with its own textual representation of ACLs, and most of them expect the syntax "other:rwx", not "other::rwx". Also, I added a comment explaining why the conversion mode_t -> acl_t goes through the textual representation rather than through acl_init() and acl_create_entry(). > for future patches to my attention please use git format-patch, > since that makes it easier for me to apply and ensure that when I review Find it attached as attachment. Now I'll have to learn how to amend previous commits... OK to commit? After this, I'll turn to the other 5 platforms. 2008-05-22 Bruno Haible <[EMAIL PROTECTED]> Make copy_acl work on MacOS X 10.5. * lib/acl-internal.h (MODE_INSIDE_ACL): New macro. (ACL_NOT_WELL_SUPPORTED): On MacOS X, also handle ENOENT. * lib/acl.c (qset_acl): Add different code branch for !MODE_INSIDE_ACL. If MODE_INSIDE_ACL, don't assume that every system has the same text representation for ACLs as FreeBSD. * lib/copy-acl.c (copy_acl): Add support for platforms with !MODE_INSIDE_ACL. * lib/file-has-acl.c (file_has_acl): Likewise. * m4/acl.m4 (gl_FUNC_ACL): Test for some functions that are witness of FreeBSD or MacOS X, respectively. *** lib/acl-internal.h.orig 2008-05-23 01:08:01.000000000 +0200 --- lib/acl-internal.h 2008-05-23 00:15:58.000000000 +0200 *************** *** 84,91 **** # define acl_from_mode(mode) (NULL) #endif ! #define ACL_NOT_WELL_SUPPORTED(Err) \ ! ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY) /* Define a replacement for acl_entries if needed. */ #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE && !HAVE_ACL_ENTRIES --- 84,104 ---- # define acl_from_mode(mode) (NULL) #endif ! /* Set to 1 if a file's mode is implicit by the ACL. ! Set to 0 if a file's mode is stored independently from the ACL. */ ! #if HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP /* MacOS X */ ! # define MODE_INSIDE_ACL 0 ! #else ! # define MODE_INSIDE_ACL 1 ! #endif ! ! #if defined __APPLE__ && defined __MACH__ /* MacOS X */ ! # define ACL_NOT_WELL_SUPPORTED(Err) \ ! ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY || (Err) == ENOENT) ! #else ! # define ACL_NOT_WELL_SUPPORTED(Err) \ ! ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY) ! #endif /* Define a replacement for acl_entries if needed. */ #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE && !HAVE_ACL_ENTRIES *** lib/acl.c.orig 2008-05-23 01:08:01.000000000 +0200 --- lib/acl.c 2008-05-23 00:52:39.000000000 +0200 *************** *** 48,79 **** int qset_acl (char const *name, int desc, mode_t mode) { ! #if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e draft 17 (abandoned) specific version. */ ! /* We must also have have_acl_from_text and acl_delete_def_file. (acl_delete_def_file could be emulated with acl_init followed by acl_set_file, but acl_set_file with an empty acl is unspecified.) */ ! # ifndef HAVE_ACL_FROM_TEXT ! # error Must have acl_from_text (see POSIX 1003.1e draft 17). ! # endif ! # ifndef HAVE_ACL_DELETE_DEF_FILE ! # error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). ! # endif acl_t acl; int ret; ! if (HAVE_ACL_FROM_MODE) { acl = acl_from_mode (mode); if (!acl) return -1; } ! else { char acl_text[] = "u::---,g::---,o::---"; if (mode & S_IRUSR) acl_text[ 3] = 'r'; --- 48,89 ---- int qset_acl (char const *name, int desc, mode_t mode) { ! #if USE_ACL ! # if MODE_INSIDE_ACL ! # if HAVE_ACL_SET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e draft 17 (abandoned) specific version. */ + /* Linux, FreeBSD, IRIX, Tru64 */ ! /* We must also have acl_from_text and acl_delete_def_file. (acl_delete_def_file could be emulated with acl_init followed by acl_set_file, but acl_set_file with an empty acl is unspecified.) */ ! # ifndef HAVE_ACL_FROM_TEXT ! # error Must have acl_from_text (see POSIX 1003.1e draft 17). ! # endif ! # ifndef HAVE_ACL_DELETE_DEF_FILE ! # error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). ! # endif acl_t acl; int ret; ! if (HAVE_ACL_FROM_MODE) /* Linux */ { acl = acl_from_mode (mode); if (!acl) return -1; } ! else /* FreeBSD, IRIX, Tru64 */ { + /* If we were to create the ACL using the functions acl_init(), + acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(), + acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we + would need to create a qualifier. I don't know how to do this. + So create it using acl_from_text(). */ + + # if HAVE_ACL_DELETE_FD_NP && HAVE_ACL_DELETE_FILE_NP /* FreeBSD */ char acl_text[] = "u::---,g::---,o::---"; if (mode & S_IRUSR) acl_text[ 3] = 'r'; *************** *** 89,94 **** --- 99,107 ---- acl = acl_from_text (acl_text); if (!acl) return -1; + # else /* Unknown flavor of POSIX-like ACLs */ + return chmod_or_fchmod (name, desc, mode); + # endif } if (HAVE_ACL_SET_FD && desc != -1) ret = acl_set_fd (desc, acl); *************** *** 124,133 **** return -1; } return 0; - #else - - # if USE_ACL && defined ACL_NO_TRIVIAL /* Solaris 10, with NFSv4 ACLs. */ acl_t *aclp; char acl_text[] = "user::---,group::---,mask:---,other:---"; --- 137,144 ---- return -1; } return 0; + # elif defined ACL_NO_TRIVIAL /* Solaris 10, with NFSv4 ACLs. */ acl_t *aclp; char acl_text[] = "user::---,group::---,mask:---,other:---"; *************** *** 158,167 **** return acl_result; } } - # endif return chmod_or_fchmod (name, desc, mode); #endif } --- 169,234 ---- return acl_result; } } return chmod_or_fchmod (name, desc, mode); + # else /* Unknown flavor of ACLs */ + return chmod_or_fchmod (name, desc, mode); + # endif + # else /* !MODE_INSIDE_ACL */ + # if HAVE_ACL_SET_FILE && HAVE_ACL_FREE + /* POSIX 1003.1e draft 17 (abandoned) specific version. */ + /* MacOS X */ + + acl_t acl; + int ret; + + /* Remove the ACL if the file has ACLs. */ + if (HAVE_ACL_GET_FD && desc != -1) + acl = acl_get_fd (desc); + else + acl = acl_get_file (name, ACL_TYPE_ACCESS); + if (acl) + { + # if HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP /* MacOS X */ + static const char empty_acl_text[] = "!#acl 1\n"; + # else /* Unknown flavor of POSIX-like ACLs */ + # error Unknown flavor of POSIX-like ACLs - add support for your platform. + # endif + + acl = acl_from_text (empty_acl_text); + if (acl) + { + 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; + + acl_free (acl); + + if (ACL_NOT_WELL_SUPPORTED (saved_errno)) + { + if (chmod_or_fchmod (name, desc, mode) != 0) + saved_errno = errno; + else + return 0; + } + errno = saved_errno; + return -1; + } + } + } + + return chmod_or_fchmod (name, desc, mode); + # else /* Unknown flavor of ACLs */ + return chmod_or_fchmod (name, desc, mode); + # endif + # endif + #else /* !USE_ACL */ + return chmod_or_fchmod (name, desc, mode); #endif } *** lib/copy-acl.c.orig 2008-05-23 01:08:01.000000000 +0200 --- lib/copy-acl.c 2008-05-23 00:54:12.000000000 +0200 *************** *** 40,45 **** --- 40,46 ---- #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ acl_t acl; if (HAVE_ACL_GET_FD && source_desc != -1) *************** *** 70,81 **** int n = acl_entries (acl); acl_free (acl); ! /* On most hosts an ACL is trivial if n == 3, and it cannot be ! less than 3. On IRIX 6.5 it is also trivial if n == -1. For simplicity and safety, assume the ACL is trivial if n <= 3. Also see file-has-acl.c for some of the other possibilities; it's not clear whether that complexity is needed here. */ ! if (n <= 3) { if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) saved_errno = errno; --- 71,83 ---- int n = acl_entries (acl); acl_free (acl); ! /* On most hosts with MODE_INSIDE_ACL an ACL is trivial if n == 3, ! and it cannot be less than 3. On IRIX 6.5 it is also trivial if ! n == -1. For simplicity and safety, assume the ACL is trivial if n <= 3. Also see file-has-acl.c for some of the other possibilities; it's not clear whether that complexity is needed here. */ ! if (n <= 3 * MODE_INSIDE_ACL) { if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) saved_errno = errno; *************** *** 97,106 **** else acl_free (acl); ! if (mode & (S_ISUID | S_ISGID | S_ISVTX)) { ! /* We did not call chmod so far, so the special bits have not yet ! been set. */ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) { --- 99,108 ---- 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. */ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) { *** lib/file-has-acl.c.orig 2008-05-23 01:08:01.000000000 +0200 --- lib/file-has-acl.c 2008-05-23 00:36:37.000000000 +0200 *************** *** 1,6 **** /* Test whether a file has a nontrivial access control list. ! Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by --- 1,6 ---- /* Test whether a file has a nontrivial access control list. ! Copyright (C) 2002-2003, 2005-2008 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by *************** *** 47,52 **** --- 47,53 ---- #elif USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ int ret; if (HAVE_ACL_EXTENDED_FILE) *************** *** 56,62 **** acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS); if (acl) { ! ret = (3 < acl_entries (acl)); acl_free (acl); if (ret == 0 && S_ISDIR (sb->st_mode)) { --- 57,63 ---- acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS); if (acl) { ! ret = (3 * MODE_INSIDE_ACL < acl_entries (acl)); acl_free (acl); if (ret == 0 && S_ISDIR (sb->st_mode)) { *** m4/acl.m4.orig 2008-05-23 01:08:01.000000000 +0200 --- m4/acl.m4 2008-05-23 00:16:28.000000000 +0200 *************** *** 1,5 **** # acl.m4 - check for access control list (ACL) primitives ! # serial 3 # Copyright (C) 2002, 2004-2008 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation --- 1,5 ---- # acl.m4 - check for access control list (ACL) primitives ! # serial 4 # Copyright (C) 2002, 2004-2008 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation *************** *** 35,41 **** AC_CHECK_FUNCS( [acl_get_file acl_get_fd acl_set_file acl_set_fd \ acl_free acl_from_mode acl_from_text \ ! acl_delete_def_file acl_extended_file]) if test $ac_cv_func_acl_get_file = yes; then # If the acl_get_file bug is detected, disable all ACL support. gl_ACL_GET_FILE( , [use_acl=0]) --- 35,43 ---- AC_CHECK_FUNCS( [acl_get_file acl_get_fd acl_set_file acl_set_fd \ acl_free acl_from_mode acl_from_text \ ! acl_delete_def_file acl_extended_file \ ! acl_delete_fd_np acl_delete_file_np \ ! acl_copy_ext_native acl_create_entry_np]) if test $ac_cv_func_acl_get_file = yes; then # If the acl_get_file bug is detected, disable all ACL support. gl_ACL_GET_FILE( , [use_acl=0])
From da9fd677c05325560fa533cbf7c3e67eb9844fbe Mon Sep 17 00:00:00 2001 From: Bruno Haible <[EMAIL PROTECTED]> Date: Fri, 23 May 2008 01:13:51 +0200 Subject: [PATCH] Make copy_acl work on MacOS X 10.5. --- ChangeLog | 14 ++++++++ lib/acl-internal.h | 17 ++++++++- lib/acl.c | 95 ++++++++++++++++++++++++++++++++++++++++++++-------- lib/copy-acl.c | 14 ++++--- lib/file-has-acl.c | 5 ++- m4/acl.m4 | 6 ++- 6 files changed, 125 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9bbd1e9..a2aef6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2008-05-22 Bruno Haible <[EMAIL PROTECTED]> + Make copy_acl work on MacOS X 10.5. + * lib/acl-internal.h (MODE_INSIDE_ACL): New macro. + (ACL_NOT_WELL_SUPPORTED): On MacOS X, also handle ENOENT. + * lib/acl.c (qset_acl): Add different code branch for !MODE_INSIDE_ACL. + If MODE_INSIDE_ACL, don't assume that every system has the same text + representation for ACLs as FreeBSD. + * lib/copy-acl.c (copy_acl): Add support for platforms with + !MODE_INSIDE_ACL. + * lib/file-has-acl.c (file_has_acl): Likewise. + * m4/acl.m4 (gl_FUNC_ACL): Test for some functions that are witness + of FreeBSD or MacOS X, respectively. + +2008-05-22 Bruno Haible <[EMAIL PROTECTED]> + * lib/acl.h: Don't include <sys/acl.h>. (GETACLCNT): Move fallback to lib/acl-internal.h. * lib/acl-internal.h: Include <sys/acl.h> here. diff --git a/lib/acl-internal.h b/lib/acl-internal.h index c23d6f4..75bca17 100644 --- a/lib/acl-internal.h +++ b/lib/acl-internal.h @@ -84,8 +84,21 @@ # define acl_from_mode(mode) (NULL) #endif -#define ACL_NOT_WELL_SUPPORTED(Err) \ - ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY) +/* Set to 1 if a file's mode is implicit by the ACL. + Set to 0 if a file's mode is stored independently from the ACL. */ +#if HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP /* MacOS X */ +# define MODE_INSIDE_ACL 0 +#else +# define MODE_INSIDE_ACL 1 +#endif + +#if defined __APPLE__ && defined __MACH__ /* MacOS X */ +# define ACL_NOT_WELL_SUPPORTED(Err) \ + ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY || (Err) == ENOENT) +#else +# define ACL_NOT_WELL_SUPPORTED(Err) \ + ((Err) == ENOTSUP || (Err) == ENOSYS || (Err) == EINVAL || (Err) == EBUSY) +#endif /* Define a replacement for acl_entries if needed. */ #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE && !HAVE_ACL_ENTRIES diff --git a/lib/acl.c b/lib/acl.c index 10499a0..7655d1b 100644 --- a/lib/acl.c +++ b/lib/acl.c @@ -48,32 +48,42 @@ chmod_or_fchmod (const char *name, int desc, mode_t mode) int qset_acl (char const *name, int desc, mode_t mode) { -#if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE +#if USE_ACL +# if MODE_INSIDE_ACL +# if HAVE_ACL_SET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e draft 17 (abandoned) specific version. */ + /* Linux, FreeBSD, IRIX, Tru64 */ - /* We must also have have_acl_from_text and acl_delete_def_file. + /* We must also have acl_from_text and acl_delete_def_file. (acl_delete_def_file could be emulated with acl_init followed by acl_set_file, but acl_set_file with an empty acl is unspecified.) */ -# ifndef HAVE_ACL_FROM_TEXT -# error Must have acl_from_text (see POSIX 1003.1e draft 17). -# endif -# ifndef HAVE_ACL_DELETE_DEF_FILE -# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). -# endif +# ifndef HAVE_ACL_FROM_TEXT +# error Must have acl_from_text (see POSIX 1003.1e draft 17). +# endif +# ifndef HAVE_ACL_DELETE_DEF_FILE +# error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). +# endif acl_t acl; int ret; - if (HAVE_ACL_FROM_MODE) + if (HAVE_ACL_FROM_MODE) /* Linux */ { acl = acl_from_mode (mode); if (!acl) return -1; } - else + else /* FreeBSD, IRIX, Tru64 */ { + /* If we were to create the ACL using the functions acl_init(), + acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(), + acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we + would need to create a qualifier. I don't know how to do this. + So create it using acl_from_text(). */ + +# if HAVE_ACL_DELETE_FD_NP && HAVE_ACL_DELETE_FILE_NP /* FreeBSD */ char acl_text[] = "u::---,g::---,o::---"; if (mode & S_IRUSR) acl_text[ 3] = 'r'; @@ -89,6 +99,9 @@ qset_acl (char const *name, int desc, mode_t mode) acl = acl_from_text (acl_text); if (!acl) return -1; +# else /* Unknown flavor of POSIX-like ACLs */ + return chmod_or_fchmod (name, desc, mode); +# endif } if (HAVE_ACL_SET_FD && desc != -1) ret = acl_set_fd (desc, acl); @@ -124,10 +137,8 @@ qset_acl (char const *name, int desc, mode_t mode) return -1; } return 0; -#else - -# if USE_ACL && defined ACL_NO_TRIVIAL +# elif defined ACL_NO_TRIVIAL /* Solaris 10, with NFSv4 ACLs. */ acl_t *aclp; char acl_text[] = "user::---,group::---,mask:---,other:---"; @@ -158,10 +169,66 @@ qset_acl (char const *name, int desc, mode_t mode) return acl_result; } } -# endif return chmod_or_fchmod (name, desc, mode); +# else /* Unknown flavor of ACLs */ + return chmod_or_fchmod (name, desc, mode); +# endif +# else /* !MODE_INSIDE_ACL */ +# if HAVE_ACL_SET_FILE && HAVE_ACL_FREE + /* POSIX 1003.1e draft 17 (abandoned) specific version. */ + /* MacOS X */ + + acl_t acl; + int ret; + + /* Remove the ACL if the file has ACLs. */ + if (HAVE_ACL_GET_FD && desc != -1) + acl = acl_get_fd (desc); + else + acl = acl_get_file (name, ACL_TYPE_ACCESS); + if (acl) + { +# if HAVE_ACL_COPY_EXT_NATIVE && HAVE_ACL_CREATE_ENTRY_NP /* MacOS X */ + static const char empty_acl_text[] = "!#acl 1\n"; +# else /* Unknown flavor of POSIX-like ACLs */ +# error Unknown flavor of POSIX-like ACLs - add support for your platform. +# endif + + acl = acl_from_text (empty_acl_text); + if (acl) + { + 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; + + acl_free (acl); + + if (ACL_NOT_WELL_SUPPORTED (saved_errno)) + { + if (chmod_or_fchmod (name, desc, mode) != 0) + saved_errno = errno; + else + return 0; + } + errno = saved_errno; + return -1; + } + } + } + + return chmod_or_fchmod (name, desc, mode); +# else /* Unknown flavor of ACLs */ + return chmod_or_fchmod (name, desc, mode); +# endif +# endif +#else /* !USE_ACL */ + return chmod_or_fchmod (name, desc, mode); #endif } diff --git a/lib/copy-acl.c b/lib/copy-acl.c index f5a879d..97d2087 100644 --- a/lib/copy-acl.c +++ b/lib/copy-acl.c @@ -40,6 +40,7 @@ copy_acl (const char *src_name, int source_desc, const char *dst_name, #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ acl_t acl; if (HAVE_ACL_GET_FD && source_desc != -1) @@ -70,12 +71,13 @@ copy_acl (const char *src_name, int source_desc, const char *dst_name, int n = acl_entries (acl); acl_free (acl); - /* On most hosts an ACL is trivial if n == 3, and it cannot be - less than 3. On IRIX 6.5 it is also trivial if n == -1. + /* On most hosts with MODE_INSIDE_ACL an ACL is trivial if n == 3, + and it cannot be less than 3. On IRIX 6.5 it is also trivial if + n == -1. For simplicity and safety, assume the ACL is trivial if n <= 3. Also see file-has-acl.c for some of the other possibilities; it's not clear whether that complexity is needed here. */ - if (n <= 3) + if (n <= 3 * MODE_INSIDE_ACL) { if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) saved_errno = errno; @@ -97,10 +99,10 @@ copy_acl (const char *src_name, int source_desc, const char *dst_name, else acl_free (acl); - if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) { - /* We did not call chmod so far, so the special bits have not yet - been set. */ + /* 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. */ if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0) { diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index c9786e6..c69d012 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -1,6 +1,6 @@ /* Test whether a file has a nontrivial access control list. - Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2005-2008 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,6 +47,7 @@ file_has_acl (char const *name, struct stat const *sb) #elif USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */ + /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ int ret; if (HAVE_ACL_EXTENDED_FILE) @@ -56,7 +57,7 @@ file_has_acl (char const *name, struct stat const *sb) acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS); if (acl) { - ret = (3 < acl_entries (acl)); + ret = (3 * MODE_INSIDE_ACL < acl_entries (acl)); acl_free (acl); if (ret == 0 && S_ISDIR (sb->st_mode)) { diff --git a/m4/acl.m4 b/m4/acl.m4 index 2916a00..72d4b4a 100644 --- a/m4/acl.m4 +++ b/m4/acl.m4 @@ -1,5 +1,5 @@ # acl.m4 - check for access control list (ACL) primitives -# serial 3 +# serial 4 # Copyright (C) 2002, 2004-2008 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -35,7 +35,9 @@ AC_DEFUN([gl_FUNC_ACL], AC_CHECK_FUNCS( [acl_get_file acl_get_fd acl_set_file acl_set_fd \ acl_free acl_from_mode acl_from_text \ - acl_delete_def_file acl_extended_file]) + acl_delete_def_file acl_extended_file \ + acl_delete_fd_np acl_delete_file_np \ + acl_copy_ext_native acl_create_entry_np]) if test $ac_cv_func_acl_get_file = yes; then # If the acl_get_file bug is detected, disable all ACL support. gl_ACL_GET_FILE( , [use_acl=0]) -- 1.5.4.1