acl: Add support for HP-UX >= 11.11 JFS ACLs.
authorBruno Haible <bruno@clisp.org>
Mon, 13 Jun 2011 00:11:03 +0000 (02:11 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 13 Jun 2011 00:11:03 +0000 (02:11 +0200)
* doc/acl-resources.txt: Add info about the ACL APIs on HP-UX.
* m4/acl.m4 (gl_FUNC_ACL): Also test for HP-UX 11.11 API.
* lib/acl-internal.h [HP-UX 11.11]: Include <aclv.h>.
(acl, aclsort): New declarations.
(aclv_nontrivial): New declaration.
* lib/file-has-acl.c (aclv_nontrivial) [HP-UX 11.11]: New function.
(file_has_acl): Read also the second kind of HP-UX ACLs.
* lib/set-mode-acl.c (qset_acl) [HP-UX 11.11]: Try to set the second
kind of HP-UX ACLs if the first kind fails.
* lib/copy-acl.c (qcopy_acl) [HP-UX 11.11]: Read and set also the
second kind of HP-UX ACLs.
* tests/test-sameacls.c [HP-UX 11.11]: Include <aclv.h>.
(main) [HP-UX 11.11]: Test also whether the second kind of HP-UX ACLs
agree.
* tests/test-file-has-acl.sh (acl_flavor) [HP-UX 11.11]: Set to
hpuxjfs.
Handle hpuxjfs.
* tests/test-set-mode-acl.sh (acl_flavor) [HP-UX 11.11]: Set to
hpuxjfs.
Handle hpuxjfs.
* tests/test-copy-acl.sh (acl_flavor) [HP-UX 11.11]: Set to hpuxjfs.
(func_test_same_acls): Use both lsacl and getacl.
Handle hpuxjfs.
* tests/test-copy-file.sh (acl_flavor) [HP-UX 11.11]: Set to hpuxjfs.
(func_test_same_acls): Use both lsacl and getacl.
Handle hpuxjfs.

12 files changed:
ChangeLog
doc/acl-resources.txt
lib/acl-internal.h
lib/copy-acl.c
lib/file-has-acl.c
lib/set-mode-acl.c
m4/acl.m4
tests/test-copy-acl.sh
tests/test-copy-file.sh
tests/test-file-has-acl.sh
tests/test-sameacls.c
tests/test-set-mode-acl.sh

index 5a0d7af..7af3f05 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,35 @@
 2011-06-12  Bruno Haible  <bruno@clisp.org>
 
+       acl: Add support for HP-UX >= 11.11 JFS ACLs.
+       * doc/acl-resources.txt: Add info about the ACL APIs on HP-UX.
+       * m4/acl.m4 (gl_FUNC_ACL): Also test for HP-UX 11.11 API.
+       * lib/acl-internal.h [HP-UX 11.11]: Include <aclv.h>.
+       (acl, aclsort): New declarations.
+       (aclv_nontrivial): New declaration.
+       * lib/file-has-acl.c (aclv_nontrivial) [HP-UX 11.11]: New function.
+       (file_has_acl): Read also the second kind of HP-UX ACLs.
+       * lib/set-mode-acl.c (qset_acl) [HP-UX 11.11]: Try to set the second
+       kind of HP-UX ACLs if the first kind fails.
+       * lib/copy-acl.c (qcopy_acl) [HP-UX 11.11]: Read and set also the
+       second kind of HP-UX ACLs.
+       * tests/test-sameacls.c [HP-UX 11.11]: Include <aclv.h>.
+       (main) [HP-UX 11.11]: Test also whether the second kind of HP-UX ACLs
+       agree.
+       * tests/test-file-has-acl.sh (acl_flavor) [HP-UX 11.11]: Set to
+       hpuxjfs.
+       Handle hpuxjfs.
+       * tests/test-set-mode-acl.sh (acl_flavor) [HP-UX 11.11]: Set to
+       hpuxjfs.
+       Handle hpuxjfs.
+       * tests/test-copy-acl.sh (acl_flavor) [HP-UX 11.11]: Set to hpuxjfs.
+       (func_test_same_acls): Use both lsacl and getacl.
+       Handle hpuxjfs.
+       * tests/test-copy-file.sh (acl_flavor) [HP-UX 11.11]: Set to hpuxjfs.
+       (func_test_same_acls): Use both lsacl and getacl.
+       Handle hpuxjfs.
+
+2011-06-12  Bruno Haible  <bruno@clisp.org>
+
        acl: Complete the 2010-08-10 fix.
        * lib/file-has-acl.c (file_has_acl) [HP-UX]: Also test against ENOTSUP.
        * lib/set-mode-acl.c (qset_acl) [HP-UX]: Likewise.
index d01e2d6..06fd118 100644 (file)
@@ -243,15 +243,16 @@ Utilities:
   chmod
 
 
-HP-UX ACLs
+HP-UX 11.00 ACLs
 
+Present in HP-UX >= 11.00. On some machines, yields ENOSYS always.
 Manual pages:
-  http://docs.hp.com/en/B2355-60105/acl.2.html
-  http://docs.hp.com/en/B2355-60105/lsacl.1.html
-  http://docs.hp.com/en/B2355-60105/chacl.1.html
-  http://docs.hp.com/en/B2355-60105/getacl.1.html
+  getacl, fgetacl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02261503/c02261503.pdf
+  setacl, fsetacl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02267386/c02267386.pdf
+  lsacl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02261049/c02261049.pdf
+  chacl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c01921575/c01921575.pdf p. 125
 Includes:
-  <acl.h> or <sys/acl.h>, optionally <aclv.h>
+  <acl.h> or <sys/acl.h>
 Library:
   none needed
 Functions:
@@ -259,14 +260,31 @@ Functions:
   fgetacl
   fsetacl
   setacl
-Functions only declared in <aclv.h>:
-  acl
 Utilities:
   lsacl
   chacl
+  chmod
+
+
+HP-UX 11.11 ACLs
+
+Present in HP-UX >= 11.11.
+Manual pages:
+  acl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02254861/c02254861.pdf
+  acl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c01921366/c01921366.pdf p. 27
+  aclsort: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02254876/c02254876.pdf
+  getacl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02261501/c02261501.pdf
+  setacl: http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02267385/c02267385.pdf
+Includes:
+  <aclv.h>
+Library:
+  none needed
+Functions:
+  acl
+  aclsort
+Utilities:
   getacl
   setacl
-  chmod
 
 
 IRIX ACLs
index 0eb11bc..b3160a7 100644 (file)
 # include <acl/libacl.h>
 #endif
 
+/* On HP-UX >= 11.11, additional ACL API is available in <aclv.h>.  */
+#if HAVE_ACLV_H
+# include <sys/types.h>
+# include <aclv.h>
+/* HP-UX 11.11 lacks these declarations.  */
+extern int acl (char *, int, int, struct acl *);
+extern int aclsort (int, int, struct acl *);
+#endif
+
 #include "error.h"
 #include "quote.h"
 
@@ -206,6 +215,14 @@ extern int acl_ace_nontrivial (int count, ace_t *entries);
    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);
 
