From ceb5e1790ec098f09dc388ca25cba015f224dc51 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Mon, 5 Sep 2011 23:45:11 +0200 Subject: [PATCH] acl: Improve support of NFSv4 ACLs on Solaris 10 (newer version). * lib/acl-internal.h (acl_nontrivial): Declare also on newer Solaris 10. * lib/file-has-acl.c (acl_nontrivial): Define also on newer Solaris 10. (acl_ace_nontrivial): Likewise. Recognize the trivial ACLs with 6 ACEs. * lib/copy-acl.c (qcopy_acl): On newer Solaris 10, use acl or facl instead of acl_get, facl_get, acl_set, facl_set. --- ChangeLog | 10 ++++ lib/acl-internal.h | 2 +- lib/copy-acl.c | 2 +- lib/file-has-acl.c | 131 +++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 123 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a141528b..3c591d80c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2011-09-05 Bruno Haible + acl: Improve support of NFSv4 ACLs on Solaris 10 (newer version). + * lib/acl-internal.h (acl_nontrivial): Declare also on newer Solaris + 10. + * lib/file-has-acl.c (acl_nontrivial): Define also on newer Solaris 10. + (acl_ace_nontrivial): Likewise. Recognize the trivial ACLs with 6 ACEs. + * lib/copy-acl.c (qcopy_acl): On newer Solaris 10, use acl or facl + instead of acl_get, facl_get, acl_set, facl_set. + +2011-09-05 Bruno Haible + copy-file: Try unit tests on more file systems. * tests/test-copy-file-1.sh: New file. * tests/test-copy-file-2.sh: New file. diff --git a/lib/acl-internal.h b/lib/acl-internal.h index 0818d698e..00b50022f 100644 --- a/lib/acl-internal.h +++ b/lib/acl-internal.h @@ -183,7 +183,7 @@ extern int acl_access_nontrivial (acl_t); # define MODE_INSIDE_ACL 1 # endif -# if !defined ACL_NO_TRIVIAL /* Solaris <= 10, Cygwin */ +# if !(defined ACL_NO_TRIVIAL && 0) /* Solaris <= 10, Cygwin */ /* Return 1 if the given ACL is non-trivial. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ diff --git a/lib/copy-acl.c b/lib/copy-acl.c index 4f2ea06a6..c46fbda35 100644 --- a/lib/copy-acl.c +++ b/lib/copy-acl.c @@ -181,7 +181,7 @@ qcopy_acl (const char *src_name, int source_desc, const char *dst_name, #elif USE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ -# if defined ACL_NO_TRIVIAL +# if defined ACL_NO_TRIVIAL && 0 /* Solaris 10 (newer version), which has additional API declared in (acl_t) and implemented in libsec (acl_set, acl_trivial, acl_fromtext, ...). */ diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 2ee6ba210..57ebadd2b 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -120,7 +120,7 @@ acl_access_nontrivial (acl_t acl) #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ -# if !defined ACL_NO_TRIVIAL /* Solaris <= 10, Cygwin */ +# if !(defined ACL_NO_TRIVIAL && 0) /* Solaris <= 10, Cygwin */ /* Test an ACL retrieved with GETACL. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. @@ -167,7 +167,7 @@ acl_ace_nontrivial (int count, ace_t *entries) int old_convention = 0; for (i = 0; i < count; i++) - if (entries[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_OTHER)) + if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) { old_convention = 1; break; @@ -183,28 +183,119 @@ acl_ace_nontrivial (int count, ace_t *entries) If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat(). If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat(). We don't need to check ace->a_who in these cases. */ - if (!(ace->a_type == ALLOW - && (ace->a_flags == ACE_OWNER - || ace->a_flags == ACE_GROUP - || ace->a_flags == ACE_OTHER))) + if (!(ace->a_type == OLD_ALLOW + && (ace->a_flags == OLD_ACE_OWNER + || ace->a_flags == OLD_ACE_GROUP + || ace->a_flags == OLD_ACE_OTHER))) return 1; } else - /* Running on Solaris 10 (newer version) or Solaris 11. */ - for (i = 0; i < count; i++) - { - ace_t *ace = &entries[i]; + { + /* Running on Solaris 10 (newer version) or Solaris 11. */ + unsigned int access_masks[6] = + { + 0, /* owner@ deny */ + 0, /* owner@ allow */ + 0, /* group@ deny */ + 0, /* group@ allow */ + 0, /* everyone@ deny */ + 0 /* everyone@ allow */ + }; + + for (i = 0; i < count; i++) + { + ace_t *ace = &entries[i]; + unsigned int index1; + unsigned int index2; + + if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE) + index1 = 1; + else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE) + index1 = 0; + else + return 1; - if (!(ace->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE - && (ace->a_flags == NEW_ACE_OWNER - || ace->a_flags - == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP) - || ace->a_flags == ACE_EVERYONE) - && (ace->a_access_mask - & ~(NEW_ACE_READ_DATA | NEW_ACE_WRITE_DATA | NEW_ACE_EXECUTE)) - == 0)) - return 1; - } + if (ace->a_flags == NEW_ACE_OWNER) + index2 = 0; + else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP)) + index2 = 2; + else if (ace->a_flags == ACE_EVERYONE) + index2 = 4; + else + return 1; + + access_masks[index1 + index2] |= ace->a_access_mask; + } + + /* The same bit shouldn't be both allowed and denied. */ + if (access_masks[0] & access_masks[1]) + return 1; + if (access_masks[2] & access_masks[3]) + return 1; + if (access_masks[4] & access_masks[5]) + return 1; + + /* Check minimum masks. */ + if ((NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER) + & ~ access_masks[1]) + return 1; + access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER); + if ((NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER) + & ~ access_masks[4]) + return 1; + access_masks[4] &= ~(NEW_ACE_WRITE_NAMED_ATTRS + | NEW_ACE_WRITE_ATTRIBUTES + | NEW_ACE_WRITE_ACL + | NEW_ACE_WRITE_OWNER); + if ((NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE) + & ~ access_masks[5]) + return 1; + access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS + | NEW_ACE_READ_ATTRIBUTES + | NEW_ACE_READ_ACL + | NEW_ACE_SYNCHRONIZE); + + /* Check the allowed or denied bits. */ + if ((access_masks[0] | access_masks[1]) + != (NEW_ACE_READ_DATA + | NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA + | NEW_ACE_EXECUTE)) + return 1; + if ((access_masks[2] | access_masks[3]) + != (NEW_ACE_READ_DATA + | NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA + | NEW_ACE_EXECUTE)) + return 1; + if ((access_masks[4] | access_masks[5]) + != (NEW_ACE_READ_DATA + | NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA + | NEW_ACE_EXECUTE)) + return 1; + + /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are + either both allowed or both denied. */ + if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0) + != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0)) + return 1; + } return 0; } -- 2.11.0