[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: acl: request for testing
From: |
Bruno Haible |
Subject: |
Re: acl: request for testing |
Date: |
Tue, 10 Jun 2008 02:44:21 +0200 |
User-agent: |
KMail/1.5.4 |
Hi Jim,
> FYI, building failed on Solaris 10,
>
> file-has-acl.c: In function 'acl_ace_nontrivial':
> file-has-acl.c:166: error: 'ALLOW' undeclared (first use in this function)
> file-has-acl.c:166: error: (Each undeclared identifier is reported only once
> file-has-acl.c:166: error: for each function it appears in.)
> file-has-acl.c:169: error: 'ACE_OTHER' undeclared (first use in this
> function)
> make[3]: *** [file-has-acl.o] Error 1
>
> With this patch, it compiles:
But you got no link error? So you must be on a Solaris 10+ system with
augmented ACL API.
> +# if defined ACE_GETACL && defined ALLOW && defined ACE_OWNER
It's the macro ACE_OTHER, not ACE_OWNER, which was removed. I've now found
a copy of the "augmented" Solaris 10+ <sys/acl.h>. The differences between
these two versions are:
- New acl_t type
- New ACL_NO_TRIVIAL macro
- ACE_OTHER macro replaced with ACE_EVERYONE macro
- ACE_OWNER, ACE_GROUP changed their values(!)
- many other ACE_* macros were changed
- ACE_READ_DATA, ACE_WRITE_DATA, ACE_EXECUTE changed their values(!)
- ALLOW, DENY macros removed(!)
- New EACL_* macros for aclcheck
- New functions
acl_check
acl_free
acl_fromtext
acl_get
acl_set
acl_strip
acl_totext
acl_trivial
facl_get
facl_set
So, Sun has shipped an ABI changed in a Solaris 10 patch. Great. Fun.
Of course, everyone expects that coreutils programs, built on a pristine
Solaris 10, still work after the Solaris 10 patch is applied. Here's the
workaround.
2008-06-09 Bruno Haible <address@hidden>
Work around the Solaris 10 ACE ACLs ABI change.
* lib/acl-internal.h (acl_nontrivial, acl_ace_nontrivial): Don't
declare if ACL_NO_TRIVIAL is present.
(ACE_ACCESS_ALLOWED_ACE_TYPE, ACE_ACCESS_DENIED_ACE_TYPE,
NEW_ACE_OWNER, NEW_ACE_GROUP, NEW_ACE_IDENTIFIER_GROUP, ACE_EVERYONE,
NEW_ACE_READ_DATA, NEW_ACE_WRITE_DATA, NEW_ACE_EXECUTE): New macros.
* lib/file-has-acl.c (acl_nontrivial, acl_ace_nontrivial): Don't
define if ACL_NO_TRIVIAL is present.
(acl_ace_nontrivial): Detect whether the old or new ABI is in use,
and use the current ABI.
(file_has_acl): Use same #if condition as elsewhere.
* lib/set-mode-acl.c (qset_acl): Detect whether the old or new ABI is
in use, and use the current ABI.
* doc/acl-resources.txt: More doc about newer Solaris 10 versions.
Reported by Jim Meyering.
*** doc/acl-resources.txt.orig 2008-06-10 02:39:42.000000000 +0200
--- doc/acl-resources.txt 2008-06-09 23:56:05.000000000 +0200
***************
*** 90,95 ****
--- 90,111 ----
aclsort
acltomode
acltotext
+ Additionally in Solaris 10 patch 118833-17 (<sys/acl.h> version 1.15):
+ acl_t type
+ ACL_NO_TRIVIAL macro
+ ACE_OTHER macro replaced with ACE_EVERYONE macro
+ ACE_OWNER, ACE_GROUP changed their values(!)
+ ALLOW, DENY macros removed(!)
+ acl_check
+ acl_free
+ acl_fromtext
+ acl_get
+ acl_set
+ acl_strip
+ acl_totext
+ acl_trivial
+ facl_get
+ facl_set
Utilities:
getfacl
setfacl
*** lib/acl-internal.h.orig 2008-06-10 02:39:42.000000000 +0200
--- lib/acl-internal.h 2008-06-10 01:33:36.000000000 +0200
***************
*** 168,182 ****
# define MODE_INSIDE_ACL 1
# endif
/* Return 1 if the given ACL is non-trivial.
Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
extern int acl_nontrivial (int count, aclent_t *entries);
! # ifdef ACE_GETACL
/* Test an ACL retrieved with ACE_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. */
extern int acl_ace_nontrivial (int count, ace_t *entries);
# endif
# elif HAVE_GETACL /* HP-UX */
--- 168,203 ----
# define MODE_INSIDE_ACL 1
# endif
+ # if !defined ACL_NO_TRIVIAL /* 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. */
extern int acl_nontrivial (int count, aclent_t *entries);
! # ifdef ACE_GETACL /* Solaris 10 */
!
/* Test an ACL retrieved with ACE_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. */
extern int acl_ace_nontrivial (int count, ace_t *entries);
+
+ /* Definitions for when the built executable is executed on Solaris 10
+ (newer version) or Solaris 11. */
+ /* For a_type. */
+ # define ACE_ACCESS_ALLOWED_ACE_TYPE 0 /* replaces ALLOW */
+ # define ACE_ACCESS_DENIED_ACE_TYPE 1 /* replaces DENY */
+ /* For a_flags. */
+ # define NEW_ACE_OWNER 0x1000
+ # define NEW_ACE_GROUP 0x2000
+ # define NEW_ACE_IDENTIFIER_GROUP 0x0040
+ # define ACE_EVERYONE 0x4000
+ /* For a_access_mask. */
+ # define NEW_ACE_READ_DATA 0x001 /* corresponds to 'r' */
+ # define NEW_ACE_WRITE_DATA 0x002 /* corresponds to 'w' */
+ # define NEW_ACE_EXECUTE 0x004 /* corresponds to 'x' */
+
+ # endif
+
# endif
# elif HAVE_GETACL /* HP-UX */
*** lib/file-has-acl.c.orig 2008-06-10 02:39:42.000000000 +0200
--- lib/file-has-acl.c 2008-06-10 01:38:19.000000000 +0200
***************
*** 120,125 ****
--- 120,127 ----
#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. */
***************
*** 146,152 ****
return 0;
}
! # if defined ACE_GETACL && defined ALLOW && defined ACE_OWNER
/* Test an ACL retrieved with ACE_GETACL.
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
--- 148,154 ----
return 0;
}
! # ifdef ACE_GETACL
/* Test an ACL retrieved with ACE_GETACL.
Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
***************
*** 156,177 ****
{
int i;
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;
- }
return 0;
}
# endif
#elif USE_ACL && HAVE_GETACL /* HP-UX */
--- 158,216 ----
{
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++)
! 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 */
***************
*** 310,316 ****
# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
! # if HAVE_ACL_TRIVIAL
/* Solaris 10 (newer version), which has additional API declared in
<sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
--- 349,355 ----
# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
! # 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,
*** lib/set-mode-acl.c.orig 2008-06-10 02:39:42.000000000 +0200
--- lib/set-mode-acl.c 2008-06-10 02:39:39.000000000 +0200
***************
*** 249,282 ****
# ifdef ACE_GETACL
/* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
file systems (whereas the other ones are used in UFS file systems). */
- {
- ace_t entries[3];
- int ret;
! entries[0].a_type = ALLOW;
! entries[0].a_flags = ACE_OWNER;
! entries[0].a_who = 0; /* irrelevant */
! entries[0].a_access_mask = (mode >> 6) & 7;
! entries[1].a_type = ALLOW;
! entries[1].a_flags = ACE_GROUP;
! entries[1].a_who = 0; /* irrelevant */
! entries[1].a_access_mask = (mode >> 3) & 7;
! entries[2].a_type = ALLOW;
! entries[2].a_flags = ACE_OTHER;
! entries[2].a_who = 0;
! entries[2].a_access_mask = mode & 7;
! if (desc != -1)
! ret = facl (desc, ACE_SETACL, sizeof (entries) / sizeof (aclent_t),
entries);
! else
! ret = acl (name, ACE_SETACL, sizeof (entries) / sizeof (aclent_t),
entries);
! if (ret < 0 && errno != EINVAL && errno != ENOTSUP)
{
! if (errno == ENOSYS)
! return chmod_or_fchmod (name, desc, mode);
! return -1;
}
}
# endif
{
--- 249,366 ----
# ifdef ACE_GETACL
/* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
file systems (whereas the other ones are used in UFS file systems). */
! /* 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?
! We fetch the existing ACL. 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 convention;
! {
! int count;
! ace_t *entries;
!
! for (;;)
{
! if (desc != -1)
! count = facl (desc, ACE_GETACLCNT, 0, NULL);
! else
! count = acl (name, ACE_GETACLCNT, 0, NULL);
! if (count <= 0)
! {
! convention = -1;
! break;
! }
! entries = (ace_t *) malloc (count * sizeof (ace_t));
! if (entries == NULL)
! {
! errno = ENOMEM;
! return -1;
! }
! if ((desc != -1
! ? facl (desc, ACE_GETACL, count, entries)
! : acl (name, ACE_GETACL, count, entries))
! == count)
! {
! int i;
!
! convention = 0;
! for (i = 0; i < count; i++)
! if (entries[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_OTHER))
! {
! convention = 1;
! break;
! }
! free (entries);
! break;
! }
! /* Huh? The number of ACL entries changed since the last call.
! Repeat. */
! free (entries);
}
}
+
+ if (convention >= 0)
+ {
+ ace_t entries[3];
+ int ret;
+
+ if (convention)
+ {
+ /* Running on Solaris 10. */
+ entries[0].a_type = ALLOW;
+ entries[0].a_flags = ACE_OWNER;
+ entries[0].a_who = 0; /* irrelevant */
+ entries[0].a_access_mask = (mode >> 6) & 7;
+ entries[1].a_type = ALLOW;
+ entries[1].a_flags = ACE_GROUP;
+ entries[1].a_who = 0; /* irrelevant */
+ entries[1].a_access_mask = (mode >> 3) & 7;
+ entries[2].a_type = ALLOW;
+ entries[2].a_flags = ACE_OTHER;
+ entries[2].a_who = 0;
+ entries[2].a_access_mask = mode & 7;
+ }
+ else
+ {
+ /* Running on Solaris 10 (newer version) or Solaris 11. */
+ entries[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ entries[0].a_flags = NEW_ACE_OWNER;
+ entries[0].a_who = 0; /* irrelevant */
+ entries[0].a_access_mask =
+ (mode & 0400 ? NEW_ACE_READ_DATA : 0)
+ | (mode & 0200 ? NEW_ACE_WRITE_DATA : 0)
+ | (mode & 0100 ? NEW_ACE_EXECUTE : 0);
+ entries[1].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ entries[1].a_flags = NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP;
+ entries[1].a_who = 0; /* irrelevant */
+ entries[1].a_access_mask =
+ (mode & 0040 ? NEW_ACE_READ_DATA : 0)
+ | (mode & 0020 ? NEW_ACE_WRITE_DATA : 0)
+ | (mode & 0010 ? NEW_ACE_EXECUTE : 0);
+ entries[2].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ entries[2].a_flags = ACE_EVERYONE;
+ entries[2].a_who = 0;
+ entries[2].a_access_mask =
+ (mode & 0004 ? NEW_ACE_READ_DATA : 0)
+ | (mode & 0002 ? NEW_ACE_WRITE_DATA : 0)
+ | (mode & 0001 ? NEW_ACE_EXECUTE : 0);
+ }
+ if (desc != -1)
+ ret = facl (desc, ACE_SETACL,
+ sizeof (entries) / sizeof (aclent_t), entries);
+ else
+ ret = acl (name, ACE_SETACL,
+ sizeof (entries) / sizeof (aclent_t), entries);
+ if (ret < 0 && errno != EINVAL && errno != ENOTSUP)
+ {
+ if (errno == ENOSYS)
+ return chmod_or_fchmod (name, desc, mode);
+ return -1;
+ }
+ }
# endif
{