+#  if HAVE_ACLV_H /* HP-UX >= 11.11 */
+
+/* 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 aclv_nontrivial (int count, struct acl *entries);
+
+#  endif
+
 # elif HAVE_ACLX_GET && 0 /* AIX */
 
 /* TODO */
index d933fa2..4f2ea06 100644 (file)
@@ -410,6 +410,12 @@ qcopy_acl (const char *src_name, int source_desc, const char *dst_name,
 
   int count;
   struct acl_entry entries[NACLENTRIES];
+# if HAVE_ACLV_H
+  int aclv_count;
+  struct acl aclv_entries[NACLVENTRIES];
+# endif
+  int did_chmod;
+  int saved_errno;
   int ret;
 
   for (;;)
@@ -445,42 +451,107 @@ qcopy_acl (const char *src_name, int source_desc, const char *dst_name,
          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)
+# if HAVE_ACLV_H
+  for (;;)
     {
-      int saved_errno = errno;
+      aclv_count = acl ((char *) src_name, ACL_CNT, NACLVENTRIES, aclv_entries);
 
-      if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
+      if (aclv_count < 0)
         {
-          struct stat source_statbuf;
-
-          if ((source_desc != -1
-               ? fstat (source_desc, &source_statbuf)
-               : stat (src_name, &source_statbuf)) == 0)
+          if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
             {
-              if (!acl_nontrivial (count, entries, &source_statbuf))
-                return chmod_or_fchmod (dst_name, dest_desc, mode);
+              count = 0;
+              break;
             }
           else
-            saved_errno = errno;
+            return -2;
         }
 
-      chmod_or_fchmod (dst_name, dest_desc, mode);
-      errno = saved_errno;
-      return -1;
+      if (aclv_count == 0)
+        break;
+
+      if (aclv_count > NACLVENTRIES)
+        /* If NACLVENTRIES cannot be trusted, use dynamic memory allocation.  */
+        abort ();
+
+      if (acl ((char *) src_name, ACL_GET, aclv_count, aclv_entries)
+          == aclv_count)
+        break;
+      /* Huh? The number of ACL entries changed since the last call.
+         Repeat.  */
     }
+# endif
 
-  if (mode & (S_ISUID | S_ISGID | S_ISVTX))
+  if (count == 0)
+# if HAVE_ACLV_H
+    if (aclv_count == 0)
+# endif
+      return qset_acl (dst_name, dest_desc, mode);
+
+  did_chmod = 0; /* set to 1 once the mode bits in 0777 have been set */
+  saved_errno = 0; /* the first non-ignorable error code */
+
+  if (count > 0)
     {
-      /* 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.  */
+      ret = (dest_desc != -1
+             ? fsetacl (dest_desc, count, entries)
+             : setacl (dst_name, count, entries));
+      if (ret < 0 && saved_errno == 0)
+        {
+          saved_errno = errno;
+          if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
+            {
+              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))
+                    saved_errno = 0;
+                }
+              else
+                saved_errno = errno;
+            }
+        }
+      else
+        did_chmod = 1;
+    }
 
