/* Test whether a file has a nontrivial access control list.
- Copyright (C) 2002-2003, 2005-2008 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2009 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
# if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */
acl_entry_t ace;
- int at_end;
+ int got_one;
- for (at_end = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
- !at_end;
- at_end = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
+ for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
+ got_one > 0;
+ got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
{
acl_tag_t tag;
if (acl_get_tag_type (ace, &tag) < 0)
if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
return 1;
}
- return 0;
+ return got_one;
# else /* IRIX, Tru64 */
# if HAVE_ACL_TO_SHORT_TEXT /* IRIX */
#elif USE_ACL && HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+# if !defined ACL_NO_TRIVIAL /* Solaris <= 10, Cygwin */
+
/* Test an ACL retrieved with GETACL.
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
return 0;
}
-# ifdef ACE_GETACL
+# ifdef ACE_GETACL
/* Test an ACL retrieved with ACE_GETACL.
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
{
int i;
+ /* The flags in the ace_t structure changed in a binary incompatible way
+ when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
+ How to distinguish the two conventions at runtime?
+ In the old convention, usually three ACEs have a_flags = ACE_OWNER /
+ ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new
+ convention, these values are not used. */
+ int old_convention = 0;
+
for (i = 0; i < count; i++)
- {
- ace_t *ace = &entries[i];
-
- /* Note: 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)))
- return 1;
- }
+ if (entries[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_OTHER))
+ {
+ old_convention = 1;
+ break;
+ }
+
+ if (old_convention)
+ /* Running on Solaris 10. */
+ for (i = 0; i < count; i++)
+ {
+ ace_t *ace = &entries[i];
+
+ /* Note:
+ 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)))
+ return 1;
+ }
+ else
+ /* Running on Solaris 10 (newer version) or Solaris 11. */
+ for (i = 0; i < count; i++)
+ {
+ ace_t *ace = &entries[i];
+
+ 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;
+ }
+
return 0;
}
+# endif
+
# endif
#elif USE_ACL && HAVE_GETACL /* HP-UX */
# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
-# if HAVE_ACL_TRIVIAL
+# if defined ACL_NO_TRIVIAL
/* Solaris 10 (newer version), which has additional API declared in
<sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,