bug-gnulib
[Top][All Lists]
Advanced

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

RE: ACLs on HP NonStop


From: Schmitz, Joachim
Subject: RE: ACLs on HP NonStop
Date: Mon, 5 Sep 2011 15:19:19 +0000

Hi Bruno

I know, it's been a while... but I think I found a problem in ACL support for 
NonStop. There are file systems and OS version that don't support them, and 
gnu-lib code thows an error for these. The code I'm referring to is in 
file-has-acl.c and goes like this:

…
# elif HAVE_ACLSORT /* NonStop Kernel */

      int count;
      struct acl entries[NACLENTRIES];

      for (;;)
        {
          count = acl ((char *) name, ACL_CNT, NACLENTRIES, NULL);

          if (count < 0)
            return -1;

          if (count == 0)
            return 0;
…

I think this could/should get changed to the following (which is very similar 
to how HPUX does it):

…
# elif HAVE_ACLSORT /* NonStop Kernel */

      int count;
      struct acl entries[NACLENTRIES];

      for (;;)
        {
          count = acl ((char *) name, ACL_CNT, NACLENTRIES, NULL);

          if (count < 0)
            return (errno == ENOSYS || errno == ENOTSUP ? 0 : -1);

          if (count == 0)
            return 0;
…

What do you think? Not too sure whether this is the only change we need though.

Bye, Jojo
-----Original Message-----
From: Bruno Haible [mailto:address@hidden 
Sent: Sunday, October 03, 2010 6:05 PM
To: Schmitz, Joachim
Cc: 'Paolo Bonzini'; 'bug-gnulib'
Subject: Re: ACLs on HP NonStop

Joachim Schmitz wrote:
> Ah, now I see, 'class' is mandatory, so we'd need
>  
> setacl -s user::6,group::0,class:0,other:0 tmpfile0

Good. I'll use class:7 instead of class:0, since this is more realistic.

> and that indeed works:

Great! I'm thus committing the ACL support.


2010-10-03  Bruno Haible  <address@hidden>
            Joachim Schmitz  <address@hidden>  (tiny change)

        acl: Add support for ACLs on NonStop Kernel.
        * m4/acl.m4 (gl_FUNC_ACL): For Solaris, test for facl(), not for acl().
        Check whether the function aclsort() exists.
        * lib/acl-internal.h: For Solaris, test HAVE_FACL, not HAVE_ACL.
        (acl_nontrivial) [HAVE_ACLSORT]: New declaration.
        * lib/file-has-acl.c: For Solaris, test HAVE_FACL, not HAVE_ACL.
        (acl_nontrivial [HAVE_ACLSORT]: New function.
        (file_has_acl): Implement for NonStop Kernel.
        * lib/set-mode-acl.c: For Solaris, test HAVE_FACL, not HAVE_ACL.
        (qset_acl): Implement for NonStop Kernel.
        * lib/copy-acl.c (qcopy_acl): Implement for NonStop Kernel.
        * tests/test-sameacls.c: For Solaris, test HAVE_FACL, not HAVE_ACL.
        (main): Implement for NonStop Kernel.
        * tests/test-file-has-acl.sh (acl_flavor): Set to 'nsk' on NonStop
        Kernel. Handle this flavor.
        * tests/test-set-mode-acl.sh: Likewise.
        * tests/test-copy-acl.sh: Likewise.
        * tests/test-copy-file.sh: Likewise.

--- lib/acl-internal.h.orig     Sun Oct  3 17:46:20 2010
+++ lib/acl-internal.h  Sun Oct  3 04:21:58 2010
@@ -26,7 +26,7 @@
 #if HAVE_SYS_ACL_H
 # include <sys/acl.h>
 #endif
-#if defined HAVE_ACL && ! defined GETACLCNT && defined ACL_CNT
+#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT
 # define GETACLCNT ACL_CNT
 #endif
 
@@ -158,7 +158,7 @@
 extern int acl_access_nontrivial (acl_t);
 #  endif
 
-# elif HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
 
 /* Set to 1 if a file's mode is implicit by the ACL.
    Set to 0 if a file's mode is stored independently from the ACL.  */
@@ -216,6 +216,12 @@
    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
 extern int acl_nontrivial (struct acl *a);
 
+# elif HAVE_ACLSORT /* NonStop Kernel */
+
+/* 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 *entries);
+
 # endif
 
 #endif
--- lib/copy-acl.c.orig Sun Oct  3 17:46:20 2010
+++ lib/copy-acl.c      Sun Oct  3 14:40:31 2010
@@ -516,6 +516,68 @@
 
   return 0;
 
+#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
+
+  int count;
+  struct acl entries[NACLENTRIES];
+  int ret;
+
+  for (;;)
+    {
+      count = acl ((char *) src_name, ACL_CNT, NACLENTRIES, NULL);
+
+      if (count < 0)
+        {
+          if (0)
+            {
+              count = 0;
+              break;
+            }
+          else
+            return -2;
+        }
+
+      if (count == 0)
+        break;
+
+      if (count > NACLENTRIES)
+        /* If NACLENTRIES cannot be trusted, use dynamic memory allocation.  */
+        abort ();
+
+      if (acl ((char *) src_name, ACL_GET, 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 = acl ((char *) dst_name, ACL_SET, count, entries);
+  if (ret < 0)
+    {
+      int saved_errno = errno;
+
+      if (0)
+        {
+          if (!acl_nontrivial (count, entries))
+            return chmod_or_fchmod (dst_name, dest_desc, mode);
+        }
+
+      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);
--- lib/file-has-acl.c.orig     Sun Oct  3 17:46:20 2010
+++ lib/file-has-acl.c  Sun Oct  3 14:41:54 2010
@@ -118,7 +118,7 @@
 # endif
 
 
-#elif USE_ACL && HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
 
 # if !defined ACL_NO_TRIVIAL /* Solaris <= 10, Cygwin */
 
@@ -294,6 +294,32 @@
 
 # endif
 
+#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
+
+/* Test an ACL retrieved with ACL_GET.
+   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.  */
+int
+acl_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
 
 
@@ -377,7 +403,7 @@
         return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
       return ret;
 
-# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
+# elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
 
 #  if defined ACL_NO_TRIVIAL
 
@@ -598,6 +624,37 @@
 
       return acl_nontrivial (&u.a);
 
+# elif HAVE_ACLSORT /* NonStop Kernel */
+
+      int count;
+      struct acl entries[NACLENTRIES];
+
+      for (;;)
+        {
+          count = acl ((char *) name, ACL_CNT, NACLENTRIES, NULL);
+
+          if (count < 0)
+            return -1;
+
+          if (count == 0)
+            return 0;
+
+          if (count > NACLENTRIES)
+            /* If NACLENTRIES 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 acl_nontrivial (count, entries);
+          /* Huh? The number of ACL entries changed since the last call.
+             Repeat.  */
+        }
+
 # endif
     }
 #endif
--- lib/set-mode-acl.c.orig     Sun Oct  3 17:46:20 2010
+++ lib/set-mode-acl.c  Sun Oct  3 03:34:20 2010
@@ -201,7 +201,7 @@
   return chmod_or_fchmod (name, desc, mode);
 #  endif
 
-# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
+# elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */
 
 #  if defined ACL_NO_TRIVIAL
   /* Solaris 10 (newer version), which has additional API declared in
@@ -573,6 +573,51 @@
 
   return ret;
 
+# elif HAVE_ACLSORT /* NonStop Kernel */
+
+  struct acl entries[4];
+  int ret;
+
+  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 (0)
+        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
--- m4/acl.m4.orig      Sun Oct  3 17:46:20 2010
+++ m4/acl.m4   Sat Oct  2 18:05:22 2010
@@ -1,5 +1,5 @@
 # acl.m4 - check for access control list (ACL) primitives
-# serial 10
+# serial 11
 
 # Copyright (C) 2002, 2004-2010 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -76,8 +76,8 @@
 
       dnl Test for Solaris API (Solaris, Cygwin).
       if test $use_acl = 0; then
-        AC_CHECK_FUNCS([acl])
-        if test $ac_cv_func_acl = yes; then
+        AC_CHECK_FUNCS([facl])
+        if test $ac_cv_func_facl = yes; then
           AC_SEARCH_LIBS([acl_trivial], [sec],
             [if test "$ac_cv_search_acl_trivial" != "none required"; then
                LIB_ACL=$ac_cv_search_acl_trivial
@@ -89,7 +89,7 @@
       fi
 
       dnl Test for HP-UX API.
-      if test $use_acl = 0 || test "$ac_cv_func_acl" = yes; then
+      if test $use_acl = 0; then
         AC_CHECK_FUNCS([getacl])
         if test $ac_cv_func_getacl = yes; then
           use_acl=1
@@ -111,6 +111,14 @@
           use_acl=1
         fi
       fi
+
+      dnl Test for NonStop Kernel API.
+      if test $use_acl = 0; then
+        AC_CHECK_FUNCS([aclsort])
+        if test $ac_cv_func_aclsort = yes; then
+          use_acl=1
+        fi
+      fi
 
       LIBS=$ac_save_LIBS
     fi
--- tests/test-copy-acl.sh.orig Sun Oct  3 17:46:20 2010
+++ tests/test-copy-acl.sh      Sun Oct  3 17:45:09 2010
@@ -91,8 +91,14 @@
       acl_flavor=hpux
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
-        # Tru64.
-        acl_flavor=osf1
+        # Tru64, NonStop Kernel.
+        if (getacl -m tmpfile0 >/dev/null) 2>/dev/null; then
+          # Tru64.
+          acl_flavor=osf1
+        else
+          # NonStop Kernel.
+          acl_flavor=nsk
+        fi
       else
         if (aclget tmpfile0 >/dev/null) 2>/dev/null; then
           # AIX.
@@ -132,7 +138,7 @@
         cmp tmpaclout1 tmpaclout2 > /dev/null
       }
       ;;
-    osf1)
+    osf1 | nsk)
       func_test_same_acls ()
       {
         getacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
@@ -408,6 +414,50 @@
         rm -f tmpfile9
 
         func_test_copy tmpfile0 tmpfile9
+
+        ;;
+
+      nsk)
+
+        # Set an ACL for a user.
+        setacl -m user:$auid:1 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile2
+
+        # Set an ACL for a group.
+        setacl -m group:$agid:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile3
+
+        # Set an ACL for other.
+        setacl -m other:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile4
+
+        # Remove the ACL for the user.
+        setacl -d user:$auid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile5
+
+        # Remove the ACL for the group.
+        setacl -d group:$agid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile6
+
+        # Delete all optional ACLs.
+        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
+        getacl tmpfile9 > tmpaclout0
+        setacl -f tmpaclout0 tmpfile0
+        rm -f tmpfile9
+
+        func_test_copy tmpfile0 tmpfile9
 
         ;;
 
--- tests/test-copy-file.sh.orig        Sun Oct  3 17:46:20 2010
+++ tests/test-copy-file.sh     Sun Oct  3 17:45:09 2010
@@ -85,8 +85,14 @@
       acl_flavor=hpux
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
-        # Tru64.
-        acl_flavor=osf1
+        # Tru64, NonStop Kernel.
+        if (getacl -m tmpfile0 >/dev/null) 2>/dev/null; then
+          # Tru64.
+          acl_flavor=osf1
+        else
+          # NonStop Kernel.
+          acl_flavor=nsk
+        fi
       else
         if (aclget tmpfile0 >/dev/null) 2>/dev/null; then
           # AIX.
@@ -126,7 +132,7 @@
         cmp tmpaclout1 tmpaclout2 > /dev/null
       }
       ;;
-    osf1)
+    osf1 | nsk)
       func_test_same_acls ()
       {
         getacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1
@@ -402,6 +408,50 @@
         rm -f tmpfile9
 
         func_test_copy tmpfile0 tmpfile9
+
+        ;;
+
+      nsk)
+
+        # Set an ACL for a user.
+        setacl -m user:$auid:1 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile2
+
+        # Set an ACL for a group.
+        setacl -m group:$agid:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile3
+
+        # Set an ACL for other.
+        setacl -m other:4 tmpfile0
+
+        func_test_copy tmpfile0 tmpfile4
+
+        # Remove the ACL for the user.
+        setacl -d user:$auid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile5
+
+        # Remove the ACL for the group.
+        setacl -d group:$agid tmpfile0
+
+        func_test_copy tmpfile0 tmpfile6
+
+        # Delete all optional ACLs.
+        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
+        getacl tmpfile9 > tmpaclout0
+        setacl -f tmpaclout0 tmpfile0
+        rm -f tmpfile9
+
+        func_test_copy tmpfile0 tmpfile9
 
         ;;
 
--- tests/test-file-has-acl.sh.orig     Sun Oct  3 17:46:21 2010
+++ tests/test-file-has-acl.sh  Sun Oct  3 12:49:38 2010
@@ -91,8 +91,14 @@
       acl_flavor=hpux
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
-        # Tru64.
-        acl_flavor=osf1
+        # Tru64, NonStop Kernel.
+        if (getacl -m tmpfile0 >/dev/null) 2>/dev/null; then
+          # Tru64.
+          acl_flavor=osf1
+        else
+          # NonStop Kernel.
+          acl_flavor=nsk
+        fi
       else
         if (aclget tmpfile0 >/dev/null) 2>/dev/null; then
           # AIX.
@@ -286,6 +292,20 @@
         fi
         ;;
 
+      nsk)
+
+        # 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
+
+        ;;
+
       aix)
 
         # Set an ACL for a user.