-      return chmod_or_fchmod (dst_name, dest_desc, mode);
+# if HAVE_ACLV_H
+  if (aclv_count > 0)
+    {
+      ret = acl ((char *) dst_name, ACL_SET, aclv_count, aclv_entries);
+      if (ret < 0 && saved_errno == 0)
+        {
+          saved_errno = errno;
+          if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
+            {
+              if (!aclv_nontrivial (aclv_count, aclv_entries))
+                saved_errno = 0;
+            }
+        }
+      else
+        did_chmod = 1;
+    }
+# endif
+
+  if (did_chmod <= ((mode & (S_ISUID | S_ISGID | S_ISVTX)) ? 1 : 0))
+    {
+      /* We did not call chmod so far, and special bits are to be set which
+         don't fit into ACLs.  */
+
+      if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
+        {
+          if (saved_errno == 0)
+            saved_errno = errno;
+        }
+    }
+
+  if (saved_errno)
+    {
+      errno = saved_errno;
+      return -1;
     }
   return 0;
 
index 03decf4..3d4d5c1 100644 (file)
@@ -234,6 +234,33 @@ acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb)
   return 0;
 }
 
+# if HAVE_ACLV_H /* HP-UX >= 11.11 */
+
+/* Return 1 if the given ACL is non-trivial.
+   Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
+int
+aclv_nontrivial (int count, struct acl *entries)
+{
+  int i;
+
+  for (i = 0; i < count; i++)
+    {
+      struct acl *ace = &entries[i];
+
+      /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
+         If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
+         We don't need to check ace->a_id in these cases.  */
+      if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
+            || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
+            || ace->a_type == CLASS_OBJ
+            || ace->a_type == OTHER_OBJ))
+        return 1;
+    }
+  return 0;
+}
+
+# endif
+
 #elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
 
 /* Return 1 if the given ACL is non-trivial.
@@ -519,11 +546,11 @@ file_has_acl (char const *name, struct stat const *sb)
 
 # elif HAVE_GETACL /* HP-UX */
 
