bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

acl: add support for HP-UX ACLs


From: Bruno Haible
Subject: acl: add support for HP-UX ACLs
Date: Sun, 8 Jun 2008 19:08:09 +0200
User-agent: KMail/1.5.4

So far, the tests fail on HP-UX 11:
  file_has_acl("tmpfile0") returned no, expected yes
  FAIL: test-file-has-acl.sh
  PASS: test-set-mode-acl.sh
  files tmpfile0 and tmpfile2 have different number of ACLs: 4 and 3
  FAIL: test-copy-acl.sh

The HP-UX ACL API is similar to the one of Solaris 7-9. The only difference is
that in order to test whether an ACL is trivial, or in order to setup a trivial
ACL, you need the owner and group id of the file.

This is a straightforward rewrite of the code for FreeBSD or Solaris.


2008-06-08  Bruno Haible  <address@hidden>

        Add support for HP-UX ACLs.
        * lib/acl-internal.h (acl_nontrivial): New declaration.
        * lib/file-has-acl.c (acl_nontrivial): New function.
        (file_has_acl): Add implementation using HP-UX 11 ACL API.
        * lib/set-mode-acl.c (qset_acl): Likewise.
        * lib/copy-acl.c (qcopy_acl): Likewise.

*** lib/acl-internal.h.orig     2008-06-08 19:01:46.000000000 +0200
--- lib/acl-internal.h  2008-06-08 18:48:46.000000000 +0200
***************
*** 179,184 ****
--- 179,190 ----
  extern int acl_ace_nontrivial (int count, ace_t *entries);
  #  endif
  
+ # elif HAVE_GETACL /* HP-UX */
+ 
+ /* 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, struct acl_entry *entries, struct stat 
*sb);
+ 
  # endif
  
  #endif
*** lib/file-has-acl.c.orig     2008-06-08 19:01:46.000000000 +0200
--- lib/file-has-acl.c  2008-06-08 19:00:38.000000000 +0200
***************
*** 174,179 ****
--- 174,200 ----
  
  # endif
  
+ #elif USE_ACL && HAVE_GETACL /* HP-UX */
+ 
+ /* Return 1 if the given ACL is non-trivial.
+    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
+ int
+ acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb)
+ {
+   int i;
+ 
+   for (i = 0; i < count; i++)
+     {
+       struct acl_entry *ace = &entries[i];
+ 
+       if (!((ace->uid == sb->st_uid && ace->gid == ACL_NSGROUP)
+           || (ace->uid == ACL_NSUSER && ace->gid == sb->st_gid)
+           || (ace->uid == ACL_NSUSER && ace->gid == ACL_NSGROUP)))
+       return 1;
+     }
+   return 0;
+ }
+ 
  #endif
  
  
***************
*** 371,376 ****
--- 392,435 ----
        return 0;
  #  endif
  
+ # elif HAVE_GETACL /* HP-UX */
+ 
+       int count;
+       struct acl_entry entries[NACLENTRIES];
+ 
+       for (;;)
+       {
+         count = getacl (name, 0, NULL);
+ 
+         if (count < 0)
+           return (errno == ENOSYS || errno == EOPNOTSUPP ? 0 : -1);
+ 
+         if (count == 0)
+           return 0;
+ 
+         if (count > NACLENTRIES)
+           /* If NACLENTRIES cannot be trusted, use dynamic memory
+              allocation.  */
+           abort ();
+ 
+         /* If there are more than 3 entries, there cannot be only the
+            (uid,%), (%,gid), (%,%) entries.  */
+         if (count > 3)
+           return 1;
+ 
+         if (getacl (name, count, entries) == count)
+           {
+             struct stat statbuf;
+ 
+             if (stat (name, &statbuf) < 0)
+               return -1;
+ 
+             return acl_nontrivial (count, entries, &statbuf);
+           }
+         /* Huh? The number of ACL entries changed since the last call.
+            Repeat.  */
+       }
+ 
  # endif
      }
  #endif
*** lib/set-mode-acl.c.orig     2008-06-08 19:01:46.000000000 +0200
--- lib/set-mode-acl.c  2008-06-08 18:16:15.000000000 +0200
***************
*** 315,320 ****
--- 315,362 ----
  
  #  endif
  