--- tests/test-sameacls.c.orig  Sun Oct  3 17:46:21 2010
+++ tests/test-sameacls.c       Sun Oct  3 14:39:37 2010
@@ -24,7 +24,7 @@
 #include <string.h>
 #include <sys/stat.h>
 
-#if HAVE_ACL_GET_FILE || HAVE_ACL || HAVE_ACLX_GET || HAVE_STATACL
+#if HAVE_ACL_GET_FILE || HAVE_FACL || HAVE_ACLX_GET || HAVE_STATACL || 
HAVE_ACLSORT
 # include <sys/types.h>
 # include <sys/acl.h>
 #endif
@@ -218,7 +218,7 @@
               }
           }
       }
-#elif HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+#elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
   int count1;
   int count2;
 
@@ -520,6 +520,71 @@
                file1, file2);
       return 1;
     }
+#elif HAVE_ACLSORT /* NonStop Kernel */
+  int count1;
+  int count2;
+
+  count1 = acl ((char *) file1, ACL_CNT, NACLENTRIES, NULL);
+  count2 = acl ((char *) file2, ACL_CNT, NACLENTRIES, NULL);
+
+  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
   }
 
--- tests/test-set-mode-acl.sh.orig     Sun Oct  3 17:46:21 2010
+++ tests/test-set-mode-acl.sh  Sun Oct  3 12:50:21 2010
@@ -91,8 +91,14 @@
       acl_flavor=hpux
     else
       if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
-        # Tru64.
-        acl_flavor=osf1
+        # Tru64, NonStop Kernel.
+        if (getacl -m tmpfile0 >/dev/null) 2>/dev/null; then
+          # Tru64.
+          acl_flavor=osf1
+        else
+          # NonStop Kernel.
+          acl_flavor=nsk
+        fi
       else
         if (aclget tmpfile0 >/dev/null) 2>/dev/null; then
           # AIX.
@@ -175,6 +181,9 @@
           osf1)
             setacl -u user:$auid:1 tmpfile0
             ;;
+          nsk)
+            setacl -m user:$auid:1 tmpfile0
+            ;;
           aix)
             { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo "        
permit --x u:$auid"; } | aclput tmpfile0
             ;;

reply via email to

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