-      int count;
-      struct acl_entry entries[NACLENTRIES];
-
       for (;;)
         {
+          int count;
+          struct acl_entry entries[NACLENTRIES];
+
           count = getacl (name, 0, NULL);
 
           if (count < 0)
@@ -532,7 +559,7 @@ file_has_acl (char const *name, struct stat const *sb)
                  EOPNOTSUPP is typically seen on NFS mounts.
                  ENOTSUP was seen on Quantum StorNext file systems (cvfs).  */
               if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
-                return 0;
+                break;
               else
                 return -1;
             }
@@ -563,6 +590,46 @@ file_has_acl (char const *name, struct stat const *sb)
              Repeat.  */
         }
 
+#  if HAVE_ACLV_H /* HP-UX >= 11.11 */
+
+      for (;;)
+        {
+          int count;
+          struct acl entries[NACLVENTRIES];
+
+          count = acl ((char *) name, ACL_CNT, NACLVENTRIES, entries);
+
+          if (count < 0)
+            {
+              /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
+                 EINVAL is seen on NFS in HP-UX 11.31.  */
+              if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
+                break;
+              else
+                return -1;
+            }
+
+          if (count == 0)
+            return 0;
+
+          if (count > NACLVENTRIES)
+            /* If NACLVENTRIES cannot be trusted, use dynamic memory
+               allocation.  */
+            abort ();
+
+          /* If there are more than 4 entries, there cannot be only the
+             four base ACL entries.  */
+          if (count > 4)
+            return 1;
+
+          if (acl ((char *) name, ACL_GET, count, entries) == count)
+            return aclv_nontrivial (count, entries);
+          /* Huh? The number of ACL entries changed since the last call.
+             Repeat.  */
+        }
+
+#  endif
+
 # elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
 
       acl_type_t type;
index 1392378..5ba86a5 100644 (file)
@@ -406,7 +406,6 @@ qset_acl (char const *name, int desc, mode_t mode)
 # elif HAVE_GETACL /* HP-UX */
 
   struct stat statbuf;
-  struct acl_entry entries[3];
   int ret;
 
   if (desc != -1)
@@ -416,25 +415,68 @@ qset_acl (char const *name, int desc, mode_t mode)
   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;
+  {
+    struct acl_entry entries[3];
+
+    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 (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 || errno == ENOTSUP)
-        return chmod_or_fchmod (name, desc, mode);
-      return -1;
+      if (!(errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP))
+        return -1;
+
+#  if HAVE_ACLV_H /* HP-UX >= 11.11 */
+      {
+        struct acl entries[4];
+
+        entries[0].a_type = USER_OBJ;
+        entries[0].a_id = 0; /* irrelevant */
+        entries[0].a_perm = (mode >> 6) & 7;
+        entries[1].a_type = GROUP_OBJ;
+        entries[1].a_id = 0; /* irrelevant */
+        entries[1].a_perm = (mode >> 3) & 7;
+        entries[2].a_type = CLASS_OBJ;
+        entries[2].a_id = 0;
+        entries[2].a_perm = (mode >> 3) & 7;
+        entries[3].a_type = OTHER_OBJ;
+        entries[3].a_id = 0;
+        entries[3].a_perm = mode & 7;
+
+        ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries);
+        if (ret > 0)
+          abort ();
+        if (ret < 0)
+          {
+            if (0)
+              return chmod_or_fchmod (name, desc, mode);
+            return -1;
+          }
+
+        ret = acl ((char *) name, ACL_SET,
+                   sizeof (entries) / sizeof (struct acl), entries);
+        if (ret < 0)
+          {
+            if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
+              return chmod_or_fchmod (name, desc, mode);
+            return -1;
+          }
+      }
+#  else
+      return chmod_or_fchmod (name, desc, mode);
+#  endif
     }
 
   if (mode & (S_ISUID | S_ISGID | S_ISVTX))
index a01382d..d6a448a 100644 (file)
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -1,5 +1,5 @@
 # acl.m4 - check for access control list (ACL) primitives
-# serial 12
+# serial 13
 
 # Copyright (C) 2002, 2004-2011 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -94,6 +94,8 @@ int type = ACL_TYPE_EXTENDED;]])],
         if test $ac_cv_func_getacl = yes; then
           use_acl=1
         fi