+ # elif HAVE_GETACL /* HP-UX */
+ 
+   struct stat statbuf;
+   struct acl_entry entries[3];
+   int ret;
+ 
+   if (desc != -1)
+     ret = fstat (desc, &statbuf);
+   else
+     ret = stat (name, &statbuf);
+   if (ret < 0)
+     return -1;
+ 
+   entries[0].uid = statbuf.st_uid;
+   entries[0].gid = ACL_NSGROUP;
+   entries[0].mode = (mode >> 6) & 7;
+   entries[1].uid = ACL_NSUSER;
+   entries[1].gid = statbuf.st_gid;
+   entries[1].mode = (mode >> 3) & 7;
+   entries[2].uid = ACL_NSUSER;
+   entries[2].gid = ACL_NSGROUP;
+   entries[2].mode = mode & 7;
+ 
+   if (desc != -1)
+     ret = fsetacl (desc, sizeof (entries) / sizeof (struct acl_entry), 
entries);
+   else
+     ret = setacl (name, sizeof (entries) / sizeof (struct acl_entry), 
entries);
+   if (ret < 0)
+     {
+       if (errno == ENOSYS || errno == EOPNOTSUPP)
+       return chmod_or_fchmod (name, desc, mode);
+       return -1;
+     }
+   
+   if (mode & (S_ISUID | S_ISGID | S_ISVTX))
+     {
+       /* We did not call chmod so far, so the special bits have not yet
+        been set.  */
+       return chmod_or_fchmod (name, desc, mode);
+     }
+   return 0;
+ 
  # else /* Unknown flavor of ACLs */
    return chmod_or_fchmod (name, desc, mode);
  # endif
*** lib/copy-acl.c.orig 2008-06-08 19:01:46.000000000 +0200
--- lib/copy-acl.c      2008-06-08 18:57:48.000000000 +0200
***************
*** 392,397 ****
--- 392,475 ----
  
  # endif
  
+ #elif USE_ACL && HAVE_GETACL /* HP-UX */
+ 
+   int count;
+   struct acl_entry entries[NACLENTRIES];
+   int ret;
+ 
+   for (;;)
+     {
+       count = (source_desc != -1
+              ? fgetacl (source_desc, 0, NULL)
+              : getacl (src_name, 0, NULL));
+ 
+       if (count < 0)
+       {
+         if (errno == ENOSYS || errno == EOPNOTSUPP)
+           {
+             count = 0;
+             break;
+           }
+         else
+           return -2;
+       }
+ 
+       if (count == 0)
+       break;
+ 
+       if (count > NACLENTRIES)
+       /* If NACLENTRIES cannot be trusted, use dynamic memory allocation.  */
+       abort ();
+ 
+       if ((source_desc != -1
+          ? fgetacl (source_desc, count, entries)
+          : getacl (src_name, count, entries))
+         == count)
+       break;
+       /* Huh? The number of ACL entries changed since the last call.
+        Repeat.  */
+     }
+ 
+   if (count == 0)
+     return qset_acl (dst_name, dest_desc, mode);
+ 
+   ret = (dest_desc != -1
+        ? fsetacl (dest_desc, count, entries)
+        : setacl (dst_name, count, entries));
+   if (ret < 0)
+     {
+       int saved_errno = errno;
+ 
+       if (errno == ENOSYS || errno == EOPNOTSUPP)
+       {
+         struct stat source_statbuf;
+ 
+         if ((source_desc != -1
+              ? fstat (source_desc, &source_statbuf)
+              : stat (src_name, &source_statbuf)) == 0)
+           {
+             if (!acl_nontrivial (count, entries, &source_statbuf))
+               return chmod_or_fchmod (dst_name, dest_desc, mode);
+           }
+         else
+           saved_errno = errno;
+       }
+ 
+       chmod_or_fchmod (dst_name, dest_desc, mode);
+       errno = saved_errno;
+       return -1;
+     }
+ 
+   if (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.  */
+ 
+       return chmod_or_fchmod (dst_name, dest_desc, mode);
+     }
+   return 0;
+ 
  #else
  
    return qset_acl (dst_name, dest_desc, mode);





reply via email to

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