bug-gnulib
[Top][All Lists]
Advanced

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

Re: ACLs on HP NonStop


From: Bruno Haible
Subject: Re: ACLs on HP NonStop
Date: Sun, 3 Oct 2010 04:33:45 +0200
User-agent: KMail/1.9.9

Hi Joachim,

> Attached my patches so far...
> ...
>    ../gllib/libgnu.a(set-mode-acl.o): In function `qset_acl':
>    set-mode-acl.o(.text._148712224+0x202): unresolved reference to facl.

This needs another approach. The test in gl_FUNC_ACL and the code in
lib/acl-internal.h use different code for each platform, because each
platform has its own idiosyncratic ACL related APIs. You tried to map
the NonStop API to Solaris/Cygwin API, and that failed. So I would
suggest to create a new code path for NonStop in these files.

Similarly, in the test suite files
  tests/test-file-has-acl.sh
  tests/test-set-mode-acl.sh
  tests/test-copy-acl.sh
  tests/test-copy-file.sh
a similar dispatch is made according to the shell commands that can
be used to set and edit ACLs.

To progress on this:

1) The C API: You provided us the necessary documentation and excepts from
   <sys/acl.h>. Thanks.

2) The shell commands: Can you run
     $ VERBOSE=1 make check TESTS=test-file-has-acl.sh
   This should show which value the variable 'acl_flavor' gets, and which
   shell commands then succeed or fail.
   Maybe we to create separate code path for acl_flavor=nsk. This depends on
   how closely NSK implements the ACL related shell commands of some other
   platform.

3) When this is done, we can turn to the lib/*acl* part. Here a new code path
   appears to be needed. 

   I've created a new acltestdir.tar.gz for you at
   http://www.haible.de/bruno/gnu/acltestdir.tar.gz

   It contains the tentative patch attached below.

Bruno


--- lib/acl-internal.h.orig     Sun Oct  3 04:26:51 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 04:26:51 2010
+++ lib/copy-acl.c      Sun Oct  3 04:25:58 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 *) 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 04:26:51 2010
+++ lib/file-has-acl.c  Sun Oct  3 03:07:12 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 */
 
@@ -292,6 +292,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
 
 #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 04:26:51 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 04:26:51 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-sameacls.c.orig  Sun Oct  3 04:26:51 2010
+++ tests/test-sameacls.c       Sat Oct  2 18:10:42 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
 # 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
   }
 



reply via email to

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