+        dnl Test for HP-UX 11.11 API.
+        AC_CHECK_HEADERS([aclv.h], [], [], [#include <sys/types.h>])
       fi
 
       dnl Test for AIX API (AIX 5.3 or newer).
index 1452c80..4111bbc 100755 (executable)
@@ -60,7 +60,7 @@ cd "$builddir" ||
   # Classification of the platform according to the programs available for
   # manipulating ACLs.
   # Possible values are:
-  #   linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none.
+  #   linux, cygwin, freebsd, solaris, hpux, hpuxjfs, osf1, aix, macosx, irix, none.
   # TODO: Support also native Win32 platforms (mingw).
   acl_flavor=none
   if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then
@@ -88,7 +88,13 @@ cd "$builddir" ||
     if (lsacl / >/dev/null) 2>/dev/null; then
       # Platforms with the lsacl and chacl programs.
       # HP-UX, sometimes also IRIX.
-      acl_flavor=hpux
+      if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
+        # HP-UX 11.11 or newer.
+        acl_flavor=hpuxjfs
+      else
+        # HP-UX 11.00.
+        acl_flavor=hpux
+      fi
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
         # Tru64, NonStop Kernel.
@@ -138,6 +144,19 @@ cd "$builddir" ||
         cmp tmpaclout1 tmpaclout2 > /dev/null
       }
       ;;
+    hpuxjfs)
+      func_test_same_acls ()
+      {
+        { lsacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
+          lsacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2
+          cmp tmpaclout1 tmpaclout2 > /dev/null
+        } &&
+        { getacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
+          getacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2
+          cmp tmpaclout1 tmpaclout2 > /dev/null
+        }
+      }
+      ;;
     osf1 | nsk)
       func_test_same_acls ()
       {
@@ -366,6 +385,62 @@ cd "$builddir" ||
 
         ;;
 
+      hpuxjfs)
+
+        # Set an ACL for a user.
+        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+        chacl -r "${orig}($auid.%,--x)" tmpfile0 \
+          || setacl -m user:$auid:1 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile2
+
+        # Set an ACL for a group.
+        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+        chacl -r "${orig}(%.$agid,r--)" tmpfile0 \
+          || setacl -m group:$agid:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile3
+
+        # Set an ACL for other.
+        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+        chacl -r "${orig}(%.%,r--)" tmpfile0 \
+          || setacl -m other:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile4
+
+        # Remove the ACL for the user.
+        chacl -d "($auid.%,--x)" tmpfile0 \
+          || setacl -d user:$auid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile5
+
+        # Remove the ACL for the group.
+        chacl -d "(%.$agid,r--)" tmpfile0 \
+          || setacl -d group:$agid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile6
+
+        # Delete all optional ACLs.
+        chacl -z tmpfile0 \
+          || { setacl -m user:$auid:1 tmpfile0
+               setacl -s user::6,group::0,class:7,other:0 tmpfile0
+             }
+
+        func_test_copy tmpfile0 tmpfile8
+
+        # Copy ACLs from a file that has no ACLs.
+        echo > tmpfile9
+        chmod a+x tmpfile9
+        orig=`lsacl tmpfile9 | sed -e 's/ tmpfile9$//'`
+        getacl tmpfile9 > tmpaclout0
+        rm -f tmpfile9
+        chacl -r "${orig}" tmpfile0 \
+          || setacl -f tmpaclout0 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile9
+
+        ;;
+
       osf1)
 
         # Set an ACL for a user.
index c63f380..fecf9bc 100755 (executable)
@@ -54,7 +54,7 @@ cd "$builddir" ||
   # Classification of the platform according to the programs available for
   # manipulating ACLs.
   # Possible values are:
-  #   linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none.
+  #   linux, cygwin, freebsd, solaris, hpux, hpuxjfs, osf1, aix, macosx, irix, none.
   # TODO: Support also native Win32 platforms (mingw).
   acl_flavor=none
   if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then
