bug-gnulib
[Top][All Lists]
Advanced

[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
  
    {





reply via email to

[Prev in Thread] Current Thread [Next in Thread]