@@ -82,7 +82,13 @@ cd "$builddir" ||
     if (lsacl / >/dev/null) 2>/dev/null; then
       # Platforms with the lsacl and chacl programs.
       # HP-UX, sometimes also IRIX.
-      acl_flavor=hpux
+      if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
+        # HP-UX 11.11 or newer.
+        acl_flavor=hpuxjfs
+      else
+        # HP-UX 11.00.
+        acl_flavor=hpux
+      fi
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
         # Tru64, NonStop Kernel.
@@ -132,6 +138,19 @@ cd "$builddir" ||
         cmp tmpaclout1 tmpaclout2 > /dev/null
       }
       ;;
+    hpuxjfs)
+      func_test_same_acls ()
+      {
+        { lsacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
+          lsacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2
+          cmp tmpaclout1 tmpaclout2 > /dev/null
+        } &&
+        { getacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
+          getacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2
+          cmp tmpaclout1 tmpaclout2 > /dev/null
+        }
+      }
+      ;;
     osf1 | nsk)
       func_test_same_acls ()
       {
@@ -360,6 +379,62 @@ cd "$builddir" ||
 
         ;;
 
+      hpuxjfs)
+
+        # Set an ACL for a user.
+        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+        chacl -r "${orig}($auid.%,--x)" tmpfile0 \
+          || setacl -m user:$auid:1 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile2
+
+        # Set an ACL for a group.
+        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+        chacl -r "${orig}(%.$agid,r--)" tmpfile0 \
+          || setacl -m group:$agid:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile3
+
+        # Set an ACL for other.
+        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+        chacl -r "${orig}(%.%,r--)" tmpfile0 \
+          || setacl -m other:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile4
+
+        # Remove the ACL for the user.
+        chacl -d "($auid.%,--x)" tmpfile0 \
+          || setacl -d user:$auid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile5
+
+        # Remove the ACL for the group.
+        chacl -d "(%.$agid,r--)" tmpfile0 \
+          || setacl -d group:$agid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile6
+
+        # Delete all optional ACLs.
+        chacl -z tmpfile0 \
+          || { setacl -m user:$auid:1 tmpfile0
+               setacl -s user::6,group::0,class:7,other:0 tmpfile0
+             }
+
+        func_test_copy tmpfile0 tmpfile8
+
+        # Copy ACLs from a file that has no ACLs.
+        echo > tmpfile9
+        chmod a+x tmpfile9
+        orig=`lsacl tmpfile9 | sed -e 's/ tmpfile9$//'`
+        getacl tmpfile9 > tmpaclout0
+        rm -f tmpfile9
+        chacl -r "${orig}" tmpfile0 \
+          || setacl -f tmpaclout0 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile9
+
+        ;;
+
       osf1)
 
         # Set an ACL for a user.
index 3f49e8d..053246a 100755 (executable)
@@ -60,7 +60,7 @@ cd "$builddir" ||
   # Classification of the platform according to the programs available for
   # manipulating ACLs.
   # Possible values are:
-  #   linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none.
+  #   linux, cygwin, freebsd, solaris, hpux, hpuxjfs, osf1, aix, macosx, irix, none.
   # TODO: Support also native Win32 platforms (mingw).
   acl_flavor=none
   if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then
@@ -88,7 +88,13 @@ cd "$builddir" ||
     if (lsacl / >/dev/null) 2>/dev/null; then
       # Platforms with the lsacl and chacl programs.
       # HP-UX, sometimes also IRIX.
-      acl_flavor=hpux
+      if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
+        # HP-UX 11.11 or newer.
+        acl_flavor=hpuxjfs
+      else
+        # HP-UX 11.00.
+        acl_flavor=hpux
+      fi
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
         # Tru64, NonStop Kernel.
@@ -256,7 +262,7 @@ cd "$builddir" ||
         fi
         ;;
 
-      hpux)
+      hpux | hpuxjfs)
 
         # Set an ACL for a user.
         orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
@@ -269,6 +275,20 @@ cd "$builddir" ||
 
           func_test_has_acl tmpfile0 no
 
+        else
+          if test $acl_flavor = hpuxjfs; then
+
+            # Set an ACL for a user.
+            setacl -m user:$auid:1 tmpfile0
+
+            func_test_has_acl tmpfile0 yes
+
+            # Remove the ACL for the user.
+            setacl -d user:$auid tmpfile0
+
+            func_test_has_acl tmpfile0 no
+
+          fi
         fi
         ;;
 
index 661a926..3fafa3c 100644 (file)
 # include <sys/types.h>
 # include <sys/acl.h>
 #endif
+#if HAVE_ACLV_H
+# include <sys/types.h>
+# include <aclv.h>
+#endif
 
 #include "progname.h"
 #include "read-file.h"
@@ -426,6 +430,80 @@ main (int argc, char *argv[])
             }
         }
     }
+
+# if HAVE_ACLV_H /* HP-UX >= 11.11 */
+  {
+    struct acl dummy_entries[NACLVENTRIES];
+
+    count1 = acl ((char *) file1, ACL_CNT, NACLVENTRIES, dummy_entries);
+    if (count1 < 0
+        && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL))
+      count1 = 0;
+    count2 = acl ((char *) file2, ACL_CNT, NACLVENTRIES, dummy_entries);
+    if (count2 < 0
+        && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL))
+      count2 = 0;
+  }
+
+  if (count1 < 0)
+    {
+      fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
+      fflush (stderr);
+      abort ();
+    }
+  if (count2 < 0)
+    {
+      fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
+      fflush (stderr);
+      abort ();
+    }
+  if (count1 != count2)
+    {
+      fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
+               file1, file2, count1, count2);
+      return 1;
+    }
+  else if (count1 > 0)
+    {
+      struct acl *entries1 = XNMALLOC (count1, struct acl);
+      struct acl *entries2 = XNMALLOC (count2, struct acl);
+      int i;
+
+      if (acl ((char *) file1, ACL_GET, count1, entries1) < count1)
+        {
+          fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
+          fflush (stderr);
+          abort ();
+        }
+      if (acl ((char *) file2, ACL_GET, count2, entries2) < count1)
+        {
+          fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
+          fflush (stderr);
+          abort ();
+        }
+      for (i = 0; i < count1; i++)
+        {
+          if (entries1[i].a_type != entries2[i].a_type)
+            {
+              fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n",
+                       file1, file2, i, entries1[i].a_type, entries2[i].a_type);
+              return 1;
+            }
+          if (entries1[i].a_id != entries2[i].a_id)
+            {
+              fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n",
+                       file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id);
+              return 1;
+            }
+          if (entries1[i].a_perm != entries2[i].a_perm)
+            {
+              fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
+                       file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm);
+              return 1;
+            }
+        }
+    }
+# endif
 #elif HAVE_ACLX_GET /* AIX */
   acl_type_t type1;
   char acl1[1000];
index 56fde29..24ce003 100755 (executable)
@@ -60,7 +60,7 @@ cd "$builddir" ||
   # Classification of the platform according to the programs available for
   # manipulating ACLs.
   # Possible values are:
-  #   linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none.
+  #   linux, cygwin, freebsd, solaris, hpux, hpuxjfs, osf1, aix, macosx, irix, none.
   # TODO: Support also native Win32 platforms (mingw).
   acl_flavor=none
   if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then
@@ -88,7 +88,13 @@ cd "$builddir" ||
     if (lsacl / >/dev/null) 2>/dev/null; then
       # Platforms with the lsacl and chacl programs.
       # HP-UX, sometimes also IRIX.
-      acl_flavor=hpux
+      if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
+        # HP-UX 11.11 or newer.
+        acl_flavor=hpuxjfs
+      else
+        # HP-UX 11.00.
+        acl_flavor=hpux
+      fi
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
         # Tru64, NonStop Kernel.
@@ -178,6 +184,11 @@ cd "$builddir" ||
             orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
             chacl -r "${orig}($auid.%,--x)" tmpfile0
             ;;
+          hpuxjfs)
+            orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
+            chacl -r "${orig}($auid.%,--x)" tmpfile0 \
+              || setacl -m user:$auid:1 tmpfile0
+            ;;
           osf1)
             setacl -u user:$auid:1 tmpfile0
             ;;